Thrill  0.1
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 <[email protected]>
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 
18 namespace tlx {
19 
20 /*!
21 
22 Command line parser which automatically fills variables and prints nice usage
23 messages.
24 
25 This is a straightforward command line parser in C++, which will recognize short
26 options -s, long options --long and parameters, both required and optional. It
27 will 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 
32 When running the program above without arguments, it will print:
33 \verbatim
34 $ ./tlx_cmdline_parser_example
35 Missing required argument for parameter 'filename'
36 
37 Usage: ./tlx_cmdline_parser_example [options] <filename>
38 
39 This may some day be a useful program, which solves many serious problems of
40 the real world and achives global peace.
41 
42 Author: Timo Bingmann <[email protected]>
43 
44 Parameters:
45  filename A filename to process
46 Options:
47  -r, --rounds N Run N rounds of the experiment.
48  -s, --size Number of bytes to process.
49 \endverbatim
50 
51 Nice output, notice the line wrapping of the description and formatting of
52 parameters and arguments. These too are wrapped if the description is too long.
53 
54 We now try to give the program some arguments:
55 \verbatim
56 $ ./tlx_cmdline_parser_example -s 2GiB -r 42 /dev/null
57 Option -s, --size set to 2147483648.
58 Option -r, --rounds N set to 42.
59 Parameter filename set to "/dev/null".
60 Command line parsed okay.
61 Parameters:
62  filename (string) "/dev/null"
63 Options:
64  -r, --rounds N (unsigned integer) 42
65  -s, --size (bytes) 2147483648
66 \endverbatim
67 
68 The output shows pretty much what happens. The command line parser is by default
69 in a verbose mode outputting all arguments and values parsed. The debug summary
70 shows to have values the corresponding variables were set.
71 
72 One feature worth naming is that the parser also supports lists of strings,
73 i.e. \c std::vector<std::string> via \ref CmdlineParser::add_param_stringlist()
74 and similar.
75 */
76 
78 {
79 private:
80  // forward declaration of Argument classes
81  struct Argument;
82  struct ArgumentBool;
83  struct ArgumentInt;
84  struct ArgumentUnsigned;
85  struct ArgumentSizeT;
86  struct ArgumentFloat;
87  struct ArgumentDouble;
88  struct ArgumentBytes32;
89  struct ArgumentBytes64;
90  struct ArgumentString;
91  struct ArgumentStringlist;
92 
93 private:
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 <#>'
103  size_t option_max_width_ = 8;
104  //! formatting width for parameters, 'param <#>'
105  size_t param_max_width_ = 8;
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
115  //! user set author of program, will be wrapped
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 
124 private:
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 
131 public:
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 
140 public:
141  //! Constructor
142  CmdlineParser();
143 
144  //! Delete all added arguments
145  ~CmdlineParser();
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
376  void add_param_unsigned(
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
434  void add_opt_param_int(
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()
445  void add_opt_param_uint(
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
455  void add_opt_param_float(
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
466  void add_opt_param_bytes(
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
472  void add_opt_param_bytes(
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 
500 private:
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 
509 public:
510  //! sort options by key (but not the positional parameters)
511  CmdlineParser& sort();
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 /******************************************************************************/
void add_opt_param_bytes(const std::string &name, uint32_t &dest, const std::string &desc)
void add_unsigned(char key, const std::string &longkey, unsigned int &dest, const std::string &desc)
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)
void add_uint(char key, const std::string &longkey, unsigned int &dest, const std::string &desc)
CmdlineParser & sort()
sort options by key (but not the positional parameters)
void add_param_double(const std::string &name, double &dest, const std::string &desc)
add double parameter [name] with description and store to dest
ArgumentList option_list_
list of options available
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 set_description(const std::string &description)
Set description of program, text will be wrapped.
~CmdlineParser()
Delete all added arguments.
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 print_option_error(int argc, const char *const *argv, const Argument *arg, std::ostream &os)
print error about option.
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
bool verbose_process_
verbose processing of arguments
void add_opt_param_uint(const std::string &name, unsigned int &dest, const std::string &desc)
void calc_option_max(const Argument *arg)
update maximum formatting width for new option
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_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 calc_param_max(const Argument *arg)
update maximum formatting width for new parameter
void add_opt_param_unsigned(const std::string &name, unsigned int &dest, const std::string &desc)
void print_result()
print nicely formatted result of processing to std::cout
ArgumentList param_list_
list of parameters, both required and optional
void add_param_bytes(const std::string &name, uint32_t &dest, const std::string &desc)
CmdlineParser()
Constructor.
void add_param_uint(const std::string &name, unsigned int &dest, const std::string &desc)
void add_bytes(char key, const std::string &longkey, uint32_t &dest, const std::string &desc)
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 constexpr int max_type_name_
maximum length of a type_name() result
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
std::vector< Argument * > ArgumentList
option and parameter list type
const char * program_name_
argv[0] for usage.
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
std::string description_
user set description of program, will be wrapped
Command line parser which automatically fills variables and prints nice usage messages.
size_t param_max_width_
formatting width for parameters, &#39;param <#>&#39;
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_string(char key, const std::string &longkey, std::string &dest, const std::string &desc)
add string option -key, –longkey and store to dest
std::string author_
user set author of program, will be wrapped
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_param_float(const std::string &name, float &dest, const std::string &desc)
add float parameter [name] with description and store to dest
void add_param_stringlist(const std::string &name, std::vector< std::string > &dest, const std::string &desc)
void add_opt_param_int(const std::string &name, int &dest, const std::string &desc)
void set_verbose_process(bool verbose_process)
Set verbose processing of command line arguments.
void add_bool(char key, const std::string &longkey, bool &dest, const std::string &desc)
size_t option_max_width_
formatting width for options, &#39;-s, –switch <#>&#39;
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
void add_opt_param_stringlist(const std::string &name, std::vector< std::string > &dest, const std::string &desc)
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
void set_author(const std::string &author)
Set author of program, will be wrapped.
void add_flag(char key, const std::string &longkey, bool &dest, const std::string &desc)
void add_int(char key, const std::string &longkey, int &dest, const std::string &desc)
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
bool process(int argc, const char *const *argv, std::ostream &os)
void print_param_error(int argc, const char *const *argv, const Argument *arg, std::ostream &os)
print error about parameter.