C++ Utilities  4.11.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 
77 enum class ValueCompletionBehavior : unsigned char {
78  None = 0,
79  PreDefinedValues = 2,
80  Files = 4,
81  Directories = 8,
83  AppendEquationSign = 32,
84  InvokeCallback = 64,
85 };
86 
89 {
90  return static_cast<ValueCompletionBehavior>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
91 }
92 
94 {
95  return static_cast<bool>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
96 }
98 
99 Argument CPP_UTILITIES_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except);
100 
105  ArgumentOccurrence(std::size_t index);
106  ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent);
107 
111  std::size_t index;
112 
116  std::vector<const char *> values;
117 
122  std::vector<Argument *> path;
123 };
124 
128 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index)
129  : index(index)
130 {
131 }
132 
141 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent)
142  : index(index)
143  , path(parentPath)
144 {
145  if (parent) {
146  path.push_back(parent);
147  }
148 }
149 
151  friend ArgumentParser;
152  friend ArgumentReader;
153  friend ArgumentParserTests;
154 
155 public:
156  typedef std::function<void(const ArgumentOccurrence &)> CallbackFunction;
157 
158  Argument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
159  ~Argument();
160 
161  const char *name() const;
162  void setName(const char *name);
163  char abbreviation() const;
164  void setAbbreviation(char abbreviation);
165  const char *environmentVariable() const;
166  void setEnvironmentVariable(const char *environmentVariable);
167  const char *description() const;
168  void setDescription(const char *description);
169  const char *example() const;
170  void setExample(const char *example);
171  const std::vector<const char *> &values(std::size_t occurrence = 0) const;
172  const char *firstValue() const;
173  std::size_t requiredValueCount() const;
174  void setRequiredValueCount(std::size_t requiredValueCount);
175  const std::vector<const char *> &valueNames() const;
176  void setValueNames(std::initializer_list<const char *> valueNames);
177  void appendValueName(const char *valueName);
178  bool allRequiredValuesPresent(std::size_t occurrence = 0) const;
179  bool isPresent() const;
180  std::size_t occurrences() const;
181  std::size_t index(std::size_t occurrence) const;
182  std::size_t minOccurrences() const;
183  std::size_t maxOccurrences() const;
184  void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
185  const std::vector<Argument *> &path(std::size_t occurrence = 0) const;
186  bool isRequired() const;
187  void setRequired(bool required);
188  bool isCombinable() const;
189  void setCombinable(bool value);
190  bool isImplicit() const;
191  void setImplicit(bool value);
192  bool denotesOperation() const;
193  void setDenotesOperation(bool denotesOperation);
194  const CallbackFunction &callback() const;
195  void setCallback(CallbackFunction callback);
196  void printInfo(std::ostream &os, unsigned char indentation = 0) const;
197  const ArgumentVector &subArguments() const;
198  void setSubArguments(const ArgumentInitializerList &subArguments);
199  void addSubArgument(Argument *arg);
200  bool hasSubArguments() const;
201  const ArgumentVector parents() const;
202  bool isMainArgument() const;
203  bool isParentPresent() const;
204  ValueCompletionBehavior valueCompletionBehaviour() const;
205  void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour);
206  const char *preDefinedCompletionValues() const;
207  void setPreDefinedCompletionValues(const char *preDefinedCompletionValues);
208  Argument *conflictsWithArgument() const;
209  Argument *wouldConflictWithArgument() const;
210  Argument *specifiedOperation() const;
211  void reset();
212  void resetRecursively();
213 
218  static constexpr std::size_t varValueCount = std::numeric_limits<std::size_t>::max();
219 
220 private:
221  const char *m_name;
222  char m_abbreviation;
223  const char *m_environmentVar;
224  const char *m_description;
225  const char *m_example;
226  std::size_t m_minOccurrences;
227  std::size_t m_maxOccurrences;
228  bool m_combinable;
229  bool m_denotesOperation;
230  std::size_t m_requiredValueCount;
231  std::vector<const char *> m_valueNames;
232  bool m_implicit;
233  std::vector<ArgumentOccurrence> m_occurrences;
234  ArgumentVector m_subArgs;
235  CallbackFunction m_callbackFunction;
236  ArgumentVector m_parents;
237  bool m_isMainArg;
238  ValueCompletionBehavior m_valueCompletionBehavior;
239  const char *m_preDefinedCompletionValues;
240 };
241 
243  friend ArgumentParserTests;
244  friend ArgumentReader;
245 
246 public:
247  ArgumentParser();
248 
249  const ArgumentVector &mainArguments() const;
250  void setMainArguments(const ArgumentInitializerList &mainArguments);
251  void addMainArgument(Argument *argument);
252  void printHelp(std::ostream &os) const;
253  void parseArgs(int argc, const char *const *argv);
254  void parseArgsOrExit(int argc, const char *const *argv);
255  void readArgs(int argc, const char *const *argv);
256  void resetArgs();
257  unsigned int actualArgumentCount() const;
258  const char *executable() const;
259  UnknownArgumentBehavior unknownArgumentBehavior() const;
260  void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior);
261  Argument *defaultArgument() const;
262  void setDefaultArgument(Argument *argument);
263  Argument *specifiedOperation() const;
264  void checkConstraints();
265  void invokeCallbacks();
266  bool isUncombinableMainArgPresent() const;
267 
268 private:
269  IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args, std::vector<char> abbreviations, std::vector<const char *> names);)
270  void printBashCompletion(int argc, const char *const *argv, unsigned int cursorPos, const ArgumentReader &reader);
271  void checkConstraints(const ArgumentVector &args);
272  static void invokeCallbacks(const ArgumentVector &args);
273 
274  ArgumentVector m_mainArgs;
275  unsigned int m_actualArgc;
276  const char *m_executable;
277  UnknownArgumentBehavior m_unknownArgBehavior;
278  Argument *m_defaultArg;
279 };
280 
286 inline const char *Argument::name() const
287 {
288  return m_name;
289 }
290 
298 inline void Argument::setName(const char *name)
299 {
300 #ifdef DEBUG_BUILD
301  if (name && *name) {
302  assert(*name != '-');
303  for (const char *c = name; *c; ++c) {
304  assert(*c != ' ' && *c != '=' && *c != '\'' && *c != '\"' && *c != '\n' && *c != '\r');
305  }
306  }
307 #endif
308  m_name = name;
309 }
310 
316 inline char Argument::abbreviation() const
317 {
318  return m_abbreviation;
319 }
320 
328 inline void Argument::setAbbreviation(char abbreviation)
329 {
330  IF_DEBUG_BUILD(assert(abbreviation != ' ' && abbreviation != '=' && abbreviation != '-' && abbreviation != '\'' && abbreviation != '"'
331  && abbreviation != '\n' && abbreviation != '\r'));
332  m_abbreviation = abbreviation;
333 }
334 
339 inline const char *Argument::environmentVariable() const
340 {
341  return m_environmentVar;
342 }
343 
348 inline void Argument::setEnvironmentVariable(const char *environmentVariable)
349 {
350  m_environmentVar = environmentVariable;
351 }
352 
358 inline const char *Argument::description() const
359 {
360  return m_description;
361 }
362 
368 inline void Argument::setDescription(const char *description)
369 {
370  m_description = description;
371 }
372 
378 inline const char *Argument::example() const
379 {
380  return m_example;
381 }
382 
388 inline void Argument::setExample(const char *example)
389 {
390  m_example = example;
391 }
392 
399 inline const std::vector<const char *> &Argument::values(std::size_t occurrence) const
400 {
401  return m_occurrences[occurrence].values;
402 }
403 
417 inline std::size_t Argument::requiredValueCount() const
418 {
419  return m_requiredValueCount;
420 }
421 
434 inline void Argument::setRequiredValueCount(std::size_t requiredValueCount)
435 {
436  m_requiredValueCount = requiredValueCount;
437 }
438 
447 inline const std::vector<const char *> &Argument::valueNames() const
448 {
449  return m_valueNames;
450 }
451 
465 inline void Argument::setValueNames(std::initializer_list<const char *> valueNames)
466 {
467  m_valueNames.assign(valueNames);
468 }
469 
476 inline void Argument::appendValueName(const char *valueName)
477 {
478  m_valueNames.emplace_back(valueName);
479 }
480 
484 inline bool Argument::allRequiredValuesPresent(std::size_t occurrence) const
485 {
486  return m_requiredValueCount == static_cast<std::size_t>(-1)
487  || (m_occurrences[occurrence].values.size() >= static_cast<std::size_t>(m_requiredValueCount));
488 }
489 
494 inline bool Argument::isImplicit() const
495 {
496  return m_implicit;
497 }
498 
503 inline void Argument::setImplicit(bool implicit)
504 {
505  m_implicit = implicit;
506 }
507 
511 inline bool Argument::isPresent() const
512 {
513  return !m_occurrences.empty();
514 }
515 
519 inline std::size_t Argument::occurrences() const
520 {
521  return m_occurrences.size();
522 }
523 
527 inline std::size_t Argument::index(std::size_t occurrence) const
528 {
529  return m_occurrences[occurrence].index;
530 }
531 
537 inline std::size_t Argument::minOccurrences() const
538 {
539  return m_minOccurrences;
540 }
541 
547 inline std::size_t Argument::maxOccurrences() const
548 {
549  return m_maxOccurrences;
550 }
551 
557 inline void Argument::setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
558 {
559  m_minOccurrences = minOccurrences;
560  m_maxOccurrences = maxOccurrences;
561 }
562 
566 inline const std::vector<Argument *> &Argument::path(std::size_t occurrence) const
567 {
568  return m_occurrences[occurrence].path;
569 }
570 
580 inline bool Argument::isRequired() const
581 {
582  return m_minOccurrences;
583 }
584 
592 inline void Argument::setRequired(bool required)
593 {
594  if (required) {
595  if (!m_minOccurrences) {
596  m_minOccurrences = 1;
597  }
598  } else {
599  m_minOccurrences = 0;
600  }
601 }
602 
611 inline bool Argument::isCombinable() const
612 {
613  return m_combinable;
614 }
615 
624 inline void Argument::setCombinable(bool value)
625 {
626  m_combinable = value;
627 }
628 
639 inline bool Argument::denotesOperation() const
640 {
641  return m_denotesOperation;
642 }
643 
648 inline void Argument::setDenotesOperation(bool denotesOperation)
649 {
650  m_denotesOperation = denotesOperation;
651 }
652 
658 {
659  return m_callbackFunction;
660 }
661 
669 {
670  m_callbackFunction = callback;
671 }
672 
679 inline const ArgumentVector &Argument::subArguments() const
680 {
681  return m_subArgs;
682 }
683 
690 inline bool Argument::hasSubArguments() const
691 {
692  return !m_subArgs.empty();
693 }
694 
705 inline const ArgumentVector Argument::parents() const
706 {
707  return m_parents;
708 }
709 
716 inline bool Argument::isMainArgument() const
717 {
718  return m_isMainArg;
719 }
720 
725 {
726  return m_valueCompletionBehavior;
727 }
728 
733 {
734  m_valueCompletionBehavior = completionValues;
735 }
736 
740 inline const char *Argument::preDefinedCompletionValues() const
741 {
742  return m_preDefinedCompletionValues;
743 }
744 
748 inline void Argument::setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
749 {
750  m_preDefinedCompletionValues = preDefinedCompletionValues;
751 }
752 
756 inline void Argument::reset()
757 {
758  m_occurrences.clear();
759 }
760 
765 inline const ArgumentVector &ArgumentParser::mainArguments() const
766 {
767  return m_mainArgs;
768 }
769 
773 inline unsigned int ArgumentParser::actualArgumentCount() const
774 {
775  return m_actualArgc;
776 }
777 
781 inline const char *ArgumentParser::executable() const
782 {
783  return m_executable;
784 }
785 
792 {
793  return m_unknownArgBehavior;
794 }
795 
802 {
803  m_unknownArgBehavior = behavior;
804 }
805 
811 {
812  return m_defaultArg;
813 }
814 
820 {
821  m_defaultArg = argument;
822 }
823 
830 {
831  checkConstraints(m_mainArgs);
832 }
833 
839 {
840  invokeCallbacks(m_mainArgs);
841 }
842 
844 public:
845  HelpArgument(ArgumentParser &parser);
846 };
847 
849 public:
850  OperationArgument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
851 };
852 
853 inline OperationArgument::OperationArgument(const char *name, char abbreviation, const char *description, const char *example)
854  : Argument(name, abbreviation, description, example)
855 {
856  setDenotesOperation(true);
857 }
858 
860 public:
861  ConfigValueArgument(const char *name, char abbreviation = '\0', const char *description = nullptr,
862  std::initializer_list<const char *> valueNames = std::initializer_list<const char *>());
863 };
864 
869  const char *name, char abbreviation, const char *description, std::initializer_list<const char *> valueNames)
870  : Argument(name, abbreviation, description)
871 {
872  setCombinable(true);
873  setRequiredValueCount(valueNames.size());
874  setValueNames(valueNames);
875 }
876 
878 public:
879  NoColorArgument();
880  ~NoColorArgument();
881  static void apply();
882 
883 private:
884  static NoColorArgument *s_instance;
885 };
886 
887 } // namespace ApplicationUtilities
888 
889 #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 NoColorArgument class allows to specify whether use of escape codes or similar technique to provi...
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.
const CallbackFunction & callback() const
Returns the assigned callback function.
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()).
The ArgumentReader class internally encapsulates the process of reading command line arguments...
#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.