lemon/arg_parser.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 596 8c3112a66878
parent 311 c887e703b566
permissions -rw-r--r--
Use XTI implementation instead of ATI in NetworkSimplex (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

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