Thrill  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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  //! add boolean option flag -key, --longkey [keytype] with description and
159  //! store to dest
160  void add_bool(
161  char key, const std::string& longkey,
162  const std::string& keytype, bool& dest, // NOLINT
163  const std::string& desc);
164 
165  //! add boolean option flag -key, --longkey [keytype] with description and
166  //! store to dest. identical to add_bool()
167  void add_flag(
168  char key, const std::string& longkey,
169  const std::string& keytype, bool& dest, // NOLINT
170  const std::string& desc);
171 
172  //! add signed integer option -key, --longkey [keytype] with description
173  //! and store to dest
174  void add_int(
175  char key, const std::string& longkey,
176  const std::string& keytype, int& dest, // NOLINT
177  const std::string& desc);
178 
179  //! add unsigned integer option -key, --longkey [keytype] with description
180  //! and store to dest
181  void add_unsigned(
182  char key, const std::string& longkey,
183  const std::string& keytype, unsigned int& dest, // NOLINT
184  const std::string& desc);
185 
186  //! add unsigned integer option -key, --longkey [keytype] with description
187  //! and store to dest. identical to add_unsigned()
188  void add_uint(
189  char key, const std::string& longkey,
190  const std::string& keytype, unsigned int& dest, // NOLINT
191  const std::string& desc);
192 
193  //! add size_t option -key, --longkey [keytype] with description and store
194  //! to dest
195  void add_size_t(
196  char key, const std::string& longkey,
197  const std::string& keytype, size_t& dest, // NOLINT
198  const std::string& desc);
199 
200  //! add float option -key, --longkey [keytype] with description and store
201  //! to dest
202  void add_float(
203  char key, const std::string& longkey,
204  const std::string& keytype, float& dest, // NOLINT
205  const std::string& desc);
206 
207  //! add double option -key, --longkey [keytype] with description and store
208  //! to dest
209  void add_double(
210  char key, const std::string& longkey,
211  const std::string& keytype, double& dest, // NOLINT
212  const std::string& desc);
213 
214  //! add SI/IEC suffixes byte size option -key, --longkey [keytype] and
215  //! store to 64-bit dest
216  void add_bytes(
217  char key, const std::string& longkey,
218  const std::string& keytype, uint32_t& dest, // NOLINT
219  const std::string& desc);
220 
221  //! add SI/IEC suffixes byte size option -key, --longkey [keytype] and
222  //! store to 64-bit dest
223  void add_bytes(
224  char key, const std::string& longkey,
225  const std::string& keytype, uint64_t& dest, // NOLINT
226  const std::string& desc);
227 
228  //! add string option -key, --longkey [keytype] and store to dest
229  void add_string(
230  char key, const std::string& longkey,
231  const std::string& keytype, std::string& dest, // NOLINT
232  const std::string& desc);
233 
234  //! add string list option -key, --longkey [keytype] and store to dest
235  void add_stringlist(
236  char key, const std::string& longkey,
237  const std::string& keytype, std::vector<std::string>& dest, // NOLINT
238  const std::string& desc);
239 
240  /**************************************************************************/
241 
242  //! add boolean option flag -key, --longkey with description and store to
243  //! dest
244  void add_bool(char key, const std::string& longkey, bool& dest, // NOLINT
245  const std::string& desc);
246 
247  //! add boolean option flag -key, --longkey with description and store to
248  //! dest. identical to add_bool()
249  void add_flag(char key, const std::string& longkey, bool& dest, // NOLINT
250  const std::string& desc);
251 
252  //! add signed integer option -key, --longkey with description and store to
253  //! dest
254  void add_int(char key, const std::string& longkey, int& dest, // NOLINT
255  const std::string& desc);
256 
257  //! add unsigned integer option -key, --longkey [keytype] with description
258  //! and store to dest
259  void add_unsigned(char key, const std::string& longkey,
260  unsigned int& dest, const std::string& desc); // NOLINT
261 
262  //! add unsigned integer option -key, --longkey [keytype] with description
263  //! and store to dest. identical to add_unsigned()
264  void add_uint(char key, const std::string& longkey,
265  unsigned int& dest, const std::string& desc); // NOLINT
266 
267  //! add size_t option -key, --longkey [keytype] with description and store
268  //! to dest
269  void add_size_t(char key, const std::string& longkey,
270  size_t& dest, const std::string& desc); // NOLINT
271 
272  //! add float option -key, --longkey [keytype] with description and store
273  //! to dest
274  void add_float(char key, const std::string& longkey,
275  float& dest, const std::string& desc); // NOLINT
276 
277  //! add double option -key, --longkey [keytype] with description and store
278  //! to dest
279  void add_double(char key, const std::string& longkey,
280  double& dest, const std::string& desc); // NOLINT
281 
282  //! add SI/IEC suffixes byte size option -key, --longkey [keytype] and
283  //! store to 32-bit dest
284  void add_bytes(char key, const std::string& longkey,
285  uint32_t& dest, const std::string& desc); // NOLINT
286 
287  //! add SI/IEC suffixes byte size option -key, --longkey [keytype] and
288  //! store to 64-bit dest
289  void add_bytes(char key, const std::string& longkey,
290  uint64_t& dest, const std::string& desc); // NOLINT
291 
292  //! add string option -key, --longkey [keytype] and store to dest
293  void add_string(char key, const std::string& longkey,
294  std::string& dest, const std::string& desc); // NOLINT
295 
296  //! add string list option -key, --longkey [keytype] and store to dest
297  void add_stringlist(
298  char key, const std::string& longkey,
299  std::vector<std::string>& dest, const std::string& desc); // NOLINT
300 
301  // ************************************************************************
302 
303  //! add signed integer parameter [name] with description and store to dest
304  void add_param_int(
305  const std::string& name, int& dest, const std::string& desc); // NOLINT
306 
307  //! add unsigned integer parameter [name] with description and store to dest
308  void add_param_unsigned(
309  const std::string& name, unsigned int& dest, // NOLINT
310  const std::string& desc);
311 
312  //! add unsigned integer parameter [name] with description and store to
313  //! dest. identical to add_unsigned()
314  void add_param_uint(
315  const std::string& name, unsigned int& dest, // NOLINT
316  const std::string& desc);
317 
318  //! add size_t parameter [name] with description and store to dest
319  void add_param_size_t(
320  const std::string& name, size_t& dest, // NOLINT
321  const std::string& desc);
322 
323  //! add float parameter [name] with description and store to dest
324  void add_param_float(
325  const std::string& name, float& dest, // NOLINT
326  const std::string& desc);
327 
328  //! add double parameter [name] with description and store to dest
329  void add_param_double(
330  const std::string& name, double& dest, // NOLINT
331  const std::string& desc);
332 
333  //! add SI/IEC suffixes byte size parameter [name] with description and
334  //! store to dest
335  void add_param_bytes(
336  const std::string& name, uint32_t& dest, // NOLINT
337  const std::string& desc);
338 
339  //! add SI/IEC suffixes byte size parameter [name] with description and
340  //! store to dest
341  void add_param_bytes(
342  const std::string& name, uint64_t& dest, // NOLINT
343  const std::string& desc);
344 
345  //! add string parameter [name] with description and store to dest
346  void add_param_string(
347  const std::string& name, std::string& dest, // NOLINT
348  const std::string& desc);
349 
350  //! add string list parameter [name] with description and store to dest.
351  //! \warning this parameter must be last, as it will gobble all non-option
352  //! arguments!
354  const std::string& name, std::vector<std::string>& dest, // NOLINT
355  const std::string& desc);
356 
357  /**************************************************************************/
358 
359  //! add optional signed integer parameter [name] with description and store
360  //! to dest
361  void add_opt_param_int(
362  const std::string& name, int& dest, const std::string& desc); // NOLINT
363 
364  //! add optional unsigned integer parameter [name] with description and
365  //! store to dest
367  const std::string& name, unsigned int& dest, // NOLINT
368  const std::string& desc);
369 
370  //! add optional unsigned integer parameter [name] with description and
371  //! store to dest. identical to add_unsigned()
372  void add_opt_param_uint(
373  const std::string& name, unsigned int& dest, // NOLINT
374  const std::string& desc);
375 
376  //! add optional size_t parameter [name] with description and store to dest
378  const std::string& name, size_t& dest, // NOLINT
379  const std::string& desc);
380 
381  //! add optional float parameter [name] with description and store to dest
382  void add_opt_param_float(
383  const std::string& name, float& dest, // NOLINT
384  const std::string& desc);
385 
386  //! add optional double parameter [name] with description and store to dest
388  const std::string& name, double& dest, // NOLINT
389  const std::string& desc);
390 
391  //! add optional SI/IEC suffixes byte size parameter [name] with
392  //! description and store to dest
393  void add_opt_param_bytes(
394  const std::string& name, uint32_t& dest, // NOLINT
395  const std::string& desc);
396 
397  //! add optional SI/IEC suffixes byte size parameter [name] with
398  //! description and store to dest
399  void add_opt_param_bytes(
400  const std::string& name, uint64_t& dest, // NOLINT
401  const std::string& desc);
402 
403  //! add optional string parameter [name] with description and store to dest
405  const std::string& name, std::string& dest, // NOLINT
406  const std::string& desc);
407 
408  //! add optional string parameter [name] with description and store to dest
409  //! \warning this parameter must be last, as it will gobble all non-option
410  //! arguments!
412  const std::string& name, std::vector<std::string>& dest, // NOLINT
413  const std::string& desc);
414 
415  /**************************************************************************/
416 
417  //! output nicely formatted usage information including description of all
418  //! parameters and options.
419  void print_usage(std::ostream& os);
420 
421  //! output to std::cout nicely formatted usage information including
422  //! description of all parameters and options.
423  void print_usage();
424 
425 private:
426  //! print error about option.
427  void print_option_error(int argc, const char* const* argv,
428  const Argument* arg, std::ostream& os);
429 
430  //! print error about parameter.
431  void print_param_error(int argc, const char* const* argv,
432  const Argument* arg, std::ostream& os);
433 
434 public:
435  //! parse command line options as specified by the options and parameters
436  //! added.
437  //! \return true if command line is okay and all required parameters are
438  //! present.
439  bool process(
440  int argc, const char* const* argv, std::ostream& os);
441 
442  //! parse command line options as specified by the options and parameters
443  //! added.
444  //! \return true if command line is okay and all required parameters are
445  //! present.
446  bool process(int argc, const char* const* argv);
447 
448  //! print nicely formatted result of processing
449  void print_result(std::ostream& os);
450 
451  //! print nicely formatted result of processing to std::cout
452  void print_result();
453 };
454 
455 } // namespace tlx
456 
457 #endif // !TLX_CMDLINE_PARSER_HEADER
458 
459 /******************************************************************************/
void add_opt_param_bytes(const std::string &name, uint32_t &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_float(char key, const std::string &longkey, const std::string &keytype, float &dest, const std::string &desc)
void add_size_t(char key, const std::string &longkey, const std::string &keytype, size_t &dest, const std::string &desc)
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.
void add_uint(char key, const std::string &longkey, const std::string &keytype, unsigned int &dest, const std::string &desc)
~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 add_double(char key, const std::string &longkey, const std::string &keytype, double &dest, const std::string &desc)
void add_int(char key, const std::string &longkey, const std::string &keytype, int &dest, const std::string &desc)
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 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 add_string(char key, const std::string &longkey, const std::string &keytype, std::string &dest, const std::string &desc)
add string option -key, –longkey [keytype] and store to dest
void print_result()
print nicely formatted result of processing to std::cout
ArgumentList param_list_
list of parameters, both required and optional
void add_bytes(char key, const std::string &longkey, const std::string &keytype, uint32_t &dest, const std::string &desc)
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_opt_param_float(const std::string &name, float &dest, const std::string &desc)
add optional float parameter [name] with description and store to dest
void add_flag(char key, const std::string &longkey, const std::string &keytype, bool &dest, const std::string &desc)
static constexpr int max_type_name_
maximum length of a type_name() result
void add_stringlist(char key, const std::string &longkey, const std::string &keytype, std::vector< std::string > &dest, const std::string &desc)
add string list option -key, –longkey [keytype] 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, 'param <#>'
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
std::string author_
user set author of program, will be wrapped
unsigned int line_wrap_
set line wrap length
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_unsigned(char key, const std::string &longkey, const std::string &keytype, unsigned int &dest, const std::string &desc)
size_t option_max_width_
formatting width for options, '-s, –switch <#>'
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_bool(char key, const std::string &longkey, const std::string &keytype, bool &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.