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