Ookii.CommandLine for C++  1.0.0
command_line_argument.h
Go to the documentation of this file.
1 #ifndef OOKII_COMMAND_LINE_ARGUMENT_H_
7 #define OOKII_COMMAND_LINE_ARGUMENT_H_
8 
9 #pragma once
10 
11 #include <functional>
12 #include "command_line_switch.h"
13 #include "usage_options.h"
14 
15 namespace ookii
16 {
17  namespace details
18  {
19  template<typename CharType, typename Traits, typename Alloc>
20  struct argument_storage
21  {
22  using string_type = std::basic_string<CharType, Traits, Alloc>;
23 
24  argument_storage(string_type name)
25  : name(name)
26  {
27  }
28 
29  string_type name;
30  string_type value_description;
31  string_type description;
32  std::optional<size_t> position;
33  std::vector<string_type> aliases;
34  bool is_required{};
35  bool cancel_parsing{};
36  CharType multi_value_separator{};
37  };
38 
39  template<class T, typename Element, typename CharType, typename Traits>
40  struct typed_argument_storage
41  {
42  using converter_type = std::function<std::optional<Element>(std::basic_string_view<CharType, Traits>, const std::locale &)>;
43 
44  typed_argument_storage(T &value)
45  : value{value}
46  {
47  }
48 
49  T &value;
50  std::optional<Element> default_value;
51  converter_type converter;
52  };
53 
54  template<typename T>
55  struct element_type
56  {
57  using type = T;
58  };
59 
60  template<typename T>
61  struct element_type<std::optional<T>>
62  {
63  using type = T;
64  };
65  }
66 
73  template<typename CharType, typename Traits = std::char_traits<CharType>, typename Alloc = std::allocator<CharType>>
75  {
76  public:
78  using storage_type = details::argument_storage<CharType, Traits, Alloc>;
80  using string_type = typename storage_type::string_type;
82  using string_view_type = std::basic_string_view<CharType, Traits>;
85 
87 
88  virtual ~command_line_argument_base() = default;
89 
90  command_line_argument_base &operator=(const command_line_argument_base &) = delete;
91 
95  const string_type &name() const noexcept
96  {
97  return _storage.name;
98  }
99 
105  const std::vector<string_type> &aliases() const noexcept
106  {
107  return _storage.aliases;
108  }
109 
119  const string_type &value_description() const noexcept
120  {
121  return _storage.value_description;
122  }
123 
133  const string_type &description() const noexcept
134  {
135  return _storage.description;
136  }
137 
146  std::optional<size_t> position() const noexcept
147  {
148  return _storage.position;
149  }
150 
156  bool is_required() const noexcept
157  {
158  return _storage.is_required;
159  }
160 
172  bool cancel_parsing() const noexcept
173  {
174  return _storage.cancel_parsing;
175  }
176 
182  bool has_value() const noexcept
183  {
184  return _has_value;
185  }
186 
191  virtual bool is_switch() const noexcept = 0;
192 
197  virtual bool is_multi_value() const noexcept
198  {
199  return false;
200  }
201 
208  virtual void reset()
209  {
210  _has_value = false;
211  }
212 
224  virtual bool set_value(string_view_type value, std::locale loc = {}) = 0;
225 
235  virtual void apply_default_value() = 0;
236 
245  virtual bool set_switch_value() = 0;
246 
257  virtual string_type format_default_value(const usage_options_type &options, const std::locale &loc = {}) const = 0;
258 
259  protected:
263  void set_value() noexcept
264  {
265  _has_value = true;
266  }
267 
269  const storage_type &base_storage() const
270  {
271  return _storage;
272  }
273 
276  : _storage{std::move(storage)}
277  {
278  }
279 
287  template<typename T>
288  static string_type format_default_value_helper(const std::optional<T> &value, const usage_options_type &options, const std::locale &loc = {})
289  {
290  if (options.include_default_value_in_description && value)
291  return format::ncformat(loc, options.default_value_format, *value);
292  else
293  return {};
294  }
295 
296  private:
297  storage_type _storage;
298  bool _has_value{};
299  };
300 
311  template<class T, typename CharType, typename Traits = std::char_traits<CharType>, typename Alloc = std::allocator<CharType>>
312  class command_line_argument final : public command_line_argument_base<CharType, Traits, Alloc>
313  {
314  public:
318  using value_type = T;
323  using element_type = typename details::element_type<T>::type;
329  using typed_storage_type = details::typed_argument_storage<value_type, element_type, CharType, Traits>;
332 
340  : base_type{std::move(storage)},
341  _storage{std::move(typed_storage)}
342  {
343  }
344 
350  bool is_switch() const noexcept override
351  {
352  return details::is_switch<T>::value;
353  }
354 
356  bool set_value(string_view_type value, std::locale loc = {}) override
357  {
358  std::optional<element_type> converted;
359  if (_storage.converter)
360  converted = _storage.converter(value, loc);
361  else
363 
364  if (!converted)
365  return false;
366 
367  _storage.value = std::move(*converted);
369  return true;
370  }
371 
373  bool set_switch_value() override
374  {
375  return set_switch_value_core();
376  }
377 
379  void apply_default_value() override
380  {
381  if (!this->has_value() && _storage.default_value)
382  {
383  _storage.value = *_storage.default_value;
384  }
385  }
386 
388  string_type format_default_value(const usage_options_type &options, const std::locale &loc = {}) const override
389  {
390  return this->format_default_value_helper(_storage.default_value, options, loc);
391  }
392 
393  private:
394  template<typename T2 = T>
395  std::enable_if_t<details::is_switch<T2>::value, bool> set_switch_value_core()
396  {
397  _storage.value = true;
398  return true;
399  }
400 
401  template<typename T2 = T>
402  std::enable_if_t<!details::is_switch<T2>::value, bool> set_switch_value_core()
403  {
404  return false;
405  }
406 
407  typed_storage_type _storage;
408  };
409 
419  template<typename T, typename CharType, typename Traits = std::char_traits<CharType>, typename Alloc = std::allocator<CharType>>
420  class multi_value_command_line_argument : public command_line_argument_base<CharType, Traits, Alloc>
421  {
422  public:
426  using value_type = T;
428  using element_type = typename T::value_type;
434  using typed_storage_type = details::typed_argument_storage<T, element_type, CharType, Traits>;
437 
445  : base_type{std::move(storage)},
446  _storage{std::move(typed_storage)}
447  {
448  }
449 
451  bool is_switch() const noexcept override
452  {
453  return details::is_switch<element_type>::value;
454  }
455 
459  bool is_multi_value() const noexcept override
460  {
461  return true;
462  }
463 
468  CharType separator() const noexcept
469  {
470  return this->base_storage().multi_value_separator;
471  }
472 
474  void reset() override
475  {
477  _storage.value.clear();
478  }
479 
481  bool set_value(string_view_type value, std::locale loc = {}) override
482  {
483  for (auto element : tokenize{value, separator()})
484  {
485  std::optional<element_type> converted;
486  if (_storage.converter)
487  converted = _storage.converter(element, loc);
488  else
490 
491  if (!converted)
492  return false;
493 
494  _storage.value.push_back(std::move(*converted));
495  }
496 
498  return true;
499  }
500 
502  bool set_switch_value() override
503  {
504  return set_switch_value_core();
505  }
506 
508  void apply_default_value() override
509  {
510  if (!this->has_value() && _storage.default_value)
511  {
512  _storage.value.push_back(*_storage.default_value);
513  }
514  }
515 
517  string_type format_default_value(const usage_options_type &options, const std::locale &loc = {}) const override
518  {
519  return this->format_default_value_helper(_storage.default_value, options, loc);
520  }
521 
522  private:
523  template<typename T2 = element_type>
524  std::enable_if_t<details::is_switch<T2>::value, bool> set_switch_value_core()
525  {
526  _storage.value.push_back(true);
527  return true;
528  }
529 
530  template<typename T2 = element_type>
531  std::enable_if_t<!details::is_switch<T2>::value, bool> set_switch_value_core()
532  {
533  return false;
534  }
535 
536  typed_storage_type _storage;
537  };
538 
539 }
540 
541 #endif
Provides options for how to format usage help.
Definition: usage_options.h:29
string_type default_value_format
The format to use for the default value of an argument.
Definition: usage_options.h:143
bool include_default_value_in_description
Indicates whether to include the default value of arguments in the description.
Definition: usage_options.h:180
Abstract base class for regular and multi-value arguments.
Definition: command_line_argument.h:75
virtual void reset()
Resets the argument to indicate it hasn't been set.
Definition: command_line_argument.h:208
void set_value() noexcept
Used to indicate that the argument has a value.
Definition: command_line_argument.h:263
const string_type & description() const noexcept
Gets the long description of the argument.
Definition: command_line_argument.h:133
const std::vector< string_type > & aliases() const noexcept
Gets a list of aliases that can be used instead of the argument's name.
Definition: command_line_argument.h:105
const storage_type & base_storage() const
Provides access to the storage fields to derived classes.
Definition: command_line_argument.h:269
typename storage_type::string_type string_type
The concrete type of std::basic_string used.
Definition: command_line_argument.h:80
virtual string_type format_default_value(const usage_options_type &options, const std::locale &loc={}) const =0
Convert the default value of the argument to a string using the specified usage options.
virtual bool is_multi_value() const noexcept
Gets a value that indicates whether the argument can be provided more than once, collecting all the s...
Definition: command_line_argument.h:197
virtual bool is_switch() const noexcept=0
Gets a value that indicates whether the argument is a switch, which means it can be supplied without ...
const string_type & value_description() const noexcept
Gets the value description for the argument.
Definition: command_line_argument.h:119
basic_usage_options< CharType, Traits, Alloc > usage_options_type
The concrete type of std::basic_usage_options used.
Definition: command_line_argument.h:84
command_line_argument_base(storage_type &&storage)
Move constructor for command_line_argument_base.
Definition: command_line_argument.h:275
std::optional< size_t > position() const noexcept
Gets the position of the argument.
Definition: command_line_argument.h:146
const string_type & name() const noexcept
Gets the name of the argument.
Definition: command_line_argument.h:95
virtual bool set_switch_value()=0
Applies the implicit value for a switch argument.
bool has_value() const noexcept
Gets a value that indicates whether the argument was specified on the last invocation of basic_comman...
Definition: command_line_argument.h:182
virtual void apply_default_value()=0
Sets the variable holding the argument's value to the default value.
std::basic_string_view< CharType, Traits > string_view_type
The concrete type of std::basic_string_view used.
Definition: command_line_argument.h:82
static string_type format_default_value_helper(const std::optional< T > &value, const usage_options_type &options, const std::locale &loc={})
Helper function for derived classes to implement format_default_value().
Definition: command_line_argument.h:288
bool cancel_parsing() const noexcept
Gets a value that indicates whether supplying this argument will cancel parsing.
Definition: command_line_argument.h:172
virtual bool set_value(string_view_type value, std::locale loc={})=0
Sets the argument to the specified value.
details::argument_storage< CharType, Traits, Alloc > storage_type
The concrete type of argument information storage used. For internal use.
Definition: command_line_argument.h:78
bool is_required() const noexcept
Gets a value that indicates whether the argument is required.
Definition: command_line_argument.h:156
Class that provides information about arguments that are not multi-value arguments.
Definition: command_line_argument.h:313
T value_type
The type of the argument's value, which equals T.
Definition: command_line_argument.h:318
bool set_value(string_view_type value, std::locale loc={}) override
Used to indicate that the argument has a value.
Definition: command_line_argument.h:356
details::typed_argument_storage< value_type, element_type, CharType, Traits > typed_storage_type
The concrete type of argument information storage used. For internal use.
Definition: command_line_argument.h:329
typename base_type::string_type string_type
The concrete type of std::basic_string used.
Definition: command_line_argument.h:325
typename details::element_type< T >::type element_type
The type of the argument's elements, which equals T.
Definition: command_line_argument.h:323
typename base_type::usage_options_type usage_options_type
The concrete type of std::basic_usage_options used.
Definition: command_line_argument.h:331
bool set_switch_value() override
Applies the implicit value for a switch argument.
Definition: command_line_argument.h:373
void apply_default_value() override
Sets the variable holding the argument's value to the default value.
Definition: command_line_argument.h:379
command_line_argument(typename base_type::storage_type &&storage, typed_storage_type &&typed_storage)
Initializes a new instance of the command_line_argument class.
Definition: command_line_argument.h:339
bool is_switch() const noexcept override
Gets a value that indicates whether the argument is a switch, which means it can be supplied without ...
Definition: command_line_argument.h:350
typename base_type::string_view_type string_view_type
The concrete type of std::basic_string_view used.
Definition: command_line_argument.h:327
string_type format_default_value(const usage_options_type &options, const std::locale &loc={}) const override
Convert the default value of the argument to a string using the specified usage options.
Definition: command_line_argument.h:388
Class that provides information about arguments that are not multi-value arguments.
Definition: command_line_argument.h:421
bool is_switch() const noexcept override
Gets a value that indicates whether the argument is a switch, which means it can be supplied without ...
Definition: command_line_argument.h:451
typename T::value_type element_type
The type of the argument's container's elements.
Definition: command_line_argument.h:428
typename base_type::usage_options_type usage_options_type
The concrete type of std::basic_usage_options used.
Definition: command_line_argument.h:436
typename base_type::string_type string_type
The concrete type of std::basic_string used.
Definition: command_line_argument.h:430
typename base_type::string_view_type string_view_type
The concrete type of std::basic_string_view used.
Definition: command_line_argument.h:432
string_type format_default_value(const usage_options_type &options, const std::locale &loc={}) const override
Convert the default value of the argument to a string using the specified usage options.
Definition: command_line_argument.h:517
void reset() override
Resets the argument to indicate it hasn't been set.
Definition: command_line_argument.h:474
bool set_switch_value() override
Applies the implicit value for a switch argument.
Definition: command_line_argument.h:502
multi_value_command_line_argument(typename base_type::storage_type &&storage, typed_storage_type &&typed_storage)
Initializes a new instance of the multi_value_command_line_argument class.
Definition: command_line_argument.h:444
details::typed_argument_storage< T, element_type, CharType, Traits > typed_storage_type
The concrete type of argument information storage used. For internal use.
Definition: command_line_argument.h:434
T value_type
The type of the argument's container, which equals T.
Definition: command_line_argument.h:426
bool is_multi_value() const noexcept override
Used to indicate that the argument has a value.
Definition: command_line_argument.h:459
CharType separator() const noexcept
Gets the character used to separate multiple values in a single argument value, or '\0' if no separat...
Definition: command_line_argument.h:468
void apply_default_value() override
Sets the variable holding the argument's value to the default value.
Definition: command_line_argument.h:508
bool set_value(string_view_type value, std::locale loc={}) override
Used to indicate that the argument has a value.
Definition: command_line_argument.h:481
A pseudo-range for string tokenization.
Definition: string_helper.h:215
Provides functionality for switch arguments.
std::string ncformat(const std::locale &loc, std::string_view format, Args &&... args)
Helper to format using a non-const format string without needing to explicitly construct a format_arg...
Definition: format_helper.h:55
Namespace containing the core Ookii.CommandLine.Cpp types.
Definition: command_line_argument.h:16
@ cancel_parsing
Cancel parsing immediately, disregarding the rest of the command line. Parsing will return with parse...
static std::optional< T > from_string(std::basic_string_view< CharType, Traits > value, const std::locale &loc={})
Convert a string to the specified type.
Definition: string_helper.h:168
Template used to specify the default value description for a type.
Definition: value_description.h:30