wibble
0.1.28
|
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 // Types of values for the command line options 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 // Set to true if the option should not be documented 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 // Remove the parsed element 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 // Deprecated 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 // Option needing a compulsory string value 00286 typedef SingleOption<String> StringOption; 00287 00288 // Option with an optional string value 00289 typedef SingleOptvalOption<String> OptvalStringOption; 00290 00291 // Option needing a compulsory int value 00292 typedef SingleOption<Int> IntOption; 00293 00294 // Option with an optional int value 00295 typedef SingleOptvalOption<Int> OptvalIntOption; 00296 00298 typedef SingleOption<ExistingFile> ExistingFileOption; 00299 00301 typedef SingleOptvalOption<ExistingFile> OptvalExistingFileOption; 00302 00303 00304 // Option that can be specified multiple times 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 // Remove the parsed element 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 // Set to true if the option group should not be documented 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 // vim:set ts=4 sw=4: 00414 #endif