1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
 
     3  * This file is a part of LEMON, a generic C++ optimization library.
 
     5  * Copyright (C) 2003-2010
 
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 
     9  * Permission to use, modify and distribute this software is granted
 
    10  * provided that this copyright notice appears in all copies. For
 
    11  * precise terms see the accompanying LICENSE file.
 
    13  * This software is provided "AS IS" with no warranty of any kind,
 
    14  * express or implied, and with no claim as to its suitability for any
 
    19 #ifndef LEMON_ARG_PARSER_H
 
    20 #define LEMON_ARG_PARSER_H
 
    29 #include <lemon/assert.h>
 
    33 ///\brief A tool to parse command line arguments.
 
    37   ///Exception used by ArgParser
 
    39   ///Exception used by ArgParser.
 
    41   class ArgParserException : public Exception {
 
    43     /// Reasons for failure
 
    45     /// Reasons for failure.
 
    48       HELP,         ///< <tt>--help</tt> option was given.
 
    49       UNKNOWN_OPT,  ///< Unknown option was given.
 
    50       INVALID_OPT   ///< Invalid combination of options.
 
    58     ArgParserException(Reason r) throw() : _reason(r) {}
 
    60     virtual ~ArgParserException() throw() {}
 
    61     ///A short description of the exception
 
    62     virtual const char* what() const throw() {
 
    66           return "lemon::ArgParseException: ask for help";
 
    69           return "lemon::ArgParseException: unknown option";
 
    72           return "lemon::ArgParseException: invalid combination of options";
 
    77     ///Return the reason for the failure
 
    78     Reason reason() const {return _reason; }
 
    82   ///Command line arguments parser
 
    85   ///Command line arguments parser.
 
    87   ///For a complete example see the \ref arg_parser_demo.cc demo file.
 
    90     static void _showHelp(void *p);
 
    94     const char * const *_argv;
 
    96     enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
 
   104         std::string *string_p;
 
   119       ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
 
   120                   has_syn(false), syn(false), self_delete(false) {}
 
   123     typedef std::map<std::string,ParData> Opts;
 
   129       typedef std::list<std::string> Opts;
 
   133       GroupData() :only_one(false), mandatory(false) {}
 
   136     typedef std::map<std::string,GroupData> Groups;
 
   143       OtherArg(std::string n, std::string h) :name(n), help(h) {}
 
   147     std::vector<OtherArg> _others_help;
 
   148     std::vector<std::string> _file_args;
 
   149     std::string _command_name;
 
   153     //Bind a function to an option.
 
   155     //\param name The name of the option. The leading '-' must be omitted.
 
   156     //\param help A help string.
 
   157     //\retval func The function to be called when the option is given. It
 
   158     //  must be of type "void f(void *)"
 
   159     //\param data Data to be passed to \c func
 
   160     ArgParser &funcOption(const std::string &name,
 
   161                     const std::string &help,
 
   162                     void (*func)(void *),void *data);
 
   164     bool _exit_on_problems;
 
   166     void _terminate(ArgParserException::Reason reason) const;
 
   171     ArgParser(int argc, const char * const *argv);
 
   180     ///Add a new integer type option
 
   182     ///Add a new integer type option.
 
   183     ///\param name The name of the option. The leading '-' must be omitted.
 
   184     ///\param help A help string.
 
   185     ///\param value A default value for the option.
 
   186     ///\param obl Indicate if the option is mandatory.
 
   187     ArgParser &intOption(const std::string &name,
 
   188                     const std::string &help,
 
   189                     int value=0, bool obl=false);
 
   191     ///Add a new floating point type option
 
   193     ///Add a new floating point type option.
 
   194     ///\param name The name of the option. The leading '-' must be omitted.
 
   195     ///\param help A help string.
 
   196     ///\param value A default value for the option.
 
   197     ///\param obl Indicate if the option is mandatory.
 
   198     ArgParser &doubleOption(const std::string &name,
 
   199                       const std::string &help,
 
   200                       double value=0, bool obl=false);
 
   202     ///Add a new bool type option
 
   204     ///Add a new bool type option.
 
   205     ///\param name The name of the option. The leading '-' must be omitted.
 
   206     ///\param help A help string.
 
   207     ///\param value A default value for the option.
 
   208     ///\param obl Indicate if the option is mandatory.
 
   209     ///\note A mandatory bool obtion is of very little use.
 
   210     ArgParser &boolOption(const std::string &name,
 
   211                       const std::string &help,
 
   212                       bool value=false, bool obl=false);
 
   214     ///Add a new string type option
 
   216     ///Add a new string type option.
 
   217     ///\param name The name of the option. The leading '-' must be omitted.
 
   218     ///\param help A help string.
 
   219     ///\param value A default value for the option.
 
   220     ///\param obl Indicate if the option is mandatory.
 
   221     ArgParser &stringOption(const std::string &name,
 
   222                       const std::string &help,
 
   223                       std::string value="", bool obl=false);
 
   225     ///Give help string for non-parsed arguments.
 
   227     ///With this function you can give help string for non-parsed arguments.
 
   228     ///The parameter \c name will be printed in the short usage line, while
 
   229     ///\c help gives a more detailed description.
 
   230     ArgParser &other(const std::string &name,
 
   231                      const std::string &help="");
 
   235     ///\name Options with External Storage
 
   236     ///Using this functions, the value of the option will be directly written
 
   237     ///into a variable once the option appears in the command line.
 
   241     ///Add a new integer type option with a storage reference
 
   243     ///Add a new integer type option with a storage reference.
 
   244     ///\param name The name of the option. The leading '-' must be omitted.
 
   245     ///\param help A help string.
 
   246     ///\param obl Indicate if the option is mandatory.
 
   247     ///\retval ref The value of the argument will be written to this variable.
 
   248     ArgParser &refOption(const std::string &name,
 
   249                     const std::string &help,
 
   250                     int &ref, bool obl=false);
 
   252     ///Add a new floating type option with a storage reference
 
   254     ///Add a new floating type option with a storage reference.
 
   255     ///\param name The name of the option. The leading '-' must be omitted.
 
   256     ///\param help A help string.
 
   257     ///\param obl Indicate if the option is mandatory.
 
   258     ///\retval ref The value of the argument will be written to this variable.
 
   259     ArgParser &refOption(const std::string &name,
 
   260                       const std::string &help,
 
   261                       double &ref, bool obl=false);
 
   263     ///Add a new bool type option with a storage reference
 
   265     ///Add a new bool type option with a storage reference.
 
   266     ///\param name The name of the option. The leading '-' must be omitted.
 
   267     ///\param help A help string.
 
   268     ///\param obl Indicate if the option is mandatory.
 
   269     ///\retval ref The value of the argument will be written to this variable.
 
   270     ///\note A mandatory bool obtion is of very little use.
 
   271     ArgParser &refOption(const std::string &name,
 
   272                       const std::string &help,
 
   273                       bool &ref, bool obl=false);
 
   275     ///Add a new string type option with a storage reference
 
   277     ///Add a new string type option with a storage reference.
 
   278     ///\param name The name of the option. The leading '-' must be omitted.
 
   279     ///\param help A help string.
 
   280     ///\param obl Indicate if the option is mandatory.
 
   281     ///\retval ref The value of the argument will be written to this variable.
 
   282     ArgParser &refOption(const std::string &name,
 
   283                       const std::string &help,
 
   284                       std::string &ref, bool obl=false);
 
   288     ///\name Option Groups and Synonyms
 
   293     ///Bundle some options into a group
 
   295     /// You can group some option by calling this function repeatedly for each
 
   296     /// option to be grouped with the same groupname.
 
   297     ///\param group The group name.
 
   298     ///\param opt The option name.
 
   299     ArgParser &optionGroup(const std::string &group,
 
   300                            const std::string &opt);
 
   302     ///Make the members of a group exclusive
 
   304     ///If you call this function for a group, than at most one of them can be
 
   305     ///given at the same time.
 
   306     ArgParser &onlyOneGroup(const std::string &group);
 
   308     ///Make a group mandatory
 
   310     ///Using this function, at least one of the members of \c group
 
   312     ArgParser &mandatoryGroup(const std::string &group);
 
   314     ///Create synonym to an option
 
   316     ///With this function you can create a synonym \c syn of the
 
   318     ArgParser &synonym(const std::string &syn,
 
   319                            const std::string &opt);
 
   324     void show(std::ostream &os,Opts::const_iterator i) const;
 
   325     void show(std::ostream &os,Groups::const_iterator i) const;
 
   326     void showHelp(Opts::const_iterator i) const;
 
   327     void showHelp(std::vector<OtherArg>::const_iterator i) const;
 
   329     void unknownOpt(std::string arg) const;
 
   331     void requiresValue(std::string arg, OptType t) const;
 
   332     void checkMandatories() const;
 
   334     void shortHelp() const;
 
   335     void showHelp() const;
 
   338     ///Start the parsing process
 
   341     /// Synonym for parse()
 
   347     ///Give back the command name (the 0th argument)
 
   348     const std::string &commandName() const { return _command_name; }
 
   350     ///Check if an opion has been given to the command.
 
   351     bool given(std::string op) const
 
   353       Opts::const_iterator i = _opts.find(op);
 
   354       return i!=_opts.end()?i->second.set:false;
 
   358     ///Magic type for operator[]
 
   360     ///This is the type of the return value of ArgParser::operator[]().
 
   361     ///It automatically converts to \c int, \c double, \c bool or
 
   362     ///\c std::string if the type of the option matches, which is checked
 
   363     ///with an \ref LEMON_ASSERT "assertion" (i.e. it performs runtime
 
   367       const ArgParser &_parser;
 
   371       RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
 
   375         Opts::const_iterator i = _parser._opts.find(_name);
 
   376         LEMON_ASSERT(i!=_parser._opts.end(),
 
   377                      std::string()+"Unkown option: '"+_name+"'");
 
   378         LEMON_ASSERT(i->second.type==ArgParser::BOOL,
 
   379                      std::string()+"'"+_name+"' is a bool option");
 
   380         return *(i->second.bool_p);
 
   383       operator std::string()
 
   385         Opts::const_iterator i = _parser._opts.find(_name);
 
   386         LEMON_ASSERT(i!=_parser._opts.end(),
 
   387                      std::string()+"Unkown option: '"+_name+"'");
 
   388         LEMON_ASSERT(i->second.type==ArgParser::STRING,
 
   389                      std::string()+"'"+_name+"' is a string option");
 
   390         return *(i->second.string_p);
 
   395         Opts::const_iterator i = _parser._opts.find(_name);
 
   396         LEMON_ASSERT(i!=_parser._opts.end(),
 
   397                      std::string()+"Unkown option: '"+_name+"'");
 
   398         LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
 
   399                      i->second.type==ArgParser::INTEGER,
 
   400                      std::string()+"'"+_name+"' is a floating point option");
 
   401         return i->second.type==ArgParser::DOUBLE ?
 
   402           *(i->second.double_p) : *(i->second.int_p);
 
   407         Opts::const_iterator i = _parser._opts.find(_name);
 
   408         LEMON_ASSERT(i!=_parser._opts.end(),
 
   409                      std::string()+"Unkown option: '"+_name+"'");
 
   410         LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
 
   411                      std::string()+"'"+_name+"' is an integer option");
 
   412         return *(i->second.int_p);
 
   417     ///Give back the value of an option
 
   419     ///Give back the value of an option.
 
   421     RefType operator[](const std::string &n) const
 
   423       return RefType(*this, n);
 
   426     ///Give back the non-option type arguments.
 
   428     ///Give back a reference to a vector consisting of the program arguments
 
   429     ///not starting with a '-' character.
 
   430     const std::vector<std::string> &files() const { return _file_args; }
 
   432     ///Throw instead of exit in case of problems
 
   433     void throwOnProblems()
 
   435       _exit_on_problems=false;
 
   440 #endif // LEMON_ARG_PARSER_H