COIN-OR::LEMON - Graph Library

source: lemon/lemon/arg_parser.h @ 1240:ee9bac10f58e

Last change on this file since 1240:ee9bac10f58e was 959:38213abd2911, checked in by Peter Kovacs <kpeter@…>, 14 years ago

Small doc fixes and improvements (#359)

File size: 13.3 KB
Line 
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-2010
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
35namespace lemon {
36
37  ///Exception used by ArgParser
38
39  ///Exception used by ArgParser.
40  ///
41  class ArgParserException : public Exception {
42  public:
43    /// Reasons for failure
44
45    /// Reasons for failure.
46    ///
47    enum Reason {
48      HELP,         ///< <tt>--help</tt> option was given.
49      UNKNOWN_OPT,  ///< Unknown option was given.
50      INVALID_OPT   ///< Invalid combination of options.
51    };
52
53  private:
54    Reason _reason;
55
56  public:
57    ///Constructor
58    ArgParserException(Reason r) throw() : _reason(r) {}
59    ///Virtual destructor
60    virtual ~ArgParserException() throw() {}
61    ///A short description of the exception
62    virtual const char* what() const throw() {
63      switch(_reason)
64        {
65        case HELP:
66          return "lemon::ArgParseException: ask for help";
67          break;
68        case UNKNOWN_OPT:
69          return "lemon::ArgParseException: unknown option";
70          break;
71        case INVALID_OPT:
72          return "lemon::ArgParseException: invalid combination of options";
73          break;
74        }
75      return "";
76    }
77    ///Return the reason for the failure
78    Reason reason() const {return _reason; }
79  };
80
81
82  ///Command line arguments parser
83
84  ///\ingroup misc
85  ///Command line arguments parser.
86  ///
87  ///For a complete example see the \ref arg_parser_demo.cc demo file.
88  class ArgParser {
89
90    static void _showHelp(void *p);
91  protected:
92
93    int _argc;
94    const char * const *_argv;
95
96    enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
97
98    class ParData {
99    public:
100      union {
101        bool *bool_p;
102        int *int_p;
103        double *double_p;
104        std::string *string_p;
105        struct {
106          void (*p)(void *);
107          void *data;
108        } func_p;
109
110      };
111      std::string help;
112      bool mandatory;
113      OptType type;
114      bool set;
115      bool ingroup;
116      bool has_syn;
117      bool syn;
118      bool self_delete;
119      ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
120                  has_syn(false), syn(false), self_delete(false) {}
121    };
122
123    typedef std::map<std::string,ParData> Opts;
124    Opts _opts;
125
126    class GroupData
127    {
128    public:
129      typedef std::list<std::string> Opts;
130      Opts opts;
131      bool only_one;
132      bool mandatory;
133      GroupData() :only_one(false), mandatory(false) {}
134    };
135
136    typedef std::map<std::string,GroupData> Groups;
137    Groups _groups;
138
139    struct OtherArg
140    {
141      std::string name;
142      std::string help;
143      OtherArg(std::string n, std::string h) :name(n), help(h) {}
144
145    };
146
147    std::vector<OtherArg> _others_help;
148    std::vector<std::string> _file_args;
149    std::string _command_name;
150
151
152  private:
153    //Bind a function to an option.
154
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);
163
164    bool _exit_on_problems;
165
166    void _terminate(ArgParserException::Reason reason) const;
167
168  public:
169
170    ///Constructor
171    ArgParser(int argc, const char * const *argv);
172
173    ~ArgParser();
174
175    ///\name Options
176    ///
177
178    ///@{
179
180    ///Add a new integer type option
181
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);
190
191    ///Add a new floating point type option
192
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);
201
202    ///Add a new bool type option
203
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);
213
214    ///Add a new string type option
215
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);
224
225    ///Give help string for non-parsed arguments.
226
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="");
232
233    ///@}
234
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.
238
239    ///@{
240
241    ///Add a new integer type option with a storage reference
242
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);
251
252    ///Add a new floating type option with a storage reference
253
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);
262
263    ///Add a new bool type option with a storage reference
264
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);
274
275    ///Add a new string type option with a storage reference
276
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);
285
286    ///@}
287
288    ///\name Option Groups and Synonyms
289    ///
290
291    ///@{
292
293    ///Bundle some options into a group
294
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);
301
302    ///Make the members of a group exclusive
303
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);
307
308    ///Make a group mandatory
309
310    ///Using this function, at least one of the members of \c group
311    ///must be given.
312    ArgParser &mandatoryGroup(const std::string &group);
313
314    ///Create synonym to an option
315
316    ///With this function you can create a synonym \c syn of the
317    ///option \c opt.
318    ArgParser &synonym(const std::string &syn,
319                           const std::string &opt);
320
321    ///@}
322
323  private:
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;
328
329    void unknownOpt(std::string arg) const;
330
331    void requiresValue(std::string arg, OptType t) const;
332    void checkMandatories() const;
333
334    void shortHelp() const;
335    void showHelp() const;
336  public:
337
338    ///Start the parsing process
339    ArgParser &parse();
340
341    /// Synonym for parse()
342    ArgParser &run()
343    {
344      return parse();
345    }
346
347    ///Give back the command name (the 0th argument)
348    const std::string &commandName() const { return _command_name; }
349
350    ///Check if an opion has been given to the command.
351    bool given(std::string op) const
352    {
353      Opts::const_iterator i = _opts.find(op);
354      return i!=_opts.end()?i->second.set:false;
355    }
356
357
358    ///Magic type for operator[]
359
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
364    ///type checking).
365    class RefType
366    {
367      const ArgParser &_parser;
368      std::string _name;
369    public:
370      ///\e
371      RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
372      ///\e
373      operator bool()
374      {
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);
381      }
382      ///\e
383      operator std::string()
384      {
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);
391      }
392      ///\e
393      operator double()
394      {
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);
403      }
404      ///\e
405      operator int()
406      {
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);
413      }
414
415    };
416
417    ///Give back the value of an option
418
419    ///Give back the value of an option.
420    ///\sa RefType
421    RefType operator[](const std::string &n) const
422    {
423      return RefType(*this, n);
424    }
425
426    ///Give back the non-option type arguments.
427
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; }
431
432    ///Throw instead of exit in case of problems
433    void throwOnProblems()
434    {
435      _exit_on_problems=false;
436    }
437  };
438}
439
440#endif // LEMON_ARG_PARSER_H
Note: See TracBrowser for help on using the repository browser.