COIN-OR::LEMON - Graph Library

source: lemon/lemon/arg_parser.h @ 499:227f36959519

Last change on this file since 499:227f36959519 was 311:c887e703b566, checked in by Akos Ladanyi <ladanyi@…>, 15 years ago

Fix an erroneous const declaration in ArgParser?

File size: 12.0 KB
RevLine 
[209]1/* -*- mode: C++; indent-tabs-mode: nil; -*-
[85]2 *
[209]3 * This file is a part of LEMON, a generic C++ optimization library.
[85]4 *
5 * Copyright (C) 2003-2008
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
[261]19#ifndef LEMON_ARG_PARSER_H
20#define LEMON_ARG_PARSER_H
[85]21
22#include <vector>
23#include <map>
24#include <list>
25#include <string>
26#include <iostream>
27#include <sstream>
28#include <algorithm>
[108]29#include <lemon/assert.h>
[85]30
31///\ingroup misc
32///\file
[88]33///\brief A tool to parse command line arguments.
[85]34
35namespace lemon {
36
37  ///Command line arguments parser
38
39  ///\ingroup misc
[88]40  ///Command line arguments parser.
[85]41  ///
[88]42  ///For a complete example see the \ref arg_parser_demo.cc demo file.
[85]43  class ArgParser {
[209]44
[85]45    static void _showHelp(void *p);
46  protected:
[209]47
[85]48    int _argc;
[311]49    const char * const *_argv;
[209]50
[85]51    enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
[209]52
[85]53    class ParData {
54    public:
55      union {
[209]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
[85]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),
[209]75                  has_syn(false), syn(false), self_delete(false) {}
[85]76    };
77
78    typedef std::map<std::string,ParData> Opts;
79    Opts _opts;
80
[209]81    class GroupData
[85]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    };
[209]90
[85]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    };
[209]101
[85]102    std::vector<OtherArg> _others_help;
103    std::vector<std::string> _file_args;
104    std::string _command_name;
[87]105
[209]106
[87]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,
[209]116                    const std::string &help,
117                    void (*func)(void *),void *data);
118
[85]119  public:
120
[204]121    ///Constructor
[311]122    ArgParser(int argc, const char * const *argv);
[85]123
124    ~ArgParser();
125
[204]126    ///\name Options
127    ///
128
129    ///@{
130
[85]131    ///Add a new integer type option
132
[204]133    ///Add a new integer type option.
[85]134    ///\param name The name of the option. The leading '-' must be omitted.
135    ///\param help A help string.
[95]136    ///\param value A default value for the option.
[85]137    ///\param obl Indicate if the option is mandatory.
138    ArgParser &intOption(const std::string &name,
[209]139                    const std::string &help,
140                    int value=0, bool obl=false);
[85]141
[86]142    ///Add a new floating point type option
[85]143
[204]144    ///Add a new floating point type option.
[85]145    ///\param name The name of the option. The leading '-' must be omitted.
146    ///\param help A help string.
[95]147    ///\param value A default value for the option.
[85]148    ///\param obl Indicate if the option is mandatory.
149    ArgParser &doubleOption(const std::string &name,
[209]150                      const std::string &help,
151                      double value=0, bool obl=false);
[85]152
153    ///Add a new bool type option
154
[204]155    ///Add a new bool type option.
[85]156    ///\param name The name of the option. The leading '-' must be omitted.
157    ///\param help A help string.
[95]158    ///\param value A default value for the option.
[85]159    ///\param obl Indicate if the option is mandatory.
[95]160    ///\note A mandatory bool obtion is of very little use.
[85]161    ArgParser &boolOption(const std::string &name,
[209]162                      const std::string &help,
163                      bool value=false, bool obl=false);
[85]164
165    ///Add a new string type option
166
[204]167    ///Add a new string type option.
[85]168    ///\param name The name of the option. The leading '-' must be omitted.
169    ///\param help A help string.
[95]170    ///\param value A default value for the option.
[85]171    ///\param obl Indicate if the option is mandatory.
172    ArgParser &stringOption(const std::string &name,
[209]173                      const std::string &help,
174                      std::string value="", bool obl=false);
[85]175
[204]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,
[209]182                     const std::string &help="");
183
[204]184    ///@}
185
186    ///\name Options with External Storage
[85]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
[204]194    ///Add a new integer type option with a storage reference.
[85]195    ///\param name The name of the option. The leading '-' must be omitted.
196    ///\param help A help string.
[90]197    ///\param obl Indicate if the option is mandatory.
[85]198    ///\retval ref The value of the argument will be written to this variable.
199    ArgParser &refOption(const std::string &name,
[209]200                    const std::string &help,
201                    int &ref, bool obl=false);
[85]202
203    ///Add a new floating type option with a storage reference
204
[204]205    ///Add a new floating type option with a storage reference.
[85]206    ///\param name The name of the option. The leading '-' must be omitted.
207    ///\param help A help string.
[90]208    ///\param obl Indicate if the option is mandatory.
[85]209    ///\retval ref The value of the argument will be written to this variable.
210    ArgParser &refOption(const std::string &name,
[209]211                      const std::string &help,
212                      double &ref, bool obl=false);
[85]213
214    ///Add a new bool type option with a storage reference
215
[204]216    ///Add a new bool type option with a storage reference.
[85]217    ///\param name The name of the option. The leading '-' must be omitted.
218    ///\param help A help string.
[90]219    ///\param obl Indicate if the option is mandatory.
[85]220    ///\retval ref The value of the argument will be written to this variable.
[95]221    ///\note A mandatory bool obtion is of very little use.
[85]222    ArgParser &refOption(const std::string &name,
[209]223                      const std::string &help,
224                      bool &ref, bool obl=false);
[85]225
226    ///Add a new string type option with a storage reference
227
[204]228    ///Add a new string type option with a storage reference.
[85]229    ///\param name The name of the option. The leading '-' must be omitted.
230    ///\param help A help string.
[95]231    ///\param obl Indicate if the option is mandatory.
[85]232    ///\retval ref The value of the argument will be written to this variable.
233    ArgParser &refOption(const std::string &name,
[209]234                      const std::string &help,
235                      std::string &ref, bool obl=false);
236
[85]237    ///@}
238
239    ///\name Option Groups and Synonyms
240    ///
[209]241
[85]242    ///@{
243
[204]244    ///Bundle some options into a group
[85]245
246    /// You can group some option by calling this function repeatedly for each
[88]247    /// option to be grouped with the same groupname.
248    ///\param group The group name.
249    ///\param opt The option name.
[85]250    ArgParser &optionGroup(const std::string &group,
[209]251                           const std::string &opt);
[85]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
[204]256    ///given at the same time.
[85]257    ArgParser &onlyOneGroup(const std::string &group);
[209]258
[85]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);
[209]264
[85]265    ///Create synonym to an option
266
[88]267    ///With this function you can create a synonym \c syn of the
[85]268    ///option \c opt.
269    ArgParser &synonym(const std::string &syn,
[209]270                           const std::string &opt);
271
[85]272    ///@}
273
[214]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;
[85]279
[214]280    void unknownOpt(std::string arg) const;
[85]281
[214]282    void requiresValue(std::string arg, OptType t) const;
283    void checkMandatories() const;
284
285    void shortHelp() const;
286    void showHelp() const;
287  public:
[209]288
[85]289    ///Start the parsing process
290    ArgParser &parse();
291
292    /// Synonym for parse()
[209]293    ArgParser &run()
[85]294    {
295      return parse();
296    }
[209]297
[204]298    ///Give back the command name (the 0th argument)
[214]299    const std::string &commandName() const { return _command_name; }
[204]300
[85]301    ///Check if an opion has been given to the command.
[214]302    bool given(std::string op) const
[85]303    {
[214]304      Opts::const_iterator i = _opts.find(op);
[85]305      return i!=_opts.end()?i->second.set:false;
306    }
307
308
309    ///Magic type for operator[]
[209]310
[85]311    ///This is the type of the return value of ArgParser::operator[]().
[88]312    ///It automatically converts to \c int, \c double, \c bool or
[290]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).
[209]316    class RefType
[85]317    {
[214]318      const ArgParser &_parser;
[85]319      std::string _name;
320    public:
321      ///\e
[214]322      RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
[85]323      ///\e
[209]324      operator bool()
[85]325      {
[214]326        Opts::const_iterator i = _parser._opts.find(_name);
[209]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);
[85]332      }
333      ///\e
334      operator std::string()
335      {
[214]336        Opts::const_iterator i = _parser._opts.find(_name);
[209]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);
[85]342      }
343      ///\e
[209]344      operator double()
[85]345      {
[214]346        Opts::const_iterator i = _parser._opts.find(_name);
[209]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);
[85]354      }
355      ///\e
[209]356      operator int()
[85]357      {
[214]358        Opts::const_iterator i = _parser._opts.find(_name);
[209]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);
[85]364      }
365
366    };
367
368    ///Give back the value of an option
[209]369
[88]370    ///Give back the value of an option.
[85]371    ///\sa RefType
[214]372    RefType operator[](const std::string &n) const
[85]373    {
374      return RefType(*this, n);
[209]375    }
[204]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.
[214]381    const std::vector<std::string> &files() const { return _file_args; }
[209]382
[85]383  };
384}
385
[261]386#endif // LEMON_ARG_PARSER_H
Note: See TracBrowser for help on using the repository browser.