00001 #ifndef WIBBLE_COMMANDLINE_OPTIONS_H
00002 #define WIBBLE_COMMANDLINE_OPTIONS_H
00003
00004 #include <wibble/commandline/core.h>
00005 #include <string>
00006 #include <vector>
00007
00008 namespace wibble {
00009 namespace commandline {
00010
00011
00012
00013 struct Bool
00014 {
00015 typedef bool value_type;
00016 static bool parse(const std::string& val);
00017
00018 static bool toBool(const value_type& val);
00019 static int toInt(const value_type& val);
00020 static std::string toString(const value_type& val);
00021 };
00022
00023 struct Int
00024 {
00025 typedef int value_type;
00026 static int parse(const std::string& val);
00027
00028 static bool toBool(const value_type& val);
00029 static int toInt(const value_type& val);
00030 static std::string toString(const value_type& val);
00031 };
00032
00033 struct String
00034 {
00035 typedef std::string value_type;
00036 static std::string parse(const std::string& val);
00037
00038 static bool toBool(const value_type& val);
00039 static int toInt(const value_type& val);
00040 static std::string toString(const value_type& val);
00041 };
00042
00043 struct ExistingFile
00044 {
00045 typedef std::string value_type;
00046 static std::string parse(const std::string& val);
00047 };
00048
00050 class Option : public Managed
00051 {
00052 std::string m_name;
00053 mutable std::string m_fullUsage;
00054
00055 protected:
00056 bool m_isset;
00057
00058 Option(const std::string& name) : m_name(name), m_isset(false) {}
00059 Option(const std::string& name,
00060 char shortName,
00061 const std::string& longName,
00062 const std::string& usage = std::string(),
00063 const std::string& description = std::string())
00064 : m_name(name), m_isset(false), usage(usage), description(description)
00065 {
00066 if (shortName != 0)
00067 shortNames.push_back(shortName);
00068 if (!longName.empty())
00069 longNames.push_back(longName);
00070 }
00071
00083 virtual ArgList::iterator parse(ArgList& list, ArgList::iterator begin) = 0;
00084
00090 virtual bool parse(const std::string& param) = 0;
00091
00092 public:
00093 virtual ~Option() {}
00094
00095 const bool isSet() const { return m_isset; }
00096 const std::string& name() const { return m_name; }
00097
00098 void addAlias(char c) { shortNames.push_back(c); }
00099 void addAlias(const std::string& str) { longNames.push_back(str); }
00100
00102 const std::string& fullUsage() const;
00103 std::string fullUsageForMan() const;
00104
00105 std::vector<char> shortNames;
00106 std::vector<std::string> longNames;
00107
00108 std::string usage;
00109 std::string description;
00110
00111 friend class OptionGroup;
00112 friend class Engine;
00113 };
00114
00116 class BoolOption : public Option
00117 {
00118 bool m_value;
00119
00120 protected:
00121 BoolOption(const std::string& name)
00122 : Option(name), m_value(false) {}
00123 BoolOption(const std::string& name,
00124 char shortName,
00125 const std::string& longName,
00126 const std::string& usage = std::string(),
00127 const std::string& description = std::string())
00128 : Option(name, shortName, longName, usage, description), m_value(false) {}
00129
00130 virtual ArgList::iterator parse(ArgList&, ArgList::iterator begin) { m_isset = true; m_value = true; return begin; }
00131 virtual bool parse(const std::string&) { m_isset = true; m_value = true; return false; }
00132
00133 public:
00134 bool boolValue() const { return m_value; }
00135 std::string stringValue() const { return m_value ? "true" : "false"; }
00136
00137 friend class OptionGroup;
00138 friend class Engine;
00139 };
00140
00141 template<typename T>
00142 class SingleOption : public Option
00143 {
00144 protected:
00145 typename T::value_type m_value;
00146
00147 SingleOption(const std::string& name)
00148 : Option(name)
00149 {
00150 usage = "<val>";
00151 }
00152 SingleOption(const std::string& name,
00153 char shortName,
00154 const std::string& longName,
00155 const std::string& usage = std::string(),
00156 const std::string& description = std::string())
00157 : Option(name, shortName, longName, usage, description)
00158 {
00159 if (usage.empty())
00160 this->usage = "<val>";
00161 }
00162
00163 ArgList::iterator parse(ArgList& list, ArgList::iterator begin)
00164 {
00165 if (begin == list.end())
00166 throw exception::BadOption("no string argument found");
00167 m_value = T::parse(*begin);
00168 m_isset = true;
00169
00170 return list.eraseAndAdvance(begin);
00171 }
00172 bool parse(const std::string& param)
00173 {
00174 m_value = T::parse(param);
00175 m_isset = true;
00176 return true;
00177 }
00178
00179 public:
00180 typename T::value_type value() const { return m_value; }
00181
00182
00183 bool boolValue() const { return T::toBool(m_value); }
00184 int intValue() const { return T::toInt(m_value); }
00185 std::string stringValue() const { return T::toString(m_value); }
00186
00187 friend class OptionGroup;
00188 friend class Engine;
00189 };
00190
00191
00192 typedef SingleOption<String> StringOption;
00193
00194
00195 struct IntOption : public SingleOption<Int>
00196 {
00197 protected:
00198 IntOption(const std::string& name) : SingleOption<Int>(name)
00199 {
00200 m_value = 0;
00201 }
00202 IntOption(const std::string& name,
00203 char shortName,
00204 const std::string& longName,
00205 const std::string& usage = std::string(),
00206 const std::string& description = std::string())
00207 : SingleOption<Int>(name, shortName, longName, usage, description)
00208 {
00209 m_value = 0;
00210 }
00211 public:
00212 friend class OptionGroup;
00213 friend class Engine;
00214 };
00215
00219 typedef SingleOption<ExistingFile> ExistingFileOption;
00220
00221
00222
00223 template<typename T>
00224 class VectorOption : public Option
00225 {
00226 std::vector< typename T::value_type > m_values;
00227
00228 protected:
00229 VectorOption(const std::string& name)
00230 : Option(name)
00231 {
00232 usage = "<val>";
00233 }
00234 VectorOption(const std::string& name,
00235 char shortName,
00236 const std::string& longName,
00237 const std::string& usage = std::string(),
00238 const std::string& description = std::string())
00239 : Option(name, shortName, longName, usage, description)
00240 {
00241 if (usage.empty())
00242 this->usage = "<val>";
00243 }
00244
00245 ArgList::iterator parse(ArgList& list, ArgList::iterator begin)
00246 {
00247 if (begin == list.end())
00248 throw exception::BadOption("no string argument found");
00249 m_isset = true;
00250 m_values.push_back(T::parse(*begin));
00251
00252 return list.eraseAndAdvance(begin);
00253 }
00254 bool parse(const std::string& param)
00255 {
00256 m_isset = true;
00257 m_values.push_back(T::parse(param));
00258 return true;
00259 }
00260
00261 public:
00262 bool boolValue() const { return !m_values.empty(); }
00263 const std::vector< typename T::value_type >& values() const { return m_values; }
00264
00265 friend class OptionGroup;
00266 friend class Engine;
00267 };
00268
00269
00273 class OptionGroup : public Managed
00274 {
00275 MemoryManager* m_manager;
00276
00277 protected:
00278 OptionGroup(MemoryManager* mman = 0, const std::string& description = std::string())
00279 : m_manager(mman), description(description) {}
00280
00281 public:
00282 Option* add(Option* o) { options.push_back(o); return o; }
00283
00284 std::vector<Option*> options;
00285
00286 std::string description;
00287
00291 template<typename T>
00292 T* create(const std::string& name,
00293 char shortName,
00294 const std::string& longName,
00295 const std::string& usage = std::string(),
00296 const std::string& description = std::string())
00297 {
00298 T* item = new T(name, shortName, longName, usage, description);
00299 if (m_manager) m_manager->add(item);
00300 return item;
00301 }
00302
00306 template<typename T>
00307 T* add(const std::string& name,
00308 char shortName,
00309 const std::string& longName,
00310 const std::string& usage = std::string(),
00311 const std::string& description = std::string())
00312 {
00313 T* res = create<T>(name, shortName, longName, usage, description);
00314 add(res);
00315 return res;
00316 }
00317
00318 friend class Engine;
00319 };
00320
00321 }
00322 }
00323
00324
00325 #endif