COIN-OR::LEMON - Graph Library

source: lemon/lemon/arg_parser.h @ 87:81e138275860

Last change on this file since 87:81e138275860 was 87:81e138275860, checked in by Alpar Juttner <alpar@…>, 12 years ago

Hide and privatize member function funcOption()

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