COIN-OR::LEMON - Graph Library

source: lemon/lemon/arg_parser.h @ 173:b026e9779b28

Last change on this file since 173:b026e9779b28 was 108:889d0c289d19, checked in by Balazs Dezso <deba@…>, 17 years ago

Reworking assertions and moving to distinict file

File size: 10.8 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
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
19#ifndef LEMON_ARG_PARSER
20#define LEMON_ARG_PARSER
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  ///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 **_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    ///\e
122    ArgParser(int argc, const char **argv);
123
124    ~ArgParser();
125
126    ///Add a new integer type option
127
128    ///\param name The name of the option. The leading '-' must be omitted.
129    ///\param help A help string.
130    ///\param value A default value for the option.
131    ///\param obl Indicate if the option is mandatory.
132    ArgParser &intOption(const std::string &name,
133                    const std::string &help,
134                    int value=0, bool obl=false);
135
136    ///Add a new floating point type option
137
138    ///\param name The name of the option. The leading '-' must be omitted.
139    ///\param help A help string.
140    ///\param value A default value for the option.
141    ///\param obl Indicate if the option is mandatory.
142    ArgParser &doubleOption(const std::string &name,
143                      const std::string &help,
144                      double value=0, bool obl=false);
145
146    ///Add a new bool type option
147
148    ///\param name The name of the option. The leading '-' must be omitted.
149    ///\param help A help string.
150    ///\param value A default value for the option.
151    ///\param obl Indicate if the option is mandatory.
152    ///\note A mandatory bool obtion is of very little use.
153    ArgParser &boolOption(const std::string &name,
154                      const std::string &help,
155                      bool value=false, bool obl=false);
156
157    ///Add a new string type option
158
159    ///\param name The name of the option. The leading '-' must be omitted.
160    ///\param help A help string.
161    ///\param value A default value for the option.
162    ///\param obl Indicate if the option is mandatory.
163    ArgParser &stringOption(const std::string &name,
164                      const std::string &help,
165                      std::string value="", bool obl=false);
166
167    ///\name Options with external storage
168    ///Using this functions, the value of the option will be directly written
169    ///into a variable once the option appears in the command line.
170
171    ///@{
172
173    ///Add a new integer type option with a storage reference
174
175    ///\param name The name of the option. The leading '-' must be omitted.
176    ///\param help A help string.
177    ///\param obl Indicate if the option is mandatory.
178    ///\retval ref The value of the argument will be written to this variable.
179    ArgParser &refOption(const std::string &name,
180                    const std::string &help,
181                    int &ref, bool obl=false);
182
183    ///Add a new floating type option with a storage reference
184
185    ///\param name The name of the option. The leading '-' must be omitted.
186    ///\param help A help string.
187    ///\param obl Indicate if the option is mandatory.
188    ///\retval ref The value of the argument will be written to this variable.
189    ArgParser &refOption(const std::string &name,
190                      const std::string &help,
191                      double &ref, bool obl=false);
192
193    ///Add a new bool type option with a storage reference
194
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    ///\note A mandatory bool obtion is of very little use.
200    ArgParser &refOption(const std::string &name,
201                      const std::string &help,
202                      bool &ref, bool obl=false);
203
204    ///Add a new string type option with a storage reference
205
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                      std::string &ref, bool obl=false);
213   
214    ///@}
215
216    ///\name Option Groups and Synonyms
217    ///
218   
219    ///@{
220
221    ///Boundle some options into a group
222
223    /// You can group some option by calling this function repeatedly for each
224    /// option to be grouped with the same groupname.
225    ///\param group The group name.
226    ///\param opt The option name.
227    ArgParser &optionGroup(const std::string &group,
228                           const std::string &opt);
229
230    ///Make the members of a group exclusive
231
232    ///If you call this function for a group, than at most one of them can be
233    ///given at the same time
234    ArgParser &onlyOneGroup(const std::string &group);
235 
236    ///Make a group mandatory
237
238    ///Using this function, at least one of the members of \c group
239    ///must be given.
240    ArgParser &mandatoryGroup(const std::string &group);
241   
242    ///Create synonym to an option
243
244    ///With this function you can create a synonym \c syn of the
245    ///option \c opt.
246    ArgParser &synonym(const std::string &syn,
247                           const std::string &opt);
248   
249    ///@}
250
251    ///Give help string for non-parsed arguments.
252
253    ///With this function you can give help string for non-parsed arguments.
254    ///The parameter \c name will be printed in the short usage line, while
255    ///\c help gives a more detailed description.
256    ArgParser &other(const std::string &name,
257                     const std::string &help="");
258   
259    ///Give back the non-option type arguments.
260
261    ///Give back a reference to a vector consisting of the program arguments
262    ///not starting with a '-' character.
263    std::vector<std::string> &files() { return _file_args; }
264
265    ///Give back the command name (the 0th argument)
266    const std::string &commandName() { return _command_name; }
267
268    void show(std::ostream &os,Opts::iterator i);
269    void show(std::ostream &os,Groups::iterator i);
270    void showHelp(Opts::iterator i);
271    void showHelp(std::vector<OtherArg>::iterator i);
272    void shortHelp();
273    void showHelp();
274
275    void unknownOpt(std::string arg);
276
277    void requiresValue(std::string arg, OptType t);
278    void checkMandatories();
279   
280    ///Start the parsing process
281    ArgParser &parse();
282
283    /// Synonym for parse()
284    ArgParser &run()
285    {
286      return parse();
287    }
288   
289    ///Check if an opion has been given to the command.
290    bool given(std::string op)
291    {
292      Opts::iterator i = _opts.find(op);
293      return i!=_opts.end()?i->second.set:false;
294    }
295
296
297    ///Magic type for operator[]
298   
299    ///This is the type of the return value of ArgParser::operator[]().
300    ///It automatically converts to \c int, \c double, \c bool or
301    ///\c std::string if the type of the option matches, otherwise it
302    ///throws an exception (i.e. it performs runtime type checking).
303    class RefType
304    {
305      ArgParser &_parser;
306      std::string _name;
307    public:
308      ///\e
309      RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
310      ///\e
311      operator bool()
312      {
313        Opts::iterator i = _parser._opts.find(_name);
314        LEMON_ASSERT(i!=_parser._opts.end(),
315                     std::string()+"Unkown option: '"+_name+"'");
316        LEMON_ASSERT(i->second.type==ArgParser::BOOL,
317                     std::string()+"'"+_name+"' is a bool option");
318        return *(i->second.bool_p);
319      }
320      ///\e
321      operator std::string()
322      {
323        Opts::iterator i = _parser._opts.find(_name);
324        LEMON_ASSERT(i!=_parser._opts.end(),
325                     std::string()+"Unkown option: '"+_name+"'");
326        LEMON_ASSERT(i->second.type==ArgParser::STRING,
327                     std::string()+"'"+_name+"' is a string option");
328        return *(i->second.string_p);
329      }
330      ///\e
331      operator double()
332      {
333        Opts::iterator i = _parser._opts.find(_name);
334        LEMON_ASSERT(i!=_parser._opts.end(),
335                     std::string()+"Unkown option: '"+_name+"'");
336        LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
337                     i->second.type==ArgParser::INTEGER,
338                     std::string()+"'"+_name+"' is a floating point option");
339        return i->second.type==ArgParser::DOUBLE ?
340          *(i->second.double_p) : *(i->second.int_p);
341      }
342      ///\e
343      operator int()
344      {
345        Opts::iterator i = _parser._opts.find(_name);
346        LEMON_ASSERT(i!=_parser._opts.end(),
347                     std::string()+"Unkown option: '"+_name+"'");
348        LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
349                     std::string()+"'"+_name+"' is an integer option");
350        return *(i->second.int_p);
351      }
352
353    };
354
355    ///Give back the value of an option
356   
357    ///Give back the value of an option.
358    ///\sa RefType
359    RefType operator[](const std::string &n)
360    {
361      return RefType(*this, n);
362    }   
363 
364  };
365}
366
367   
368
369#endif // LEMON_MAIN_PARAMS
Note: See TracBrowser for help on using the repository browser.