TAP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
Argument.hpp
Go to the documentation of this file.
1 
26 #pragma once
27 
28 #include <functional>
29 #include <memory>
30 
31 namespace TAP {
32 
33 class Argument;
34 
36 using ArgumentCheckFunc = std::function<void(const Argument&)>;
37 
48 class Argument: public BaseArgument {
49 protected:
51  std::string m_flags;
53  std::vector<std::string> m_names;
54 
57 
59  std::string m_description;
60 
62  unsigned int m_min = 1;
64  unsigned int m_max = 1;
65 
67  mutable std::shared_ptr<unsigned int> m_count;
68 
71 
72 #ifndef TAP_AUTOFLAG
73 
78  Argument(std::string description) :
79  m_isPositional(true), m_description(std::move(description)), m_count(std::make_shared<unsigned int>(0)) {
80  }
81 #endif
82 
83 public:
85  // Creation/definition
87 #ifdef TAP_AUTOFLAG
88 
94  Argument(std::string description) :
95  m_isPositional(true), m_description(std::move(description)), m_count(std::make_shared<unsigned int>(0)) {
96 
98  // Cannot perform below check as it requires virtual calls
99  // instead, user will have to make sure this does not happen
100  /*if (!takes_value() && m_isPositional) {
101  throw std::logic_error("Cannot create positional argument without value");
102  }*/
103  }
104 #endif
105 
111  Argument(std::string description, char flag) :
112  m_isPositional(false), m_description(std::move(description)), m_count(std::make_shared<unsigned int>(0)) {
113 #ifdef TAP_AUTOFLAG
115 #endif
116  alias(flag);
117  }
118 
124  Argument(std::string description, std::string name) :
125  m_isPositional(false), m_description(std::move(description)), m_count(std::make_shared<unsigned int>(0)) {
126 #ifdef TAP_AUTOFLAG
128 #endif
129  alias(std::move(name));
130  }
131 
138  Argument(std::string description, char flag, std::string name) :
139  m_isPositional(false), m_description(std::move(description)), m_count(std::make_shared<unsigned int>(0)) {
140 #ifdef TAP_AUTOFLAG
142 #endif
143  alias(flag, std::move(name));
144  }
145 
149  Argument(const Argument&) = default;
150 
154  Argument(Argument&&) = default;
155 
159  virtual ~Argument() {
160  }
161 
165  Argument& operator=(const Argument& other) = default;
166 
170  Argument& operator=(Argument&& other) = default;
171 
177  Argument& alias(char flag) {
178  m_flags.insert(m_flags.end(), flag);
179  return *this;
180  }
181 
187  Argument& alias(std::string name) {
188  m_names.push_back(std::move(name));
189  return *this;
190  }
191 
198  Argument& alias(char flag, std::string name) {
199  m_flags.insert(m_flags.end(), flag);
200  m_names.push_back(std::move(name));
201  return *this;
202  }
203 
208  const std::string& description() const {
209  return m_description;
210  }
211 
216  virtual Argument& check(ArgumentCheckFunc checkFunc) {
217  m_checkFunc = checkFunc;
218  return *this;
219  }
220 
222  // Lookup operations
224 
230  bool matches() const {
231  if (m_isPositional) {
232  return true;
233  }
234  return false;
235  }
236 
244  bool matches(char flag) const {
245  for (char self_flag : m_flags) {
246  if (self_flag == flag) {
247  return true;
248  }
249  }
250  return false;
251  }
252 
260  bool matches(const std::string& name) const {
261  for (const std::string& self_name : m_names) {
262  if (self_name == name) {
263  return true;
264  }
265  }
266  return false;
267  }
268 
272  void find_all_arguments(std::vector<const Argument*>& collector) const override {
273  collector.push_back(this);
274  }
275 
276  // Make public
279 
281  // Count operations
283 
289  Argument& many(bool many = true) {
290  if (!many) {
291  // Note: max of N (!=0) does not mean many
292  m_max = std::max(m_max, 1u);
293  } else {
294  m_max = 0u;
295  }
296  return *this;
297  }
298 
299  /*bool many() const {
300  return m_max != 1;
301  }*/
302 
309  Argument& min(unsigned int min) {
310  if (min == 0) {
311  throw std::logic_error("Cannot set zero minimum");
312  }
313  m_min = min;
314  if (min > m_max && m_max != 0u) {
315  m_max = m_min;
316  }
317  return *this;
318  }
319 
325  unsigned int min() const {
326  return m_min;
327  }
328 
335  Argument& max(unsigned int max) {
336  m_max = max;
337  return *this;
338  }
339 
344  unsigned int max() const {
345  return m_max;
346  }
347 
349  // value operations
351 
354  unsigned int count() const override {
355  return *m_count;
356  }
357 
363  bool can_set() const {
364  return (m_max == 0 || *m_count < m_max);
365  }
366 
370  virtual void set() const {
371  (*m_count)++;
372  check();
373  }
374 
380  virtual bool takes_value() const {
381  // Note: not the same as setCount < max, it is a fixed property
382  return false;
383  }
384 
386  // Validation operations
388 
391  void check_valid() const override;
392 
396  std::string usage() const override;
397 
403  virtual std::string ident() const;
404 
408  std::unique_ptr<BaseArgument> clone() const & override {
409  return std::unique_ptr<BaseArgument>(new Argument(*this));
410  }
411 
415  std::unique_ptr<BaseArgument> clone() && override {
416  return std::unique_ptr<BaseArgument>(new Argument(std::move(*this)));
417  }
418 protected:
423  virtual void check() const {
424  if (m_checkFunc != nullptr) {
425  m_checkFunc(*this);
426  }
427  }
428 
429 private:
430 #ifdef TAP_AUTOFLAG
431 
445  bool escape = false;
446  bool addFlag = false;
447  bool addName = false;
448  auto nameStart = m_description.begin();
449  std::vector<std::string::iterator> specialChars;
450  for (auto it = m_description.begin(); it != m_description.end(); ++it) {
451  char c = *it;
452  bool skip = false;
453 
454  if (addFlag) {
455  alias(c);
456  addFlag = false;
457  m_isPositional = false;
458  skip = true;
459  }
460 
461  if (!isalnum(c) && addName) {
462  // Check if valid character for a name
463  if (it != nameStart) {
464  alias( std::string(nameStart, it) );
465  m_isPositional = false;
466  }
467  addName = false;
468  }
469 
470  if (skip) {
471  continue;
472  }
473 
474  switch(c) {
475  case '\\':
476  escape = !escape;
477  if (!escape) {
478  specialChars.push_back(it);
479  }
480  break;
481  case '%':
482  // Treat next word as flag
483  if (escape) {
484  escape = false;
485  specialChars.push_back(it-1);
486  continue;
487  } else {
488  addFlag = true;
489  specialChars.push_back(it);
490  }
491  break;
492  case '$':
493  // Treat next word as name
494  if (escape) {
495  escape = false;
496  specialChars.push_back(it-1);
497  continue;
498  } else {
499  addName = true;
500  nameStart = it+1;
501  specialChars.push_back(it);
502  }
503  break;
504  case '&':
505  // Treat next word as flag and name
506  if (escape) {
507  escape = false;
508  specialChars.push_back(it-1);
509  continue;
510  } else {
511  addFlag = true;
512  addName = true;
513  nameStart = it+1;
514  specialChars.push_back(it);
515  }
516  break;
517  default:
518  break;
519  }
520  }
521  if (addName && nameStart != m_description.end()) {
522  alias(std::string(nameStart, m_description.end()));
523  }
524  // Remove the special characters
525  for (auto it = specialChars.rbegin(); it != specialChars.rend(); it++) {
526  m_description.erase(*it, (*it)+1);
527  }
528  }
529 #endif
530 };
531 
536 protected:
537  ~ValueAcceptor() {}
538 public:
544  virtual void set(const std::string& value) const = 0;
545 };
546 
547 }
const char skip[]
Define the parsed arg delimiter.
Definition: Tap.h:375
Argument(std::string description, char flag, std::string name)
Create an argument that is identified by both a name and flag.
Definition: Argument.hpp:138
std::shared_ptr< unsigned int > m_count
Actual counted number of occurrences.
Definition: Argument.hpp:67
std::string usage() const override
See BaseArgument::usage()
Argument(std::string description, std::string name)
Create an argument that is identified by a name.
Definition: Argument.hpp:124
bool matches(const std::string &name) const
Returns a pointer to this argument if it matches the given name with any alias, otherwise a null-poin...
Definition: Argument.hpp:260
Argument & min(unsigned int min)
Set the minimum number of required occurrences if set.
Definition: Argument.hpp:309
virtual std::string ident() const
Print a string representation of this argument to the given stream.
Argument & max(unsigned int max)
Set the maximum number of required occurrences.
Definition: Argument.hpp:335
const char nameStart[]
Marker for names (>1 letter arg)
Definition: Tap.h:359
std::unique_ptr< BaseArgument > clone()&&override
See BaseArgument::clone().
Definition: Argument.hpp:415
bool matches(char flag) const
Returns a pointer to this argument if it matches the given flag with any alias, otherwise a null-poin...
Definition: Argument.hpp:244
unsigned int min() const
Returns the minimum number of occurrences of this argument for it to be satisfied if set...
Definition: Argument.hpp:325
Base argument class, used both by actual Argument classes and constraints (ArgumentConstraint).
Definition: BaseArgument.hpp:40
bool matches() const
Returns a pointer to this argument if it matches as a positional argument, otherwise a null-pointer...
Definition: Argument.hpp:230
std::string m_description
Description or help text of argument.
Definition: Argument.hpp:59
Simple argument class.
Definition: Argument.hpp:48
void parse_description()
When TAP_AUTOFLAG is defined, this function finds flag and/or name markers in the description of the ...
Definition: Argument.hpp:444
unsigned int m_max
Maximum number of occurrences.
Definition: Argument.hpp:64
void find_all_arguments(std::vector< const Argument * > &collector) const override
See BaseArgument::find_all_arguments()
Definition: Argument.hpp:272
bool required() const
Returns whether the argument is required.
Definition: BaseArgument.hpp:119
ArgumentCheckFunc m_checkFunc
Callback for check.
Definition: Argument.hpp:70
Interface class for arguments that accept a value when takes_value() is true.
Definition: Argument.hpp:535
std::unique_ptr< BaseArgument > clone() const &override
See BaseArgument::clone().
Definition: Argument.hpp:408
Argument(std::string description)
Create an argument with flag and/or name set by description.
Definition: Argument.hpp:94
const std::string & description() const
Returns the description of this argument.
Definition: Argument.hpp:208
unsigned int max() const
Returns the maximum number of occurrences of this argument.
Definition: Argument.hpp:344
Argument & operator=(const Argument &other)=default
Argument assignment operator.
std::vector< std::string > m_names
Names this argument matches.
Definition: Argument.hpp:53
virtual ~Argument()
Argument destructor.
Definition: Argument.hpp:159
std::function< void(const Argument &)> ArgumentCheckFunc
Function pointer that is used by Argument::check().
Definition: Argument.hpp:36
Argument & alias(char flag)
An a flag alias for the argument.
Definition: Argument.hpp:177
Argument & alias(char flag, std::string name)
An both a flag and name alias for the argument.
Definition: Argument.hpp:198
unsigned int count() const override
See BaseArgument::count()
Definition: Argument.hpp:354
bool m_isPositional
True if used as positional argument.
Definition: Argument.hpp:56
unsigned int m_min
Minimum number of occurrences if argument is set.
Definition: Argument.hpp:62
virtual Argument & check(ArgumentCheckFunc checkFunc)
Set the check function to use.
Definition: Argument.hpp:216
virtual bool takes_value() const
Returns whether or not this argument requires a value when it occurs (see also set()).
Definition: Argument.hpp:380
Argument(std::string description, char flag)
Create an argument that is identified by a flag.
Definition: Argument.hpp:111
Argument & many(bool many=true)
Allow the argument to occur multiple times or not.
Definition: Argument.hpp:289
Argument & alias(std::string name)
An a name alias for the argument.
Definition: Argument.hpp:187
bool can_set() const
Returns whether this argument is still allowed to occur on the command line.
Definition: Argument.hpp:363
void check_valid() const override
See BaseArgument::check_valid()
std::string m_flags
Flags this arguments matches.
Definition: Argument.hpp:51
virtual void set(const std::string &value) const =0
Set the argument (mark as occurred), and assign a value to it.
virtual void check() const
Executes the associated check function.
Definition: Argument.hpp:423
BaseArgument & set_required(bool required=true)
Mark the argument as required or not.
Definition: BaseArgument.hpp:110
virtual void set() const
Set the argument (mark as occurred).
Definition: Argument.hpp:370