C++ Utilities  4.7.0
Common C++ classes and routines used by my applications such as argument parser, IO and conversion utilities
argumentparser.h
Go to the documentation of this file.
1 #ifndef APPLICATION_UTILITIES_ARGUMENTPARSER_H
2 #define APPLICATION_UTILITIES_ARGUMENTPARSER_H
3 
4 #include "../global.h"
5 
6 #include <functional>
7 #include <initializer_list>
8 #include <limits>
9 #include <vector>
10 #ifdef DEBUG_BUILD
11 #include <cassert>
12 #endif
13 
15 
17 
18 CPP_UTILITIES_EXPORT extern const char *applicationName;
19 CPP_UTILITIES_EXPORT extern const char *applicationAuthor;
20 CPP_UTILITIES_EXPORT extern const char *applicationVersion;
21 CPP_UTILITIES_EXPORT extern const char *applicationUrl;
22 CPP_UTILITIES_EXPORT extern std::initializer_list<const char *> dependencyVersions;
23 
30 #ifndef APP_STATICALLY_LINKED
31 #define SET_DEPENDENCY_INFO ::ApplicationUtilities::dependencyVersions = DEPENCENCY_VERSIONS
32 #else
33 #define SET_DEPENDENCY_INFO ::ApplicationUtilities::dependencyVersions = STATIC_DEPENCENCY_VERSIONS
34 #endif
35 
41 #define SET_APPLICATION_INFO \
42  ::ApplicationUtilities::applicationName = APP_NAME; \
43  ::ApplicationUtilities::applicationAuthor = APP_AUTHOR; \
44  ::ApplicationUtilities::applicationVersion = APP_VERSION; \
45  ::ApplicationUtilities::applicationUrl = APP_URL; \
46  SET_DEPENDENCY_INFO
47 
48 CPP_UTILITIES_EXPORT extern void (*exitFunction)(int);
49 
50 class Argument;
51 class ArgumentParser;
53 
54 typedef std::initializer_list<Argument *> ArgumentInitializerList;
55 typedef std::vector<Argument *> ArgumentVector;
56 typedef std::function<bool(Argument *)> ArgumentPredicate;
57 
63  Ignore,
64  Warn,
65  Fail
66 };
67 
71 enum class ValueCompletionBehavior : unsigned char {
72  None = 0,
73  PreDefinedValues = 2,
74  Files = 4,
75  Directories = 8,
77  AppendEquationSign = 32
78 };
79 
82 {
83  return static_cast<ValueCompletionBehavior>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
84 }
85 
87 {
88  return static_cast<bool>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
89 }
91 
92 Argument CPP_UTILITIES_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except);
93 
98  ArgumentOccurrence(std::size_t index);
99  ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent);
100 
104  std::size_t index;
105 
109  std::vector<const char *> values;
110 
115  std::vector<Argument *> path;
116 };
117 
121 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index)
122  : index(index)
123 {
124 }
125 
134 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent)
135  : index(index)
136  , path(parentPath)
137 {
138  if (parent) {
139  path.push_back(parent);
140  }
141 }
142 
144  friend ArgumentParser;
145  friend ArgumentReader;
146 
147 public:
148  typedef std::function<void(const ArgumentOccurrence &)> CallbackFunction;
149 
150  Argument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
151  ~Argument();
152 
153  const char *name() const;
154  void setName(const char *name);
155  char abbreviation() const;
156  void setAbbreviation(char abbreviation);
157  const char *environmentVariable() const;
158  void setEnvironmentVariable(const char *environmentVariable);
159  const char *description() const;
160  void setDescription(const char *description);
161  const char *example() const;
162  void setExample(const char *example);
163  const std::vector<const char *> &values(std::size_t occurrence = 0) const;
164  const char *firstValue() const;
165  std::size_t requiredValueCount() const;
166  void setRequiredValueCount(std::size_t requiredValueCount);
167  const std::vector<const char *> &valueNames() const;
168  void setValueNames(std::initializer_list<const char *> valueNames);
169  void appendValueName(const char *valueName);
170  bool allRequiredValuesPresent(std::size_t occurrence = 0) const;
171  bool isPresent() const;
172  std::size_t occurrences() const;
173  std::size_t index(std::size_t occurrence) const;
174  std::size_t minOccurrences() const;
175  std::size_t maxOccurrences() const;
176  void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
177  const std::vector<Argument *> &path(std::size_t occurrence = 0) const;
178  bool isRequired() const;
179  void setRequired(bool required);
180  bool isCombinable() const;
181  void setCombinable(bool value);
182  bool isImplicit() const;
183  void setImplicit(bool value);
184  bool denotesOperation() const;
185  void setDenotesOperation(bool denotesOperation);
186  void setCallback(CallbackFunction callback);
187  void printInfo(std::ostream &os, unsigned char indentation = 0) const;
188  const ArgumentVector &subArguments() const;
189  void setSubArguments(const ArgumentInitializerList &subArguments);
190  void addSubArgument(Argument *arg);
191  bool hasSubArguments() const;
192  const ArgumentVector parents() const;
193  bool isMainArgument() const;
194  bool isParentPresent() const;
195  ValueCompletionBehavior valueCompletionBehaviour() const;
196  void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour);
197  const char *preDefinedCompletionValues() const;
198  void setPreDefinedCompletionValues(const char *preDefinedCompletionValues);
199  Argument *conflictsWithArgument() const;
200  Argument *wouldConflictWithArgument() const;
201  void reset();
202  void resetRecursively();
203 
208  static constexpr std::size_t varValueCount = std::numeric_limits<std::size_t>::max();
209 
210 private:
211  const char *m_name;
212  char m_abbreviation;
213  const char *m_environmentVar;
214  const char *m_description;
215  const char *m_example;
216  std::size_t m_minOccurrences;
217  std::size_t m_maxOccurrences;
218  bool m_combinable;
219  bool m_denotesOperation;
220  std::size_t m_requiredValueCount;
221  std::vector<const char *> m_valueNames;
222  bool m_implicit;
223  std::vector<ArgumentOccurrence> m_occurrences;
224  ArgumentVector m_subArgs;
225  CallbackFunction m_callbackFunction;
226  ArgumentVector m_parents;
227  bool m_isMainArg;
228  ValueCompletionBehavior m_valueCompletionBehavior;
229  const char *m_preDefinedCompletionValues;
230 };
231 
233  friend ArgumentParserTests;
234  friend ArgumentReader;
235 
236 public:
237  ArgumentParser();
238 
239  const ArgumentVector &mainArguments() const;
240  void setMainArguments(const ArgumentInitializerList &mainArguments);
241  void addMainArgument(Argument *argument);
242  void printHelp(std::ostream &os) const;
243  void parseArgs(int argc, const char *const *argv);
244  void readArgs(int argc, const char *const *argv);
245  void resetArgs();
246  unsigned int actualArgumentCount() const;
247  const char *executable() const;
248  UnknownArgumentBehavior unknownArgumentBehavior() const;
249  void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior);
250  Argument *defaultArgument() const;
251  void setDefaultArgument(Argument *argument);
252  void checkConstraints();
253  void invokeCallbacks();
254  bool isUncombinableMainArgPresent() const;
255 
256 private:
257  IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args, std::vector<char> abbreviations, std::vector<const char *> names);)
258  void printBashCompletion(int argc, const char *const *argv, unsigned int cursorPos, const ArgumentReader &reader);
259  void checkConstraints(const ArgumentVector &args);
260  void invokeCallbacks(const ArgumentVector &args);
261 
262  ArgumentVector m_mainArgs;
263  unsigned int m_actualArgc;
264  const char *m_executable;
265  UnknownArgumentBehavior m_unknownArgBehavior;
266  Argument *m_defaultArg;
267 };
268 
274 inline const char *Argument::name() const
275 {
276  return m_name;
277 }
278 
286 inline void Argument::setName(const char *name)
287 {
288 #ifdef DEBUG_BUILD
289  if (name && *name) {
290  assert(*name != '-');
291  for (const char *c = name; *c; ++c) {
292  assert(*c != ' ' && *c != '=' && *c != '\'' && *c != '\"' && *c != '\n' && *c != '\r');
293  }
294  }
295 #endif
296  m_name = name;
297 }
298 
304 inline char Argument::abbreviation() const
305 {
306  return m_abbreviation;
307 }
308 
316 inline void Argument::setAbbreviation(char abbreviation)
317 {
318  IF_DEBUG_BUILD(assert(abbreviation != ' ' && abbreviation != '=' && abbreviation != '-' && abbreviation != '\'' && abbreviation != '"'
319  && abbreviation != '\n' && abbreviation != '\r'));
320  m_abbreviation = abbreviation;
321 }
322 
327 inline const char *Argument::environmentVariable() const
328 {
329  return m_environmentVar;
330 }
331 
336 inline void Argument::setEnvironmentVariable(const char *environmentVariable)
337 {
338  m_environmentVar = environmentVariable;
339 }
340 
346 inline const char *Argument::description() const
347 {
348  return m_description;
349 }
350 
356 inline void Argument::setDescription(const char *description)
357 {
358  m_description = description;
359 }
360 
366 inline const char *Argument::example() const
367 {
368  return m_example;
369 }
370 
376 inline void Argument::setExample(const char *example)
377 {
378  m_example = example;
379 }
380 
387 inline const std::vector<const char *> &Argument::values(std::size_t occurrence) const
388 {
389  return m_occurrences[occurrence].values;
390 }
391 
405 inline std::size_t Argument::requiredValueCount() const
406 {
407  return m_requiredValueCount;
408 }
409 
422 inline void Argument::setRequiredValueCount(std::size_t requiredValueCount)
423 {
424  m_requiredValueCount = requiredValueCount;
425 }
426 
435 inline const std::vector<const char *> &Argument::valueNames() const
436 {
437  return m_valueNames;
438 }
439 
453 inline void Argument::setValueNames(std::initializer_list<const char *> valueNames)
454 {
455  m_valueNames.assign(valueNames);
456 }
457 
464 inline void Argument::appendValueName(const char *valueName)
465 {
466  m_valueNames.emplace_back(valueName);
467 }
468 
472 inline bool Argument::allRequiredValuesPresent(std::size_t occurrence) const
473 {
474  return m_requiredValueCount == static_cast<std::size_t>(-1)
475  || (m_occurrences[occurrence].values.size() >= static_cast<std::size_t>(m_requiredValueCount));
476 }
477 
482 inline bool Argument::isImplicit() const
483 {
484  return m_implicit;
485 }
486 
491 inline void Argument::setImplicit(bool implicit)
492 {
493  m_implicit = implicit;
494 }
495 
499 inline bool Argument::isPresent() const
500 {
501  return !m_occurrences.empty();
502 }
503 
507 inline std::size_t Argument::occurrences() const
508 {
509  return m_occurrences.size();
510 }
511 
515 inline std::size_t Argument::index(std::size_t occurrence) const
516 {
517  return m_occurrences[occurrence].index;
518 }
519 
525 inline std::size_t Argument::minOccurrences() const
526 {
527  return m_minOccurrences;
528 }
529 
535 inline std::size_t Argument::maxOccurrences() const
536 {
537  return m_maxOccurrences;
538 }
539 
545 inline void Argument::setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
546 {
547  m_minOccurrences = minOccurrences;
548  m_maxOccurrences = maxOccurrences;
549 }
550 
554 inline const std::vector<Argument *> &Argument::path(std::size_t occurrence) const
555 {
556  return m_occurrences[occurrence].path;
557 }
558 
568 inline bool Argument::isRequired() const
569 {
570  return m_minOccurrences;
571 }
572 
580 inline void Argument::setRequired(bool required)
581 {
582  if (required) {
583  if (!m_minOccurrences) {
584  m_minOccurrences = 1;
585  }
586  } else {
587  m_minOccurrences = 0;
588  }
589 }
590 
599 inline bool Argument::isCombinable() const
600 {
601  return m_combinable;
602 }
603 
612 inline void Argument::setCombinable(bool value)
613 {
614  m_combinable = value;
615 }
616 
627 inline bool Argument::denotesOperation() const
628 {
629  return m_denotesOperation;
630 }
631 
636 inline void Argument::setDenotesOperation(bool denotesOperation)
637 {
638  m_denotesOperation = denotesOperation;
639 }
640 
647 {
648  m_callbackFunction = callback;
649 }
650 
657 inline const ArgumentVector &Argument::subArguments() const
658 {
659  return m_subArgs;
660 }
661 
668 inline bool Argument::hasSubArguments() const
669 {
670  return !m_subArgs.empty();
671 }
672 
683 inline const ArgumentVector Argument::parents() const
684 {
685  return m_parents;
686 }
687 
694 inline bool Argument::isMainArgument() const
695 {
696  return m_isMainArg;
697 }
698 
703 {
704  return m_valueCompletionBehavior;
705 }
706 
711 {
712  m_valueCompletionBehavior = completionValues;
713 }
714 
718 inline const char *Argument::preDefinedCompletionValues() const
719 {
720  return m_preDefinedCompletionValues;
721 }
722 
726 inline void Argument::setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
727 {
728  m_preDefinedCompletionValues = preDefinedCompletionValues;
729 }
730 
734 inline void Argument::reset()
735 {
736  m_occurrences.clear();
737 }
738 
743 inline const ArgumentVector &ArgumentParser::mainArguments() const
744 {
745  return m_mainArgs;
746 }
747 
751 inline unsigned int ArgumentParser::actualArgumentCount() const
752 {
753  return m_actualArgc;
754 }
755 
759 inline const char *ArgumentParser::executable() const
760 {
761  return m_executable;
762 }
763 
770 {
771  return m_unknownArgBehavior;
772 }
773 
780 {
781  m_unknownArgBehavior = behavior;
782 }
783 
789 {
790  return m_defaultArg;
791 }
792 
798 {
799  m_defaultArg = argument;
800 }
801 
808 {
809  checkConstraints(m_mainArgs);
810 }
811 
817 {
818  invokeCallbacks(m_mainArgs);
819 }
820 
822 public:
823  HelpArgument(ArgumentParser &parser);
824 };
825 
827 public:
828  OperationArgument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
829 };
830 
831 inline OperationArgument::OperationArgument(const char *name, char abbreviation, const char *description, const char *example)
832  : Argument(name, abbreviation, description, example)
833 {
834  setDenotesOperation(true);
835 }
836 
838 public:
839  ConfigValueArgument(const char *name, char abbreviation = '\0', const char *description = nullptr,
840  std::initializer_list<const char *> valueNames = std::initializer_list<const char *>());
841 };
842 
847  const char *name, char abbreviation, const char *description, std::initializer_list<const char *> valueNames)
848  : Argument(name, abbreviation, description)
849 {
850  setCombinable(true);
851  setRequiredValueCount(valueNames.size());
852  setValueNames(valueNames);
853 }
854 }
855 
856 #endif // APPLICATION_UTILITIES_ARGUMENTPARSER_H
bool isMainArgument() const
Returns an indication whether the argument is used as main argument.
std::function< bool(Argument *)> ArgumentPredicate
CPP_UTILITIES_EXPORT const char * applicationUrl
Specifies the URL to the application website (used by ArgumentParser::printHelp()).
ValueCompletionBehavior
The ValueCompletionBehavior enum specifies the items to be considered when generating completion for ...
const char * preDefinedCompletionValues() const
Returns the assigned values used when generating completion for the values.
bool denotesOperation() const
Returns whether the argument denotes the operation.
UnknownArgumentBehavior unknownArgumentBehavior() const
Returns how unknown arguments are treated.
The ConfigValueArgument class is an Argument where setCombinable() is true by default.
std::initializer_list< Argument * > ArgumentInitializerList
#define IF_DEBUG_BUILD(x)
Wraps debug-only lines conveniently.
Definition: global.h:130
Argument * defaultArgument() const
Returns the default argument.
std::size_t requiredValueCount() const
Returns the number of values which are required to be given for this argument.
void setImplicit(bool value)
Sets whether the argument is an implicit argument.
const char * description() const
Returns the description of the argument.
std::size_t index
The index of the occurrence.
void setCombinable(bool value)
Sets whether this argument can be combined.
ValueCompletionBehavior valueCompletionBehaviour() const
Returns the items to be considered when generating completion for the values.
void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior)
Sets how unknown arguments are treated.
const ArgumentVector parents() const
Returns the parents of this argument.
Contains currently only ArgumentParser and related classes.
std::size_t maxOccurrences() const
Returns the maximum number of occurrences.
constexpr DirectoryEntryType operator|(DirectoryEntryType lhs, DirectoryEntryType rhs)
Definition: path.h:28
bool isRequired() const
Returns an indication whether the argument is mandatory.
Argument CPP_UTILITIES_EXPORT * firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except)
This function return the first present and uncombinable argument of the given list of arguments...
void setRequired(bool required)
Sets whether this argument is mandatory or not.
std::size_t index(std::size_t occurrence) const
Returns the indices of the argument&#39;s occurences which could be detected when parsing.
std::function< void(const ArgumentOccurrence &)> CallbackFunction
void setDefaultArgument(Argument *argument)
Sets the default argument.
CPP_UTILITIES_EXPORT const char * applicationVersion
Specifies the version of the application (used by ArgumentParser::printHelp()).
ConfigValueArgument(const char *name, char abbreviation='\0', const char *description=nullptr, std::initializer_list< const char *> valueNames=std::initializer_list< const char *>())
Constructs a new ConfigValueArgument with the specified parameter.
void invokeCallbacks()
Invokes all assigned callbacks.
The ArgumentParserTests class tests the ArgumentParser and Argument classes.
void checkConstraints()
Checks whether contraints are violated.
const char * name() const
Returns the name of the argument.
const std::vector< const char * > & valueNames() const
Returns the names of the requried values.
The OperationArgument class is an Argument where denotesOperation() is true by default.
void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
Sets the allowed number of occurrences.
const ArgumentVector & subArguments() const
Returns the secondary arguments for this argument.
std::size_t minOccurrences() const
Returns the minimum number of occurrences.
void setAbbreviation(char abbreviation)
Sets the abbreviation of the argument.
void setDescription(const char *description)
Sets the description of the argument.
void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour)
Sets the items to be considered when generating completion for the values.
void appendValueName(const char *valueName)
Appends a value name.
CPP_UTILITIES_EXPORT std::initializer_list< const char * > dependencyVersions
Specifies the dependency versions the application was linked against (used by ArgumentParser::printHe...
const std::vector< const char * > & values(std::size_t occurrence=0) const
Returns the parameter values for the specified occurrence of argument.
CPP_UTILITIES_EXPORT void(* exitFunction)(int)
Specifies a function quit the application.
const char * executable() const
Returns the name of the current executable.
std::size_t occurrences() const
Returns how often the argument could be detected when parsing.
The Argument class is a wrapper for command line argument information.
void setCallback(CallbackFunction callback)
Sets a callback function which will be called by the parser if the argument could be found and no par...
void setExample(const char *example)
Sets the a usage example for the argument.
const std::vector< Argument * > & path(std::size_t occurrence=0) const
Returns the path of the specified occurrence.
bool isCombinable() const
Returns an indication whether the argument is combinable.
void setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
Assignes the values to be used when generating completion for the values.
std::vector< Argument * > path
The "path" of the occurrence (the parent elements which have been specified before).
UnknownArgumentBehavior
The UnknownArgumentBehavior enum specifies the behavior of the argument parser when an unknown argume...
OperationArgument(const char *name, char abbreviation='\0', const char *description=nullptr, const char *example=nullptr)
void setEnvironmentVariable(const char *environmentVariable)
Sets the environment variable queried when firstValue() is called.
The ArgumentOccurrence struct holds argument values for an occurrence of an argument.
CPP_UTILITIES_EXPORT const char * applicationName
Specifies the name of the application (used by ArgumentParser::printHelp()).
bool isPresent() const
Returns an indication whether the argument could be detected when parsing.
bool hasSubArguments() const
Returns an indication whether the argument has secondary arguments.
The HelpArgument class prints help information for an argument parser when present (–help...
bool allRequiredValuesPresent(std::size_t occurrence=0) const
Returns an indication whether all required values are present.
const ArgumentVector & mainArguments() const
Returns the main arguments.
void setDenotesOperation(bool denotesOperation)
Sets whether the argument denotes the operation.
char abbreviation() const
Returns the abbreviation of the argument.
const char * example() const
Returns the usage example of the argument.
void reset()
Resets occurrences (indices, values and paths).
ArgumentOccurrence(std::size_t index)
Constructs an argument occurrence for the specified index.
void setRequiredValueCount(std::size_t requiredValueCount)
Sets the number of values which are required to be given for this argument.
CPP_UTILITIES_EXPORT const char * applicationAuthor
Specifies the author of the application (used by ArgumentParser::printHelp()).
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
const char * environmentVariable() const
Returns the environment variable queried when firstValue() is called.
unsigned int actualArgumentCount() const
Returns the actual number of arguments that could be found when parsing.
void setName(const char *name)
Sets the name of the argument.
bool isImplicit() const
Returns an indication whether the argument is an implicit argument.
The ArgumentParser class provides a means for handling command line arguments.
void setValueNames(std::initializer_list< const char *> valueNames)
Sets the names of the requried values.
std::vector< Argument * > ArgumentVector
constexpr DirectoryEntryType operator &(DirectoryEntryType lhs, DirectoryEntryType rhs)
Definition: path.h:38
std::vector< const char * > values
The parameter values which have been specified after the occurrence of the argument.