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 static bool init_val;
00022 };
00023
00024 struct Int
00025 {
00026 typedef int value_type;
00027 static int parse(const std::string& val);
00028
00029 static bool toBool(const value_type& val);
00030 static int toInt(const value_type& val);
00031 static std::string toString(const value_type& val);
00032 static int init_val;
00033 };
00034
00035 struct String
00036 {
00037 typedef std::string value_type;
00038 static std::string parse(const std::string& val);
00039
00040 static bool toBool(const value_type& val);
00041 static int toInt(const value_type& val);
00042 static std::string toString(const value_type& val);
00043 static std::string init_val;
00044 };
00045
00046 struct ExistingFile
00047 {
00048 typedef std::string value_type;
00049 static std::string parse(const std::string& val);
00050 static std::string toString(const value_type& val);
00051 static std::string init_val;
00052 };
00053
00055 class Option : public Managed
00056 {
00057 std::string m_name;
00058 mutable std::string m_fullUsage;
00059
00060 protected:
00061 bool m_isset;
00062
00063 Option(const std::string& name) : m_name(name), m_isset(false) {}
00064 Option(const std::string& name,
00065 char shortName,
00066 const std::string& longName,
00067 const std::string& usage = std::string(),
00068 const std::string& description = std::string())
00069 : m_name(name), m_isset(false), usage(usage), description(description)
00070 {
00071 if (shortName != 0)
00072 shortNames.push_back(shortName);
00073 if (!longName.empty())
00074 longNames.push_back(longName);
00075 }
00076
00088 virtual ArgList::iterator parse(ArgList& list, ArgList::iterator begin) = 0;
00089
00095 virtual bool parse(const std::string& param) = 0;
00096
00101 virtual void parse_noarg() = 0;
00102
00104 virtual bool arg_is_optional() const { return false; }
00105
00106 public:
00107 Option();
00108 virtual ~Option() {}
00109
00110 bool isSet() const { return m_isset; }
00111 const std::string& name() const { return m_name; }
00112
00113 void addAlias(char c) { shortNames.push_back(c); }
00114 void addAlias(const std::string& str) { longNames.push_back(str); }
00115
00117 const std::string& fullUsage() const;
00118 std::string fullUsageForMan() const;
00119
00120 std::vector<char> shortNames;
00121 std::vector<std::string> longNames;
00122
00123 std::string usage;
00124 std::string description;
00125
00126
00127 bool hidden;
00128
00129 friend class OptionGroup;
00130 friend class Engine;
00131 };
00132
00134 class BoolOption : public Option
00135 {
00136 bool m_value;
00137
00138 protected:
00139 BoolOption(const std::string& name)
00140 : Option(name), m_value(false) {}
00141 BoolOption(const std::string& name,
00142 char shortName,
00143 const std::string& longName,
00144 const std::string& usage = std::string(),
00145 const std::string& description = std::string())
00146 : Option(name, shortName, longName, usage, description), m_value(false) {}
00147
00148 virtual ArgList::iterator parse(ArgList&, ArgList::iterator begin) { parse_noarg(); return begin; }
00149 virtual bool parse(const std::string&) { parse_noarg(); return false; }
00150 virtual void parse_noarg() { m_isset = true; m_value = true; }
00151
00152 public:
00153 bool boolValue() const { return m_value; }
00154 std::string stringValue() const { return m_value ? "true" : "false"; }
00155
00156 friend class OptionGroup;
00157 friend class Engine;
00158 };
00159
00160 template<typename T>
00161 class SingleOption : public Option
00162 {
00163 protected:
00164 typename T::value_type m_value;
00165
00166 SingleOption(const std::string& name)
00167 : Option(name), m_value(T::init_val)
00168 {
00169 usage = "<val>";
00170 }
00171 SingleOption(const std::string& name,
00172 char shortName,
00173 const std::string& longName,
00174 const std::string& usage = std::string(),
00175 const std::string& description = std::string())
00176 : Option(name, shortName, longName, usage, description)
00177 {
00178 if (usage.empty())
00179 this->usage = "<val>";
00180 }
00181
00182 ArgList::iterator parse(ArgList& list, ArgList::iterator begin)
00183 {
00184 if (begin == list.end())
00185 throw exception::BadOption("option requires an argument");
00186 m_value = T::parse(*begin);
00187 m_isset = true;
00188
00189 return list.eraseAndAdvance(begin);
00190 }
00191 bool parse(const std::string& param)
00192 {
00193 m_value = T::parse(param);
00194 m_isset = true;
00195 return true;
00196 }
00197 void parse_noarg()
00198 {
00199 throw exception::BadOption("option requires an argument");
00200 }
00201
00202 public:
00203 void setValue( const typename T::value_type &a ) {
00204 m_value = a;
00205 }
00206
00207 typename T::value_type value() const { return m_value; }
00208
00209
00210 bool boolValue() const { return T::toBool(m_value); }
00211 int intValue() const { return T::toInt(m_value); }
00212 std::string stringValue() const { return T::toString(m_value); }
00213
00214 friend class OptionGroup;
00215 friend class Engine;
00216 };
00217
00224 template<typename T>
00225 class SingleOptvalOption : public Option
00226 {
00227 protected:
00228 typename T::value_type m_value;
00229 bool m_hasval;
00230
00231 SingleOptvalOption(const std::string& name)
00232 : Option(name)
00233 {
00234 usage = "<val>";
00235 }
00236 SingleOptvalOption(const std::string& name,
00237 char shortName,
00238 const std::string& longName,
00239 const std::string& usage = std::string(),
00240 const std::string& description = std::string())
00241 : Option(name, 0, longName, usage, description)
00242 {
00243 if (shortName != 0)
00244 throw wibble::exception::Consistency(
00245 "creating option " + name + " with optional value"
00246 "short options with optional values are not allowed");
00247 if (usage.empty())
00248 this->usage = "<val>";
00249 }
00250
00251 ArgList::iterator parse(ArgList& list, ArgList::iterator begin)
00252 {
00253 throw wibble::exception::Consistency(
00254 "parsing option with optional value"
00255 "short options with optional values are not allowed");
00256 }
00257 bool parse(const std::string& param)
00258 {
00259 m_value = T::parse(param);
00260 m_isset = true;
00261 m_hasval = true;
00262 return true;
00263 }
00264 void parse_noarg()
00265 {
00266 m_isset = true;
00267 m_hasval = false;
00268 }
00269
00270 virtual bool arg_is_optional() const { return true; }
00271
00272 public:
00273 bool hasValue() const { return m_hasval; }
00274
00275 void setValue( const typename T::value_type &a ) {
00276 m_value = a;
00277 }
00278
00279 typename T::value_type value() const { return m_value; }
00280
00281 friend class OptionGroup;
00282 friend class Engine;
00283 };
00284
00285
00286 typedef SingleOption<String> StringOption;
00287
00288
00289 typedef SingleOptvalOption<String> OptvalStringOption;
00290
00291
00292 typedef SingleOption<Int> IntOption;
00293
00294
00295 typedef SingleOptvalOption<Int> OptvalIntOption;
00296
00298 typedef SingleOption<ExistingFile> ExistingFileOption;
00299
00301 typedef SingleOptvalOption<ExistingFile> OptvalExistingFileOption;
00302
00303
00304
00305 template<typename T>
00306 class VectorOption : public Option
00307 {
00308 std::vector< typename T::value_type > m_values;
00309
00310 protected:
00311 VectorOption(const std::string& name)
00312 : Option(name)
00313 {
00314 usage = "<val>";
00315 }
00316 VectorOption(const std::string& name,
00317 char shortName,
00318 const std::string& longName,
00319 const std::string& usage = std::string(),
00320 const std::string& description = std::string())
00321 : Option(name, shortName, longName, usage, description)
00322 {
00323 if (usage.empty())
00324 this->usage = "<val>";
00325 }
00326
00327 ArgList::iterator parse(ArgList& list, ArgList::iterator begin)
00328 {
00329 if (begin == list.end())
00330 throw exception::BadOption("no string argument found");
00331 m_isset = true;
00332 m_values.push_back(T::parse(*begin));
00333
00334 return list.eraseAndAdvance(begin);
00335 }
00336 bool parse(const std::string& param)
00337 {
00338 m_isset = true;
00339 m_values.push_back(T::parse(param));
00340 return true;
00341 }
00342 void parse_noarg()
00343 {
00344 throw exception::BadOption("option requires an argument");
00345 }
00346
00347 public:
00348 bool boolValue() const { return !m_values.empty(); }
00349 const std::vector< typename T::value_type >& values() const { return m_values; }
00350
00351 friend class OptionGroup;
00352 friend class Engine;
00353 };
00354
00355
00359 class OptionGroup : public Managed
00360 {
00361 MemoryManager* m_manager;
00362
00363 protected:
00364 OptionGroup(MemoryManager* mman = 0, const std::string& description = std::string())
00365 : m_manager(mman), description(description), hidden(false) {}
00366
00367 public:
00368 Option* add(Option* o) { options.push_back(o); return o; }
00369
00370 std::vector<Option*> options;
00371
00372 std::string description;
00373
00374
00375 bool hidden;
00376
00380 template<typename T>
00381 T* create(const std::string& name,
00382 char shortName,
00383 const std::string& longName,
00384 const std::string& usage = std::string(),
00385 const std::string& description = std::string())
00386 {
00387 T* item = new T(name, shortName, longName, usage, description);
00388 if (m_manager) m_manager->add(item);
00389 return item;
00390 }
00391
00395 template<typename T>
00396 T* add(const std::string& name,
00397 char shortName,
00398 const std::string& longName,
00399 const std::string& usage = std::string(),
00400 const std::string& description = std::string())
00401 {
00402 T* res = create<T>(name, shortName, longName, usage, description);
00403 add(res);
00404 return res;
00405 }
00406
00407 friend class Engine;
00408 };
00409
00410 }
00411 }
00412
00413
00414 #endif