lemon/arg_parser.h
changeset 213 56579d12575b
parent 204 77d56a21c3ab
child 214 60eecd3fe37a
equal deleted inserted replaced
7:110b85270adf 8:fe448abed4f5
     1 /* -*- C++ -*-
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     4  *
     5  * Copyright (C) 2003-2008
     5  * Copyright (C) 2003-2008
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     8  *
    39   ///\ingroup misc
    39   ///\ingroup misc
    40   ///Command line arguments parser.
    40   ///Command line arguments parser.
    41   ///
    41   ///
    42   ///For a complete example see the \ref arg_parser_demo.cc demo file.
    42   ///For a complete example see the \ref arg_parser_demo.cc demo file.
    43   class ArgParser {
    43   class ArgParser {
    44     
    44 
    45     static void _showHelp(void *p);
    45     static void _showHelp(void *p);
    46   protected:
    46   protected:
    47     
    47 
    48     int _argc;
    48     int _argc;
    49     const char **_argv;
    49     const char **_argv;
    50     
    50 
    51     enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
    51     enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
    52     
    52 
    53     class ParData {
    53     class ParData {
    54     public:
    54     public:
    55       union {
    55       union {
    56 	bool *bool_p;
    56         bool *bool_p;
    57 	int *int_p;
    57         int *int_p;
    58 	double *double_p;
    58         double *double_p;
    59 	std::string *string_p;
    59         std::string *string_p;
    60 	struct {
    60         struct {
    61 	  void (*p)(void *);
    61           void (*p)(void *);
    62 	  void *data;
    62           void *data;
    63 	} func_p;
    63         } func_p;
    64 	  
    64 
    65       };
    65       };
    66       std::string help;
    66       std::string help;
    67       bool mandatory;
    67       bool mandatory;
    68       OptType type;
    68       OptType type;
    69       bool set;
    69       bool set;
    70       bool ingroup;
    70       bool ingroup;
    71       bool has_syn;
    71       bool has_syn;
    72       bool syn;
    72       bool syn;
    73       bool self_delete;
    73       bool self_delete;
    74       ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
    74       ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
    75 		  has_syn(false), syn(false), self_delete(false) {}
    75                   has_syn(false), syn(false), self_delete(false) {}
    76     };
    76     };
    77 
    77 
    78     typedef std::map<std::string,ParData> Opts;
    78     typedef std::map<std::string,ParData> Opts;
    79     Opts _opts;
    79     Opts _opts;
    80 
    80 
    81     class GroupData 
    81     class GroupData
    82     {
    82     {
    83     public:
    83     public:
    84       typedef std::list<std::string> Opts;
    84       typedef std::list<std::string> Opts;
    85       Opts opts;
    85       Opts opts;
    86       bool only_one;
    86       bool only_one;
    87       bool mandatory;
    87       bool mandatory;
    88       GroupData() :only_one(false), mandatory(false) {}
    88       GroupData() :only_one(false), mandatory(false) {}
    89     };
    89     };
    90       
    90 
    91     typedef std::map<std::string,GroupData> Groups;
    91     typedef std::map<std::string,GroupData> Groups;
    92     Groups _groups;
    92     Groups _groups;
    93 
    93 
    94     struct OtherArg
    94     struct OtherArg
    95     {
    95     {
    96       std::string name;
    96       std::string name;
    97       std::string help;
    97       std::string help;
    98       OtherArg(std::string n, std::string h) :name(n), help(h) {}
    98       OtherArg(std::string n, std::string h) :name(n), help(h) {}
    99 
    99 
   100     };
   100     };
   101       
   101 
   102     std::vector<OtherArg> _others_help;
   102     std::vector<OtherArg> _others_help;
   103     std::vector<std::string> _file_args;
   103     std::vector<std::string> _file_args;
   104     std::string _command_name;
   104     std::string _command_name;
   105 
   105 
   106     
   106 
   107   private:
   107   private:
   108     //Bind a function to an option.
   108     //Bind a function to an option.
   109 
   109 
   110     //\param name The name of the option. The leading '-' must be omitted.
   110     //\param name The name of the option. The leading '-' must be omitted.
   111     //\param help A help string.
   111     //\param help A help string.
   112     //\retval func The function to be called when the option is given. It
   112     //\retval func The function to be called when the option is given. It
   113     //  must be of type "void f(void *)"
   113     //  must be of type "void f(void *)"
   114     //\param data Data to be passed to \c func
   114     //\param data Data to be passed to \c func
   115     ArgParser &funcOption(const std::string &name,
   115     ArgParser &funcOption(const std::string &name,
   116 		    const std::string &help,
   116                     const std::string &help,
   117 		    void (*func)(void *),void *data);
   117                     void (*func)(void *),void *data);
   118     
   118 
   119   public:
   119   public:
   120 
   120 
   121     ///Constructor
   121     ///Constructor
   122     ArgParser(int argc, const char **argv);
   122     ArgParser(int argc, const char **argv);
   123 
   123 
   134     ///\param name The name of the option. The leading '-' must be omitted.
   134     ///\param name The name of the option. The leading '-' must be omitted.
   135     ///\param help A help string.
   135     ///\param help A help string.
   136     ///\param value A default value for the option.
   136     ///\param value A default value for the option.
   137     ///\param obl Indicate if the option is mandatory.
   137     ///\param obl Indicate if the option is mandatory.
   138     ArgParser &intOption(const std::string &name,
   138     ArgParser &intOption(const std::string &name,
   139 		    const std::string &help,
   139                     const std::string &help,
   140 		    int value=0, bool obl=false);
   140                     int value=0, bool obl=false);
   141 
   141 
   142     ///Add a new floating point type option
   142     ///Add a new floating point type option
   143 
   143 
   144     ///Add a new floating point type option.
   144     ///Add a new floating point type option.
   145     ///\param name The name of the option. The leading '-' must be omitted.
   145     ///\param name The name of the option. The leading '-' must be omitted.
   146     ///\param help A help string.
   146     ///\param help A help string.
   147     ///\param value A default value for the option.
   147     ///\param value A default value for the option.
   148     ///\param obl Indicate if the option is mandatory.
   148     ///\param obl Indicate if the option is mandatory.
   149     ArgParser &doubleOption(const std::string &name,
   149     ArgParser &doubleOption(const std::string &name,
   150 		      const std::string &help,
   150                       const std::string &help,
   151 		      double value=0, bool obl=false);
   151                       double value=0, bool obl=false);
   152 
   152 
   153     ///Add a new bool type option
   153     ///Add a new bool type option
   154 
   154 
   155     ///Add a new bool type option.
   155     ///Add a new bool type option.
   156     ///\param name The name of the option. The leading '-' must be omitted.
   156     ///\param name The name of the option. The leading '-' must be omitted.
   157     ///\param help A help string.
   157     ///\param help A help string.
   158     ///\param value A default value for the option.
   158     ///\param value A default value for the option.
   159     ///\param obl Indicate if the option is mandatory.
   159     ///\param obl Indicate if the option is mandatory.
   160     ///\note A mandatory bool obtion is of very little use.
   160     ///\note A mandatory bool obtion is of very little use.
   161     ArgParser &boolOption(const std::string &name,
   161     ArgParser &boolOption(const std::string &name,
   162 		      const std::string &help,
   162                       const std::string &help,
   163 		      bool value=false, bool obl=false);
   163                       bool value=false, bool obl=false);
   164 
   164 
   165     ///Add a new string type option
   165     ///Add a new string type option
   166 
   166 
   167     ///Add a new string type option.
   167     ///Add a new string type option.
   168     ///\param name The name of the option. The leading '-' must be omitted.
   168     ///\param name The name of the option. The leading '-' must be omitted.
   169     ///\param help A help string.
   169     ///\param help A help string.
   170     ///\param value A default value for the option.
   170     ///\param value A default value for the option.
   171     ///\param obl Indicate if the option is mandatory.
   171     ///\param obl Indicate if the option is mandatory.
   172     ArgParser &stringOption(const std::string &name,
   172     ArgParser &stringOption(const std::string &name,
   173 		      const std::string &help,
   173                       const std::string &help,
   174 		      std::string value="", bool obl=false);
   174                       std::string value="", bool obl=false);
   175 
   175 
   176     ///Give help string for non-parsed arguments.
   176     ///Give help string for non-parsed arguments.
   177 
   177 
   178     ///With this function you can give help string for non-parsed arguments.
   178     ///With this function you can give help string for non-parsed arguments.
   179     ///The parameter \c name will be printed in the short usage line, while
   179     ///The parameter \c name will be printed in the short usage line, while
   180     ///\c help gives a more detailed description.
   180     ///\c help gives a more detailed description.
   181     ArgParser &other(const std::string &name,
   181     ArgParser &other(const std::string &name,
   182 		     const std::string &help="");
   182                      const std::string &help="");
   183     
   183 
   184     ///@}
   184     ///@}
   185 
   185 
   186     ///\name Options with External Storage
   186     ///\name Options with External Storage
   187     ///Using this functions, the value of the option will be directly written
   187     ///Using this functions, the value of the option will be directly written
   188     ///into a variable once the option appears in the command line.
   188     ///into a variable once the option appears in the command line.
   195     ///\param name The name of the option. The leading '-' must be omitted.
   195     ///\param name The name of the option. The leading '-' must be omitted.
   196     ///\param help A help string.
   196     ///\param help A help string.
   197     ///\param obl Indicate if the option is mandatory.
   197     ///\param obl Indicate if the option is mandatory.
   198     ///\retval ref The value of the argument will be written to this variable.
   198     ///\retval ref The value of the argument will be written to this variable.
   199     ArgParser &refOption(const std::string &name,
   199     ArgParser &refOption(const std::string &name,
   200 		    const std::string &help,
   200                     const std::string &help,
   201 		    int &ref, bool obl=false);
   201                     int &ref, bool obl=false);
   202 
   202 
   203     ///Add a new floating type option with a storage reference
   203     ///Add a new floating type option with a storage reference
   204 
   204 
   205     ///Add a new floating type option with a storage reference.
   205     ///Add a new floating type option with a storage reference.
   206     ///\param name The name of the option. The leading '-' must be omitted.
   206     ///\param name The name of the option. The leading '-' must be omitted.
   207     ///\param help A help string.
   207     ///\param help A help string.
   208     ///\param obl Indicate if the option is mandatory.
   208     ///\param obl Indicate if the option is mandatory.
   209     ///\retval ref The value of the argument will be written to this variable.
   209     ///\retval ref The value of the argument will be written to this variable.
   210     ArgParser &refOption(const std::string &name,
   210     ArgParser &refOption(const std::string &name,
   211 		      const std::string &help,
   211                       const std::string &help,
   212 		      double &ref, bool obl=false);
   212                       double &ref, bool obl=false);
   213 
   213 
   214     ///Add a new bool type option with a storage reference
   214     ///Add a new bool type option with a storage reference
   215 
   215 
   216     ///Add a new bool type option with a storage reference.
   216     ///Add a new bool type option with a storage reference.
   217     ///\param name The name of the option. The leading '-' must be omitted.
   217     ///\param name The name of the option. The leading '-' must be omitted.
   218     ///\param help A help string.
   218     ///\param help A help string.
   219     ///\param obl Indicate if the option is mandatory.
   219     ///\param obl Indicate if the option is mandatory.
   220     ///\retval ref The value of the argument will be written to this variable.
   220     ///\retval ref The value of the argument will be written to this variable.
   221     ///\note A mandatory bool obtion is of very little use.
   221     ///\note A mandatory bool obtion is of very little use.
   222     ArgParser &refOption(const std::string &name,
   222     ArgParser &refOption(const std::string &name,
   223 		      const std::string &help,
   223                       const std::string &help,
   224 		      bool &ref, bool obl=false);
   224                       bool &ref, bool obl=false);
   225 
   225 
   226     ///Add a new string type option with a storage reference
   226     ///Add a new string type option with a storage reference
   227 
   227 
   228     ///Add a new string type option with a storage reference.
   228     ///Add a new string type option with a storage reference.
   229     ///\param name The name of the option. The leading '-' must be omitted.
   229     ///\param name The name of the option. The leading '-' must be omitted.
   230     ///\param help A help string.
   230     ///\param help A help string.
   231     ///\param obl Indicate if the option is mandatory.
   231     ///\param obl Indicate if the option is mandatory.
   232     ///\retval ref The value of the argument will be written to this variable.
   232     ///\retval ref The value of the argument will be written to this variable.
   233     ArgParser &refOption(const std::string &name,
   233     ArgParser &refOption(const std::string &name,
   234 		      const std::string &help,
   234                       const std::string &help,
   235 		      std::string &ref, bool obl=false);
   235                       std::string &ref, bool obl=false);
   236     
   236 
   237     ///@}
   237     ///@}
   238 
   238 
   239     ///\name Option Groups and Synonyms
   239     ///\name Option Groups and Synonyms
   240     ///
   240     ///
   241     
   241 
   242     ///@{
   242     ///@{
   243 
   243 
   244     ///Bundle some options into a group
   244     ///Bundle some options into a group
   245 
   245 
   246     /// You can group some option by calling this function repeatedly for each
   246     /// You can group some option by calling this function repeatedly for each
   247     /// option to be grouped with the same groupname.
   247     /// option to be grouped with the same groupname.
   248     ///\param group The group name.
   248     ///\param group The group name.
   249     ///\param opt The option name.
   249     ///\param opt The option name.
   250     ArgParser &optionGroup(const std::string &group,
   250     ArgParser &optionGroup(const std::string &group,
   251 			   const std::string &opt);
   251                            const std::string &opt);
   252 
   252 
   253     ///Make the members of a group exclusive
   253     ///Make the members of a group exclusive
   254 
   254 
   255     ///If you call this function for a group, than at most one of them can be
   255     ///If you call this function for a group, than at most one of them can be
   256     ///given at the same time.
   256     ///given at the same time.
   257     ArgParser &onlyOneGroup(const std::string &group);
   257     ArgParser &onlyOneGroup(const std::string &group);
   258   
   258 
   259     ///Make a group mandatory
   259     ///Make a group mandatory
   260 
   260 
   261     ///Using this function, at least one of the members of \c group
   261     ///Using this function, at least one of the members of \c group
   262     ///must be given.
   262     ///must be given.
   263     ArgParser &mandatoryGroup(const std::string &group);
   263     ArgParser &mandatoryGroup(const std::string &group);
   264     
   264 
   265     ///Create synonym to an option
   265     ///Create synonym to an option
   266 
   266 
   267     ///With this function you can create a synonym \c syn of the
   267     ///With this function you can create a synonym \c syn of the
   268     ///option \c opt.
   268     ///option \c opt.
   269     ArgParser &synonym(const std::string &syn,
   269     ArgParser &synonym(const std::string &syn,
   270 			   const std::string &opt);
   270                            const std::string &opt);
   271     
   271 
   272     ///@}
   272     ///@}
   273 
   273 
   274     void show(std::ostream &os,Opts::iterator i);
   274     void show(std::ostream &os,Opts::iterator i);
   275     void show(std::ostream &os,Groups::iterator i);
   275     void show(std::ostream &os,Groups::iterator i);
   276     void showHelp(Opts::iterator i);
   276     void showHelp(Opts::iterator i);
   280 
   280 
   281     void unknownOpt(std::string arg);
   281     void unknownOpt(std::string arg);
   282 
   282 
   283     void requiresValue(std::string arg, OptType t);
   283     void requiresValue(std::string arg, OptType t);
   284     void checkMandatories();
   284     void checkMandatories();
   285     
   285 
   286     ///Start the parsing process
   286     ///Start the parsing process
   287     ArgParser &parse();
   287     ArgParser &parse();
   288 
   288 
   289     /// Synonym for parse()
   289     /// Synonym for parse()
   290     ArgParser &run() 
   290     ArgParser &run()
   291     {
   291     {
   292       return parse();
   292       return parse();
   293     }
   293     }
   294     
   294 
   295     ///Give back the command name (the 0th argument)
   295     ///Give back the command name (the 0th argument)
   296     const std::string &commandName() { return _command_name; }
   296     const std::string &commandName() { return _command_name; }
   297 
   297 
   298     ///Check if an opion has been given to the command.
   298     ///Check if an opion has been given to the command.
   299     bool given(std::string op) 
   299     bool given(std::string op)
   300     {
   300     {
   301       Opts::iterator i = _opts.find(op);
   301       Opts::iterator i = _opts.find(op);
   302       return i!=_opts.end()?i->second.set:false;
   302       return i!=_opts.end()?i->second.set:false;
   303     }
   303     }
   304 
   304 
   305 
   305 
   306     ///Magic type for operator[]
   306     ///Magic type for operator[]
   307     
   307 
   308     ///This is the type of the return value of ArgParser::operator[]().
   308     ///This is the type of the return value of ArgParser::operator[]().
   309     ///It automatically converts to \c int, \c double, \c bool or
   309     ///It automatically converts to \c int, \c double, \c bool or
   310     ///\c std::string if the type of the option matches, otherwise it
   310     ///\c std::string if the type of the option matches, otherwise it
   311     ///throws an exception (i.e. it performs runtime type checking).
   311     ///throws an exception (i.e. it performs runtime type checking).
   312     class RefType 
   312     class RefType
   313     {
   313     {
   314       ArgParser &_parser;
   314       ArgParser &_parser;
   315       std::string _name;
   315       std::string _name;
   316     public:
   316     public:
   317       ///\e
   317       ///\e
   318       RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
   318       RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
   319       ///\e
   319       ///\e
   320       operator bool() 
   320       operator bool()
   321       {
   321       {
   322 	Opts::iterator i = _parser._opts.find(_name);
   322         Opts::iterator i = _parser._opts.find(_name);
   323 	LEMON_ASSERT(i!=_parser._opts.end(),
   323         LEMON_ASSERT(i!=_parser._opts.end(),
   324 		     std::string()+"Unkown option: '"+_name+"'");
   324                      std::string()+"Unkown option: '"+_name+"'");
   325 	LEMON_ASSERT(i->second.type==ArgParser::BOOL,
   325         LEMON_ASSERT(i->second.type==ArgParser::BOOL,
   326 		     std::string()+"'"+_name+"' is a bool option");
   326                      std::string()+"'"+_name+"' is a bool option");
   327 	return *(i->second.bool_p);
   327         return *(i->second.bool_p);
   328       }
   328       }
   329       ///\e
   329       ///\e
   330       operator std::string()
   330       operator std::string()
   331       {
   331       {
   332 	Opts::iterator i = _parser._opts.find(_name);
   332         Opts::iterator i = _parser._opts.find(_name);
   333 	LEMON_ASSERT(i!=_parser._opts.end(),
   333         LEMON_ASSERT(i!=_parser._opts.end(),
   334 		     std::string()+"Unkown option: '"+_name+"'");
   334                      std::string()+"Unkown option: '"+_name+"'");
   335 	LEMON_ASSERT(i->second.type==ArgParser::STRING,
   335         LEMON_ASSERT(i->second.type==ArgParser::STRING,
   336 		     std::string()+"'"+_name+"' is a string option");
   336                      std::string()+"'"+_name+"' is a string option");
   337 	return *(i->second.string_p);
   337         return *(i->second.string_p);
   338       }
   338       }
   339       ///\e
   339       ///\e
   340       operator double() 
   340       operator double()
   341       {
   341       {
   342 	Opts::iterator i = _parser._opts.find(_name);
   342         Opts::iterator i = _parser._opts.find(_name);
   343 	LEMON_ASSERT(i!=_parser._opts.end(),
   343         LEMON_ASSERT(i!=_parser._opts.end(),
   344 		     std::string()+"Unkown option: '"+_name+"'");
   344                      std::string()+"Unkown option: '"+_name+"'");
   345 	LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
   345         LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
   346 		     i->second.type==ArgParser::INTEGER,
   346                      i->second.type==ArgParser::INTEGER,
   347 		     std::string()+"'"+_name+"' is a floating point option");
   347                      std::string()+"'"+_name+"' is a floating point option");
   348 	return i->second.type==ArgParser::DOUBLE ?
   348         return i->second.type==ArgParser::DOUBLE ?
   349 	  *(i->second.double_p) : *(i->second.int_p);
   349           *(i->second.double_p) : *(i->second.int_p);
   350       }
   350       }
   351       ///\e
   351       ///\e
   352       operator int() 
   352       operator int()
   353       {
   353       {
   354 	Opts::iterator i = _parser._opts.find(_name);
   354         Opts::iterator i = _parser._opts.find(_name);
   355 	LEMON_ASSERT(i!=_parser._opts.end(),
   355         LEMON_ASSERT(i!=_parser._opts.end(),
   356 		     std::string()+"Unkown option: '"+_name+"'");
   356                      std::string()+"Unkown option: '"+_name+"'");
   357 	LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
   357         LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
   358 		     std::string()+"'"+_name+"' is an integer option");
   358                      std::string()+"'"+_name+"' is an integer option");
   359 	return *(i->second.int_p);
   359         return *(i->second.int_p);
   360       }
   360       }
   361 
   361 
   362     };
   362     };
   363 
   363 
   364     ///Give back the value of an option
   364     ///Give back the value of an option
   365     
   365 
   366     ///Give back the value of an option.
   366     ///Give back the value of an option.
   367     ///\sa RefType
   367     ///\sa RefType
   368     RefType operator[](const std::string &n)
   368     RefType operator[](const std::string &n)
   369     {
   369     {
   370       return RefType(*this, n);
   370       return RefType(*this, n);
   371     }    
   371     }
   372 
   372 
   373     ///Give back the non-option type arguments.
   373     ///Give back the non-option type arguments.
   374 
   374 
   375     ///Give back a reference to a vector consisting of the program arguments
   375     ///Give back a reference to a vector consisting of the program arguments
   376     ///not starting with a '-' character.
   376     ///not starting with a '-' character.
   377     std::vector<std::string> &files() { return _file_args; }
   377     std::vector<std::string> &files() { return _file_args; }
   378  
   378 
   379   };
   379   };
   380 }
   380 }
   381 
   381 
   382 #endif // LEMON_ARG_PARSER
   382 #endif // LEMON_ARG_PARSER