gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Hide and privatize member function funcOption()
0 1 0
default
1 file changed with 13 insertions and 11 deletions:
↑ Collapse diff ↑
Ignore white space 384 line context
1 1
/* -*- C++ -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_ARG_PARSER
20 20
#define LEMON_ARG_PARSER
21 21

	
22 22
#include <vector>
23 23
#include <map>
24 24
#include <list>
25 25
#include <string>
26 26
#include <iostream>
27 27
#include <sstream>
28 28
#include <algorithm>
29 29
#include <lemon/error.h>
30 30

	
31 31
///\ingroup misc
32 32
///\file
33 33
///\brief A tools to parse command line arguments.
34 34
///
35 35
///\author Alpar Juttner
36 36

	
37 37
namespace lemon {
38 38

	
39 39
  ///Command line arguments parser
40 40

	
41 41
  ///\ingroup misc
42 42
  ///Command line arguments parser
43 43
  ///
44 44
  class ArgParser {
45 45
    
46 46
    static void _showHelp(void *p);
47 47
  protected:
48 48
    
49 49
    int _argc;
50 50
    const char **_argv;
51 51
    
52 52
    enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
53 53
    
54 54
    class ParData {
55 55
    public:
56 56
      union {
57 57
	bool *bool_p;
58 58
	int *int_p;
59 59
	double *double_p;
60 60
	std::string *string_p;
61 61
	struct {
62 62
	  void (*p)(void *);
63 63
	  void *data;
64 64
	} func_p;
65 65
	  
66 66
      };
67 67
      std::string help;
68 68
      bool mandatory;
69 69
      OptType type;
70 70
      bool set;
71 71
      bool ingroup;
72 72
      bool has_syn;
73 73
      bool syn;
74 74
      bool self_delete;
75 75
      ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
76 76
		  has_syn(false), syn(false), self_delete(false) {}
77 77
    };
78 78

	
79 79
    typedef std::map<std::string,ParData> Opts;
80 80
    Opts _opts;
81 81

	
82 82
    class GroupData 
83 83
    {
84 84
    public:
85 85
      typedef std::list<std::string> Opts;
86 86
      Opts opts;
87 87
      bool only_one;
88 88
      bool mandatory;
89 89
      GroupData() :only_one(false), mandatory(false) {}
90 90
    };
91 91
      
92 92
    typedef std::map<std::string,GroupData> Groups;
93 93
    Groups _groups;
94 94

	
95 95
    struct OtherArg
96 96
    {
97 97
      std::string name;
98 98
      std::string help;
99 99
      OtherArg(std::string n, std::string h) :name(n), help(h) {}
100 100

	
101 101
    };
102 102
      
103 103
    std::vector<OtherArg> _others_help;
104 104
    std::vector<std::string> _file_args;
105 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);
106 119
    
107 120
  public:
108 121

	
109 122
    ///\e
110 123
    ArgParser(int argc, const char **argv);
111 124

	
112 125
    ~ArgParser();
113 126

	
114 127
    ///Add a new integer type option
115 128

	
116 129
    ///\param name The name of the option. The leading '-' must be omitted.
117 130
    ///\param help A help string.
118 131
    ///\retval value The value of the argument will be written to this variable.
119 132
    ///\param obl Indicate if the option is mandatory.
120 133
    ArgParser &intOption(const std::string &name,
121 134
		    const std::string &help,
122 135
		    int value=0, bool obl=false);
123 136

	
124 137
    ///Add a new floating point type option
125 138

	
126 139
    ///\param name The name of the option. The leading '-' must be omitted.
127 140
    ///\param help A help string.
128 141
    ///\retval value The value of the argument will be written to this variable.
129 142
    ///\param obl Indicate if the option is mandatory.
130 143
    ArgParser &doubleOption(const std::string &name,
131 144
		      const std::string &help,
132 145
		      double value=0, bool obl=false);
133 146

	
134 147
    ///Add a new bool type option
135 148

	
136 149
    ///\param name The name of the option. The leading '-' must be omitted.
137 150
    ///\param help A help string.
138 151
    ///\retval value The value of the argument will be written to this variable.
139 152
    ///\param obl Indicate if the option is mandatory.
140 153
    ////\note A mandatory bool obtion is of very little use.)
141 154
    ArgParser &boolOption(const std::string &name,
142 155
		      const std::string &help,
143 156
		      bool value=false, bool obl=false);
144 157

	
145 158
    ///Add a new string type option
146 159

	
147 160
    ///\param name The name of the option. The leading '-' must be omitted.
148 161
    ///\param help A help string.
149 162
    ///\retval value The value of the argument will be written to this variable.
150 163
    ///\param obl Indicate if the option is mandatory.
151 164
    ArgParser &stringOption(const std::string &name,
152 165
		      const std::string &help,
153 166
		      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 167

	
166 168
    ///\name Options with an external strorage.
167 169
    ///Using this functions, the value of the option will be directly written
168 170
    ///into a variable once the option appears in the command line.
169 171

	
170 172
    ///@{
171 173

	
172 174
    ///Add a new integer type option with a storage reference
173 175

	
174 176
    ///\param name The name of the option. The leading '-' must be omitted.
175 177
    ///\param help A help string.
176 178
    ///\retval ref The value of the argument will be written to this variable.
177 179
    ///\param obl Indicate if the option is mandatory.
178 180
    ArgParser &refOption(const std::string &name,
179 181
		    const std::string &help,
180 182
		    int &ref, bool obl=false);
181 183

	
182 184
    ///Add a new floating type option with a storage reference
183 185

	
184 186
    ///\param name The name of the option. The leading '-' must be omitted.
185 187
    ///\param help A help string.
186 188
    ///\retval ref The value of the argument will be written to this variable.
187 189
    ///\param obl Indicate if the option is mandatory.
188 190
    ArgParser &refOption(const std::string &name,
189 191
		      const std::string &help,
190 192
		      double &ref, bool obl=false);
191 193

	
192 194
    ///Add a new bool type option with a storage reference
193 195

	
194 196
    ///\param name The name of the option. The leading '-' must be omitted.
195 197
    ///\param help A help string.
196 198
    ///\retval ref The value of the argument will be written to this variable.
197 199
    ///\param obl Indicate if the option is mandatory.
198 200
    ////\note A mandatory bool obtion is of very little use.)
199 201
    ArgParser &refOption(const std::string &name,
200 202
		      const std::string &help,
201 203
		      bool &ref, bool obl=false);
202 204

	
203 205
    ///Add a new string type option with a storage reference
204 206

	
205 207
    ///\param name The name of the option. The leading '-' must be omitted.
206 208
    ///\param help A help string.
207 209
    ///\retval ref The value of the argument will be written to this variable.
208 210
    ///\param obl Indicate if the option is mandatory.
209 211
    ArgParser &refOption(const std::string &name,
210 212
		      const std::string &help,
211 213
		      std::string &ref, bool obl=false);
212 214
    
213 215
    ///@}
214 216

	
215 217
    ///\name Option Groups and Synonyms
216 218
    ///
217 219
    
218 220
    ///@{
219 221

	
220 222
    ///Boundle some options into a group
221 223

	
222 224
    /// You can group some option by calling this function repeatedly for each
223 225
    /// option to be grupped with the same groupname.
224 226
    ///\param group The group name
225 227
    ///\param opt The option name
226 228
    ArgParser &optionGroup(const std::string &group,
227 229
			   const std::string &opt);
228 230

	
229 231
    ///Make the members of a group exclusive
230 232

	
231 233
    ///If you call this function for a group, than at most one of them can be
232 234
    ///given at the same time
233 235
    ArgParser &onlyOneGroup(const std::string &group);
234 236
  
235 237
    ///Make a group mandatory
236 238

	
237 239
    ///Using this function, at least one of the members of \c group
238 240
    ///must be given.
239 241
    ArgParser &mandatoryGroup(const std::string &group);
240 242
    
241 243
    ///Create synonym to an option
242 244

	
243 245
    ///With this function you can create a sysnonym called \c sys of the
244 246
    ///option \c opt.
245 247
    ArgParser &synonym(const std::string &syn,
246 248
			   const std::string &opt);
247 249
    
248 250
    ///@}
249 251

	
250 252
    ///Give help string for non-parsed arguments.
251 253

	
252 254
    ///With this function you can give help string for non-parsed arguments.
253 255
    ///the parameter \c name will be printed in the short usage line, while
254 256
    ///\c help gives a more detailed description.
255 257
    ArgParser &other(const std::string &name,
256 258
		     const std::string &help="");
257 259
    
258 260
    ///Non option type arguments.
259 261

	
260 262
    ///Gives back a reference to a vector consisting of the program arguments
261 263
    ///not starting with a '-' character.
262 264
    std::vector<std::string> &files() { return _file_args; }
263 265

	
264 266
    ///Give back the command name (the 0th argument)
265 267
    const std::string &commandName() { return _command_name; }
266 268

	
267 269
    void show(std::ostream &os,Opts::iterator i);
268 270
    void show(std::ostream &os,Groups::iterator i);
269 271
    void showHelp(Opts::iterator i);
270 272
    void showHelp(std::vector<OtherArg>::iterator i);
271 273
    void shortHelp();
272 274
    void showHelp();
273 275

	
274 276
    void unknownOpt(std::string arg);
275 277

	
276 278
    void requiresValue(std::string arg, OptType t);
277 279
    void checkMandatories();
278 280
    
279 281
    ///Start the parsing process
280 282
    ArgParser &parse();
281 283

	
282 284
    /// Synonym for parse()
283 285
    ArgParser &run() 
284 286
    {
285 287
      return parse();
286 288
    }
287 289
    
288 290
    ///Check if an opion has been given to the command.
289 291
    bool given(std::string op) 
290 292
    {
291 293
      Opts::iterator i = _opts.find(op);
292 294
      return i!=_opts.end()?i->second.set:false;
293 295
    }
294 296

	
295 297

	
296 298
    ///Magic type for operator[]
297 299
    
298 300
    ///This is the type of the return value of ArgParser::operator[]().
299 301
    ///It automatically converts to int, double, bool or std::string if
300 302
    ///the type of the option matches, otherwise it throws an exception.
301 303
    ///(i.e. it performs runtime type checking).
302 304
    class RefType 
303 305
    {
304 306
      ArgParser &_parser;
305 307
      std::string _name;
306 308
    public:
307 309
      ///\e
308 310
      RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
309 311
      ///\e
310 312
      operator bool() 
311 313
      {
312 314
	Opts::iterator i = _parser._opts.find(_name);
313 315
	LEMON_ASSERT(i==_parser._opts.end(),
314 316
		     std::string()+"Unkown option: '"+_name+"'");
315 317
	LEMON_ASSERT(i->second.type!=ArgParser::BOOL,
316 318
		     std::string()+"'"+_name+"' is a bool option");
317 319
	return *(i->second.bool_p);
318 320
      }
319 321
      ///\e
320 322
      operator std::string()
321 323
      {
322 324
	Opts::iterator i = _parser._opts.find(_name);
323 325
	LEMON_ASSERT(i==_parser._opts.end(),
324 326
		     std::string()+"Unkown option: '"+_name+"'");
325 327
	LEMON_ASSERT(i->second.type!=ArgParser::STRING,
326 328
		     std::string()+"'"+_name+"' is a string option");
327 329
	return *(i->second.string_p);
328 330
      }
329 331
      ///\e
330 332
      operator double() 
331 333
      {
332 334
	Opts::iterator i = _parser._opts.find(_name);
333 335
	LEMON_ASSERT(i==_parser._opts.end(),
334 336
		     std::string()+"Unkown option: '"+_name+"'");
335 337
	LEMON_ASSERT(i->second.type!=ArgParser::DOUBLE &&
336 338
		     i->second.type!=ArgParser::INTEGER,
337 339
		     std::string()+"'"+_name+"' is a floating point option");
338 340
	return i->second.type==ArgParser::DOUBLE ?
339 341
	  *(i->second.double_p) : *(i->second.int_p);
340 342
      }
341 343
      ///\e
342 344
      operator int() 
343 345
      {
344 346
	Opts::iterator i = _parser._opts.find(_name);
345 347
	LEMON_ASSERT(i==_parser._opts.end(),
346 348
		     std::string()+"Unkown option: '"+_name+"'");
347 349
	LEMON_ASSERT(i->second.type!=ArgParser::INTEGER,
348 350
		     std::string()+"'"+_name+"' is an integer option");
349 351
	return *(i->second.int_p);
350 352
      }
351 353

	
352 354
    };
353 355

	
354 356
    ///Give back the value of an option
355 357
    
356 358
    ///Give back the value of an option
0 comments (0 inline)