tlx
cmdline_parser.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 * tlx/cmdline_parser.hpp
3 *
4 * Part of tlx - http://panthema.net/tlx
5 *
6 * Copyright (C) 2013-2015 Timo Bingmann <tb@panthema.net>
7 *
8 * All rights reserved. Published under the Boost Software License, Version 1.0
9 ******************************************************************************/
10
11#ifndef TLX_CMDLINE_PARSER_HEADER
12#define TLX_CMDLINE_PARSER_HEADER
13
14#include <iosfwd>
15#include <string>
16#include <vector>
17
18namespace tlx {
19
20/*!
21
22Command line parser which automatically fills variables and prints nice usage
23messages.
24
25This is a straightforward command line parser in C++, which will recognize short
26options -s, long options --long and parameters, both required and optional. It
27will automatically parse integers and <b>byte sizes</b> with SI/IEC suffixes
28(e.g. 1 GiB). It also works with lists of strings, e.g. multiple filenames.
29
30\snippet tests/cmdline_parser_example.cpp example
31
32When running the program above without arguments, it will print:
33\verbatim
34$ ./tlx_cmdline_parser_example
35Missing required argument for parameter 'filename'
36
37Usage: ./tlx_cmdline_parser_example [options] <filename>
38
39This may some day be a useful program, which solves many serious problems of
40the real world and achives global peace.
41
42Author: Timo Bingmann <tb@panthema.net>
43
44Parameters:
45 filename A filename to process
46Options:
47 -r, --rounds N Run N rounds of the experiment.
48 -s, --size Number of bytes to process.
49\endverbatim
50
51Nice output, notice the line wrapping of the description and formatting of
52parameters and arguments. These too are wrapped if the description is too long.
53
54We now try to give the program some arguments:
55\verbatim
56$ ./tlx_cmdline_parser_example -s 2GiB -r 42 /dev/null
57Option -s, --size set to 2147483648.
58Option -r, --rounds N set to 42.
59Parameter filename set to "/dev/null".
60Command line parsed okay.
61Parameters:
62 filename (string) "/dev/null"
63Options:
64 -r, --rounds N (unsigned integer) 42
65 -s, --size (bytes) 2147483648
66\endverbatim
67
68The output shows pretty much what happens. The command line parser is by default
69in a verbose mode outputting all arguments and values parsed. The debug summary
70shows to have values the corresponding variables were set.
71
72One feature worth naming is that the parser also supports lists of strings,
73i.e. \c std::vector<std::string> via \ref CmdlineParser::add_param_stringlist()
74and similar.
75*/
76
77class CmdlineParser
78{
79private:
80 // forward declaration of Argument classes
81 class Argument;
82 class ArgumentBool;
83 class ArgumentInt;
84 class ArgumentUnsigned;
85 class ArgumentSizeT;
86 class ArgumentFloat;
87 class ArgumentDouble;
88 class ArgumentBytes32;
89 class ArgumentBytes64;
90 class ArgumentString;
92
93private:
94 //! option and parameter list type
95 using ArgumentList = std::vector<Argument*>;
96
97 //! list of options available
99 //! list of parameters, both required and optional
101
102 //! formatting width for options, '-s, --switch <#>'
104 //! formatting width for parameters, 'param <#>'
106
107 //! argv[0] for usage.
108 const char* program_name_ = nullptr;
109
110 //! verbose processing of arguments
111 bool verbose_process_ = false;
112
113 //! user set description of program, will be wrapped
114 std::string description_;
115 //! user set author of program, will be wrapped
116 std::string author_;
117
118 //! set line wrap length
119 unsigned int line_wrap_ = 80;
120
121 //! maximum length of a type_name() result
122 static constexpr int max_type_name_ = 16;
123
124private:
125 //! update maximum formatting width for new option
126 void calc_option_max(const Argument* arg);
127
128 //! update maximum formatting width for new parameter
129 void calc_param_max(const Argument* arg);
130
131public:
132 //! Wrap a long string at spaces into lines. Prefix is added
133 //! unconditionally to each line. Lines are wrapped after wraplen
134 //! characters if possible.
135 static void output_wrap(
136 std::ostream& os, const std::string& text,
137 size_t wraplen, size_t indent_first = 0, size_t indent_rest = 0,
138 size_t current = 0, size_t indent_newline = 0);
139
140public:
141 //! Constructor
143
144 //! Delete all added arguments
146
147 //! Set description of program, text will be wrapped
148 void set_description(const std::string& description);
149
150 //! Set author of program, will be wrapped.
151 void set_author(const std::string& author);
152
153 //! Set verbose processing of command line arguments
154 void set_verbose_process(bool verbose_process);
155
156 /**************************************************************************/
157
158 //! \name Add Option with short -k, --longkey, and description.
159 //! \{
160
161 //! add boolean option flag -key, --longkey with description and store to
162 //! dest
163 void add_bool(char key, const std::string& longkey, bool& dest, // NOLINT
164 const std::string& desc);
165
166 //! add boolean option flag -key, --longkey with description and store to
167 //! dest. identical to add_bool()
168 void add_flag(char key, const std::string& longkey, bool& dest, // NOLINT
169 const std::string& desc);
170
171 //! add signed integer option -key, --longkey with description and store to
172 //! dest
173 void add_int(char key, const std::string& longkey, int& dest, // NOLINT
174 const std::string& desc);
175
176 //! add unsigned integer option -key, --longkey with description and store
177 //! to dest
178 void add_unsigned(char key, const std::string& longkey,
179 unsigned int& dest, const std::string& desc); // NOLINT
180
181 //! add unsigned integer option -key, --longkey with description and store
182 //! to dest. identical to add_unsigned()
183 void add_uint(char key, const std::string& longkey,
184 unsigned int& dest, const std::string& desc); // NOLINT
185
186 //! add size_t option -key, --longkey with description and store to dest
187 void add_size_t(char key, const std::string& longkey,
188 size_t& dest, const std::string& desc); // NOLINT
189
190 //! add float option -key, --longkey with description and store to dest
191 void add_float(char key, const std::string& longkey,
192 float& dest, const std::string& desc); // NOLINT
193
194 //! add double option -key, --longkey with description and store to dest
195 void add_double(char key, const std::string& longkey,
196 double& dest, const std::string& desc); // NOLINT
197
198 //! add SI/IEC suffixes byte size option -key, --longkey and store to 32-bit
199 //! dest
200 void add_bytes(char key, const std::string& longkey,
201 uint32_t& dest, const std::string& desc); // NOLINT
202
203 //! add SI/IEC suffixes byte size option -key, --longkey and store to 64-bit
204 //! dest
205 void add_bytes(char key, const std::string& longkey,
206 uint64_t& dest, const std::string& desc); // NOLINT
207
208 //! add string option -key, --longkey and store to dest
209 void add_string(char key, const std::string& longkey,
210 std::string& dest, const std::string& desc); // NOLINT
211
212 //! add string list option -key, --longkey and store to dest
213 void add_stringlist(
214 char key, const std::string& longkey,
215 std::vector<std::string>& dest, const std::string& desc); // NOLINT
216
217 //! \}
218
219 /**************************************************************************/
220
221 //! \name Add Option with --longkey and description.
222 //! \{
223
224 //! add boolean option flag --longkey with description and store to dest
225 void add_bool(const std::string& longkey, bool& dest, // NOLINT
226 const std::string& desc);
227
228 //! add boolean option flag --longkey with description and store to
229 //! dest. identical to add_bool()
230 void add_flag(const std::string& longkey, bool& dest, // NOLINT
231 const std::string& desc);
232
233 //! add signed integer option --longkey with description and store to dest
234 void add_int(const std::string& longkey, int& dest, // NOLINT
235 const std::string& desc);
236
237 //! add unsigned integer option --longkey with description and store to dest
238 void add_unsigned(const std::string& longkey,
239 unsigned int& dest, const std::string& desc); // NOLINT
240
241 //! add unsigned integer option --longkey with description and store to
242 //! dest. identical to add_unsigned()
243 void add_uint(const std::string& longkey,
244 unsigned int& dest, const std::string& desc); // NOLINT
245
246 //! add size_t option --longkey with description and store to dest
247 void add_size_t(const std::string& longkey,
248 size_t& dest, const std::string& desc); // NOLINT
249
250 //! add float option --longkey with description and store to dest
251 void add_float(const std::string& longkey,
252 float& dest, const std::string& desc); // NOLINT
253
254 //! add double option --longkey with description and store to dest
255 void add_double(const std::string& longkey,
256 double& dest, const std::string& desc); // NOLINT
257
258 //! add SI/IEC suffixes byte size option --longkey and store to 32-bit dest
259 void add_bytes(const std::string& longkey,
260 uint32_t& dest, const std::string& desc); // NOLINT
261
262 //! add SI/IEC suffixes byte size option --longkey and store to 64-bit dest
263 void add_bytes(const std::string& longkey,
264 uint64_t& dest, const std::string& desc); // NOLINT
265
266 //! add string option --longkey and store to dest
267 void add_string(const std::string& longkey,
268 std::string& dest, const std::string& desc); // NOLINT
269
270 //! add string list option --longkey and store to dest
271 void add_stringlist(
272 const std::string& longkey,
273 std::vector<std::string>& dest, const std::string& desc); // NOLINT
274
275 //! \}
276
277 /**************************************************************************/
278
279 //! \name Add Option with short -k, --longkey, [keytype], and description.
280 //! \{
281
282 //! add boolean option flag -key, --longkey [keytype] with description and
283 //! store to dest
284 void add_bool(
285 char key, const std::string& longkey,
286 const std::string& keytype, bool& dest, // NOLINT
287 const std::string& desc);
288
289 //! add boolean option flag -key, --longkey [keytype] with description and
290 //! store to dest. identical to add_bool()
291 void add_flag(
292 char key, const std::string& longkey,
293 const std::string& keytype, bool& dest, // NOLINT
294 const std::string& desc);
295
296 //! add signed integer option -key, --longkey [keytype] with description
297 //! and store to dest
298 void add_int(
299 char key, const std::string& longkey,
300 const std::string& keytype, int& dest, // NOLINT
301 const std::string& desc);
302
303 //! add unsigned integer option -key, --longkey [keytype] with description
304 //! and store to dest
305 void add_unsigned(
306 char key, const std::string& longkey,
307 const std::string& keytype, unsigned int& dest, // NOLINT
308 const std::string& desc);
309
310 //! add unsigned integer option -key, --longkey [keytype] with description
311 //! and store to dest. identical to add_unsigned()
312 void add_uint(
313 char key, const std::string& longkey,
314 const std::string& keytype, unsigned int& dest, // NOLINT
315 const std::string& desc);
316
317 //! add size_t option -key, --longkey [keytype] with description and store
318 //! to dest
319 void add_size_t(
320 char key, const std::string& longkey,
321 const std::string& keytype, size_t& dest, // NOLINT
322 const std::string& desc);
323
324 //! add float option -key, --longkey [keytype] with description and store
325 //! to dest
326 void add_float(
327 char key, const std::string& longkey,
328 const std::string& keytype, float& dest, // NOLINT
329 const std::string& desc);
330
331 //! add double option -key, --longkey [keytype] with description and store
332 //! to dest
333 void add_double(
334 char key, const std::string& longkey,
335 const std::string& keytype, double& dest, // NOLINT
336 const std::string& desc);
337
338 //! add SI/IEC suffixes byte size option -key, --longkey [keytype] and
339 //! store to 64-bit dest
340 void add_bytes(
341 char key, const std::string& longkey,
342 const std::string& keytype, uint32_t& dest, // NOLINT
343 const std::string& desc);
344
345 //! add SI/IEC suffixes byte size option -key, --longkey [keytype] and
346 //! store to 64-bit dest
347 void add_bytes(
348 char key, const std::string& longkey,
349 const std::string& keytype, uint64_t& dest, // NOLINT
350 const std::string& desc);
351
352 //! add string option -key, --longkey [keytype] and store to dest
353 void add_string(
354 char key, const std::string& longkey,
355 const std::string& keytype, std::string& dest, // NOLINT
356 const std::string& desc);
357
358 //! add string list option -key, --longkey [keytype] and store to dest
359 void add_stringlist(
360 char key, const std::string& longkey,
361 const std::string& keytype, std::vector<std::string>& dest, // NOLINT
362 const std::string& desc);
363
364 //! \}
365
366 // ************************************************************************
367
368 //! \name Add Required Parameter [name] with description.
369 //! \{
370
371 //! add signed integer parameter [name] with description and store to dest
372 void add_param_int(
373 const std::string& name, int& dest, const std::string& desc); // NOLINT
374
375 //! add unsigned integer parameter [name] with description and store to dest
377 const std::string& name, unsigned int& dest, // NOLINT
378 const std::string& desc);
379
380 //! add unsigned integer parameter [name] with description and store to
381 //! dest. identical to add_unsigned()
382 void add_param_uint(
383 const std::string& name, unsigned int& dest, // NOLINT
384 const std::string& desc);
385
386 //! add size_t parameter [name] with description and store to dest
387 void add_param_size_t(
388 const std::string& name, size_t& dest, // NOLINT
389 const std::string& desc);
390
391 //! add float parameter [name] with description and store to dest
392 void add_param_float(
393 const std::string& name, float& dest, // NOLINT
394 const std::string& desc);
395
396 //! add double parameter [name] with description and store to dest
397 void add_param_double(
398 const std::string& name, double& dest, // NOLINT
399 const std::string& desc);
400
401 //! add SI/IEC suffixes byte size parameter [name] with description and
402 //! store to dest
403 void add_param_bytes(
404 const std::string& name, uint32_t& dest, // NOLINT
405 const std::string& desc);
406
407 //! add SI/IEC suffixes byte size parameter [name] with description and
408 //! store to dest
409 void add_param_bytes(
410 const std::string& name, uint64_t& dest, // NOLINT
411 const std::string& desc);
412
413 //! add string parameter [name] with description and store to dest
414 void add_param_string(
415 const std::string& name, std::string& dest, // NOLINT
416 const std::string& desc);
417
418 //! add string list parameter [name] with description and store to dest.
419 //! \warning this parameter must be last, as it will gobble all non-option
420 //! arguments!
422 const std::string& name, std::vector<std::string>& dest, // NOLINT
423 const std::string& desc);
424
425 //! \}
426
427 /**************************************************************************/
428
429 //! \name Add Optional Parameter [name] with description.
430 //! \{
431
432 //! add optional signed integer parameter [name] with description and store
433 //! to dest
435 const std::string& name, int& dest, const std::string& desc); // NOLINT
436
437 //! add optional unsigned integer parameter [name] with description and
438 //! store to dest
440 const std::string& name, unsigned int& dest, // NOLINT
441 const std::string& desc);
442
443 //! add optional unsigned integer parameter [name] with description and
444 //! store to dest. identical to add_unsigned()
446 const std::string& name, unsigned int& dest, // NOLINT
447 const std::string& desc);
448
449 //! add optional size_t parameter [name] with description and store to dest
451 const std::string& name, size_t& dest, // NOLINT
452 const std::string& desc);
453
454 //! add optional float parameter [name] with description and store to dest
456 const std::string& name, float& dest, // NOLINT
457 const std::string& desc);
458
459 //! add optional double parameter [name] with description and store to dest
461 const std::string& name, double& dest, // NOLINT
462 const std::string& desc);
463
464 //! add optional SI/IEC suffixes byte size parameter [name] with
465 //! description and store to dest
467 const std::string& name, uint32_t& dest, // NOLINT
468 const std::string& desc);
469
470 //! add optional SI/IEC suffixes byte size parameter [name] with
471 //! description and store to dest
473 const std::string& name, uint64_t& dest, // NOLINT
474 const std::string& desc);
475
476 //! add optional string parameter [name] with description and store to dest
478 const std::string& name, std::string& dest, // NOLINT
479 const std::string& desc);
480
481 //! add optional string parameter [name] with description and store to dest
482 //! \warning this parameter must be last, as it will gobble all non-option
483 //! arguments!
485 const std::string& name, std::vector<std::string>& dest, // NOLINT
486 const std::string& desc);
487
488 //! \}
489
490 /**************************************************************************/
491
492 //! output nicely formatted usage information including description of all
493 //! parameters and options.
494 void print_usage(std::ostream& os);
495
496 //! output to std::cout nicely formatted usage information including
497 //! description of all parameters and options.
498 void print_usage();
499
500private:
501 //! print error about option.
502 void print_option_error(int argc, const char* const* argv,
503 const Argument* arg, std::ostream& os);
504
505 //! print error about parameter.
506 void print_param_error(int argc, const char* const* argv,
507 const Argument* arg, std::ostream& os);
508
509public:
510 //! sort options by key (but not the positional parameters)
512
513 //! parse command line options as specified by the options and parameters
514 //! added.
515 //! \return true if command line is okay and all required parameters are
516 //! present.
517 bool process(
518 int argc, const char* const* argv, std::ostream& os);
519
520 //! parse command line options as specified by the options and parameters
521 //! added.
522 //! \return true if command line is okay and all required parameters are
523 //! present.
524 bool process(int argc, const char* const* argv);
525
526 //! print nicely formatted result of processing
527 void print_result(std::ostream& os);
528
529 //! print nicely formatted result of processing to std::cout
530 void print_result();
531};
532
533} // namespace tlx
534
535#endif // !TLX_CMDLINE_PARSER_HEADER
536
537/******************************************************************************/
base class of all options and parameters
ArgumentBytes32(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, uint32_t &dest)
contructor filling most attributes
void add_flag(char key, const std::string &longkey, bool &dest, const std::string &desc)
add boolean option flag -key, –longkey with description and store to dest.
void add_opt_param_uint(const std::string &name, unsigned int &dest, const std::string &desc)
add optional unsigned integer parameter [name] with description and store to dest.
ArgumentSizeT(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, size_t &dest)
contructor filling most attributes
void print_param_error(int argc, const char *const *argv, const Argument *arg, std::ostream &os)
print error about parameter.
void add_size_t(char key, const std::string &longkey, size_t &dest, const std::string &desc)
add size_t option -key, –longkey with description and store to dest
void add_param_bytes(const std::string &name, uint32_t &dest, const std::string &desc)
add SI/IEC suffixes byte size parameter [name] with description and store to dest
ArgumentList option_list_
list of options available
void set_author(const std::string &author)
Set author of program, will be wrapped.
void add_param_stringlist(const std::string &name, std::vector< std::string > &dest, const std::string &desc)
add string list parameter [name] with description and store to dest.
size_t option_max_width_
formatting width for options, '-s, –switch <#>'
void add_bool(char key, const std::string &longkey, bool &dest, const std::string &desc)
add boolean option flag -key, –longkey with description and store to dest
CmdlineParser & sort()
sort options by key (but not the positional parameters)
void add_opt_param_int(const std::string &name, int &dest, const std::string &desc)
add optional signed integer parameter [name] with description and store to dest
void add_param_size_t(const std::string &name, size_t &dest, const std::string &desc)
add size_t parameter [name] with description and store to dest
void add_param_uint(const std::string &name, unsigned int &dest, const std::string &desc)
add unsigned integer parameter [name] with description and store to dest.
ArgumentInt(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, int &dest)
contructor filling most attributes
const char * program_name_
argv[0] for usage.
std::vector< Argument * > ArgumentList
option and parameter list type
CmdlineParser()
Constructor.
void set_verbose_process(bool verbose_process)
Set verbose processing of command line arguments.
void add_opt_param_bytes(const std::string &name, uint32_t &dest, const std::string &desc)
add optional SI/IEC suffixes byte size parameter [name] with description and store to dest
virtual bool process(int &argc, const char *const *&argv)=0
process one item from command line for this argument
unsigned int line_wrap_
set line wrap length
void add_double(char key, const std::string &longkey, double &dest, const std::string &desc)
add double option -key, –longkey with description and store to dest
void add_opt_param_float(const std::string &name, float &dest, const std::string &desc)
add optional float parameter [name] with description and store to dest
static void output_wrap(std::ostream &os, const std::string &text, size_t wraplen, size_t indent_first=0, size_t indent_rest=0, size_t current=0, size_t indent_newline=0)
Wrap a long string at spaces into lines.
void print_result()
print nicely formatted result of processing to std::cout
bool verbose_process_
verbose processing of arguments
ArgumentBytes64(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, uint64_t &dest)
contructor filling most attributes
ArgumentDouble(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, double &dest)
contructor filling most attributes
void add_opt_param_size_t(const std::string &name, size_t &dest, const std::string &desc)
add optional size_t parameter [name] with description and store to dest
ArgumentList param_list_
list of parameters, both required and optional
void calc_param_max(const Argument *arg)
update maximum formatting width for new parameter
void add_opt_param_double(const std::string &name, double &dest, const std::string &desc)
add optional double parameter [name] with description and store to dest
void add_param_double(const std::string &name, double &dest, const std::string &desc)
add double parameter [name] with description and store to dest
std::string author_
user set author of program, will be wrapped
void set_description(const std::string &description)
Set description of program, text will be wrapped.
ArgumentBool(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, bool &dest)
contructor filling most attributes
void add_bytes(char key, const std::string &longkey, uint32_t &dest, const std::string &desc)
add SI/IEC suffixes byte size option -key, –longkey and store to 32-bit dest
~CmdlineParser()
Delete all added arguments.
ArgumentUnsigned(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, unsigned int &dest)
contructor filling most attributes
void add_param_unsigned(const std::string &name, unsigned int &dest, const std::string &desc)
add unsigned integer parameter [name] with description and store to dest
void add_int(char key, const std::string &longkey, int &dest, const std::string &desc)
add signed integer option -key, –longkey with description and store to dest
void add_param_string(const std::string &name, std::string &dest, const std::string &desc)
add string parameter [name] with description and store to dest
void add_opt_param_unsigned(const std::string &name, unsigned int &dest, const std::string &desc)
add optional unsigned integer parameter [name] with description and store to dest
void add_param_int(const std::string &name, int &dest, const std::string &desc)
add signed integer parameter [name] with description and store to dest
void add_opt_param_string(const std::string &name, std::string &dest, const std::string &desc)
add optional string parameter [name] with description and store to dest
void add_unsigned(char key, const std::string &longkey, unsigned int &dest, const std::string &desc)
add unsigned integer option -key, –longkey with description and store to dest
ArgumentStringlist(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, std::vector< std::string > &dest)
contructor filling most attributes
void print_option_error(int argc, const char *const *argv, const Argument *arg, std::ostream &os)
print error about option.
void add_string(char key, const std::string &longkey, std::string &dest, const std::string &desc)
add string option -key, –longkey and store to dest
void add_float(char key, const std::string &longkey, float &dest, const std::string &desc)
add float option -key, –longkey with description and store to dest
Argument(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required)
contructor filling most attributes
void add_param_float(const std::string &name, float &dest, const std::string &desc)
add float parameter [name] with description and store to dest
ArgumentFloat(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, float &dest)
contructor filling most attributes
void add_opt_param_stringlist(const std::string &name, std::vector< std::string > &dest, const std::string &desc)
add optional string parameter [name] with description and store to dest
void add_stringlist(char key, const std::string &longkey, std::vector< std::string > &dest, const std::string &desc)
add string list option -key, –longkey and store to dest
static constexpr int max_type_name_
maximum length of a type_name() result
void print_usage()
output to std::cout nicely formatted usage information including description of all parameters and op...
std::string description_
user set description of program, will be wrapped
void add_uint(char key, const std::string &longkey, unsigned int &dest, const std::string &desc)
add unsigned integer option -key, –longkey with description and store to dest.
size_t param_max_width_
formatting width for parameters, 'param <#>'
ArgumentString(char key, const std::string &longkey, const std::string &keytype, const std::string &desc, bool required, std::string &dest)
contructor filling most attributes
void calc_option_max(const Argument *arg)
update maximum formatting width for new option