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