• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

options.h

Go to the documentation of this file.
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

Generated on Sun Feb 17 2013 02:35:45 for wibble by  doxygen 1.7.1