COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/arg_parser.h @ 2517:d9cfac072869

Last change on this file since 2517:d9cfac072869 was 2436:0c941c524b47, checked in by Alpar Juttner, 17 years ago

Integer parameters also convert to double

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