C++ Utilities  4.13.0
Useful C++ classes and routines 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 
75  ReadArguments = 0x0,
76  CheckConstraints = 0x1,
77  InvokeCallbacks = 0x2,
79  = 0x4,
80 };
81 
84 {
85  return static_cast<ParseArgumentBehavior>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
86 }
87 
89 {
90  return static_cast<bool>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
91 }
93 
103 enum class ValueCompletionBehavior : unsigned char {
104  None = 0,
105  PreDefinedValues = 2,
106  Files = 4,
107  Directories = 8,
109  AppendEquationSign = 32,
110  InvokeCallback = 64,
111 };
112 
115 {
116  return static_cast<ValueCompletionBehavior>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
117 }
118 
120 {
121  return static_cast<bool>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
122 }
124 
125 Argument CPP_UTILITIES_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except);
126 
131  ArgumentOccurrence(std::size_t index);
132  ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent);
133 
137  std::size_t index;
138 
142  std::vector<const char *> values;
143 
148  std::vector<Argument *> path;
149 };
150 
154 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index)
155  : index(index)
156 {
157 }
158 
167 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent)
168  : index(index)
169  , path(parentPath)
170 {
171  if (parent) {
172  path.push_back(parent);
173  }
174 }
175 
177  friend ArgumentParser;
178  friend ArgumentReader;
179  friend ArgumentParserTests;
180 
181 public:
182  typedef std::function<void(const ArgumentOccurrence &)> CallbackFunction;
183 
184  Argument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
185  ~Argument();
186 
187  const char *name() const;
188  void setName(const char *name);
189  char abbreviation() const;
190  void setAbbreviation(char abbreviation);
191  const char *environmentVariable() const;
192  void setEnvironmentVariable(const char *environmentVariable);
193  const char *description() const;
194  void setDescription(const char *description);
195  const char *example() const;
196  void setExample(const char *example);
197  const std::vector<const char *> &values(std::size_t occurrence = 0) const;
198  const char *firstValue() const;
199  std::size_t requiredValueCount() const;
200  void setRequiredValueCount(std::size_t requiredValueCount);
201  const std::vector<const char *> &valueNames() const;
202  void setValueNames(std::initializer_list<const char *> valueNames);
203  void appendValueName(const char *valueName);
204  bool allRequiredValuesPresent(std::size_t occurrence = 0) const;
205  bool isPresent() const;
206  std::size_t occurrences() const;
207  std::size_t index(std::size_t occurrence) const;
208  std::size_t minOccurrences() const;
209  std::size_t maxOccurrences() const;
210  void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
211  const std::vector<Argument *> &path(std::size_t occurrence = 0) const;
212  bool isRequired() const;
213  void setRequired(bool required);
214  bool isCombinable() const;
215  void setCombinable(bool value);
216  bool isImplicit() const;
217  void setImplicit(bool value);
218  bool denotesOperation() const;
219  void setDenotesOperation(bool denotesOperation);
220  const CallbackFunction &callback() const;
221  void setCallback(CallbackFunction callback);
222  void printInfo(std::ostream &os, unsigned char indentation = 0) const;
223  const ArgumentVector &subArguments() const;
224  void setSubArguments(const ArgumentInitializerList &subArguments);
225  void addSubArgument(Argument *arg);
226  bool hasSubArguments() const;
227  const ArgumentVector parents() const;
228  bool isMainArgument() const;
229  bool isParentPresent() const;
230  ValueCompletionBehavior valueCompletionBehaviour() const;
231  void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour);
232  const char *preDefinedCompletionValues() const;
233  void setPreDefinedCompletionValues(const char *preDefinedCompletionValues);
234  Argument *conflictsWithArgument() const;
235  Argument *wouldConflictWithArgument() const;
236  Argument *specifiedOperation() const;
237  void reset();
238  void resetRecursively();
239  const std::vector<ArgumentOccurrence> &occurrenceInfo() const;
240  std::vector<ArgumentOccurrence> &occurrenceInfo();
241 
246  static constexpr std::size_t varValueCount = std::numeric_limits<std::size_t>::max();
247 
248 private:
249  bool matchesDenotation(const char *denotation, size_t denotationLength) const;
250 
251  const char *m_name;
252  char m_abbreviation;
253  const char *m_environmentVar;
254  const char *m_description;
255  const char *m_example;
256  std::size_t m_minOccurrences;
257  std::size_t m_maxOccurrences;
258  bool m_combinable;
259  bool m_denotesOperation;
260  std::size_t m_requiredValueCount;
261  std::vector<const char *> m_valueNames;
262  bool m_implicit;
263  std::vector<ArgumentOccurrence> m_occurrences;
264  ArgumentVector m_subArgs;
265  CallbackFunction m_callbackFunction;
266  ArgumentVector m_parents;
267  bool m_isMainArg;
268  ValueCompletionBehavior m_valueCompletionBehavior;
269  const char *m_preDefinedCompletionValues;
270 };
271 
273  friend ArgumentParserTests;
274  friend ArgumentReader;
275 
276 public:
277  ArgumentParser();
278 
279  const ArgumentVector &mainArguments() const;
280  void setMainArguments(const ArgumentInitializerList &mainArguments);
281  void addMainArgument(Argument *argument);
282  void printHelp(std::ostream &os) const;
283  void parseArgs(int argc, const char *const *argv);
284  void parseArgsOrExit(int argc, const char *const *argv);
285  void parseArgsExt(int argc, const char *const *argv,
286  ParseArgumentBehavior behavior
288  void readArgs(int argc, const char *const *argv);
289  void resetArgs();
290  unsigned int actualArgumentCount() const;
291  const char *executable() const;
292  UnknownArgumentBehavior unknownArgumentBehavior() const;
293  void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior);
294  Argument *defaultArgument() const;
295  void setDefaultArgument(Argument *argument);
296  Argument *specifiedOperation() const;
297  void checkConstraints();
298  void invokeCallbacks();
299  bool isUncombinableMainArgPresent() const;
300 
301 private:
302  IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args);)
303  void printBashCompletion(int argc, const char *const *argv, unsigned int cursorPos, const ArgumentReader &reader);
304  void checkConstraints(const ArgumentVector &args);
305  static void invokeCallbacks(const ArgumentVector &args);
306 
307  ArgumentVector m_mainArgs;
308  unsigned int m_actualArgc;
309  const char *m_executable;
310  UnknownArgumentBehavior m_unknownArgBehavior;
311  Argument *m_defaultArg;
312 };
313 
319 inline const char *Argument::name() const
320 {
321  return m_name;
322 }
323 
331 inline void Argument::setName(const char *name)
332 {
333 #ifdef DEBUG_BUILD
334  if (name && *name) {
335  assert(*name != '-');
336  for (const char *c = name; *c; ++c) {
337  assert(*c != ' ' && *c != '=' && *c != '\'' && *c != '\"' && *c != '\n' && *c != '\r');
338  }
339  }
340 #endif
341  m_name = name;
342 }
343 
349 inline char Argument::abbreviation() const
350 {
351  return m_abbreviation;
352 }
353 
361 inline void Argument::setAbbreviation(char abbreviation)
362 {
363  IF_DEBUG_BUILD(assert(abbreviation != ' ' && abbreviation != '=' && abbreviation != '-' && abbreviation != '\'' && abbreviation != '"'
364  && abbreviation != '\n' && abbreviation != '\r'));
365  m_abbreviation = abbreviation;
366 }
367 
372 inline const char *Argument::environmentVariable() const
373 {
374  return m_environmentVar;
375 }
376 
381 inline void Argument::setEnvironmentVariable(const char *environmentVariable)
382 {
383  m_environmentVar = environmentVariable;
384 }
385 
391 inline const char *Argument::description() const
392 {
393  return m_description;
394 }
395 
401 inline void Argument::setDescription(const char *description)
402 {
403  m_description = description;
404 }
405 
411 inline const char *Argument::example() const
412 {
413  return m_example;
414 }
415 
421 inline void Argument::setExample(const char *example)
422 {
423  m_example = example;
424 }
425 
432 inline const std::vector<const char *> &Argument::values(std::size_t occurrence) const
433 {
434  return m_occurrences[occurrence].values;
435 }
436 
450 inline std::size_t Argument::requiredValueCount() const
451 {
452  return m_requiredValueCount;
453 }
454 
467 inline void Argument::setRequiredValueCount(std::size_t requiredValueCount)
468 {
469  m_requiredValueCount = requiredValueCount;
470 }
471 
480 inline const std::vector<const char *> &Argument::valueNames() const
481 {
482  return m_valueNames;
483 }
484 
498 inline void Argument::setValueNames(std::initializer_list<const char *> valueNames)
499 {
500  m_valueNames.assign(valueNames);
501 }
502 
509 inline void Argument::appendValueName(const char *valueName)
510 {
511  m_valueNames.emplace_back(valueName);
512 }
513 
517 inline bool Argument::allRequiredValuesPresent(std::size_t occurrence) const
518 {
519  return m_requiredValueCount == Argument::varValueCount
520  || (m_occurrences[occurrence].values.size() >= static_cast<std::size_t>(m_requiredValueCount));
521 }
522 
527 inline bool Argument::isImplicit() const
528 {
529  return m_implicit;
530 }
531 
536 inline void Argument::setImplicit(bool implicit)
537 {
538  m_implicit = implicit;
539 }
540 
544 inline bool Argument::isPresent() const
545 {
546  return !m_occurrences.empty();
547 }
548 
552 inline std::size_t Argument::occurrences() const
553 {
554  return m_occurrences.size();
555 }
556 
560 inline std::size_t Argument::index(std::size_t occurrence) const
561 {
562  return m_occurrences[occurrence].index;
563 }
564 
570 inline std::size_t Argument::minOccurrences() const
571 {
572  return m_minOccurrences;
573 }
574 
580 inline std::size_t Argument::maxOccurrences() const
581 {
582  return m_maxOccurrences;
583 }
584 
590 inline void Argument::setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
591 {
592  m_minOccurrences = minOccurrences;
593  m_maxOccurrences = maxOccurrences;
594 }
595 
599 inline const std::vector<Argument *> &Argument::path(std::size_t occurrence) const
600 {
601  return m_occurrences[occurrence].path;
602 }
603 
613 inline bool Argument::isRequired() const
614 {
615  return m_minOccurrences;
616 }
617 
625 inline void Argument::setRequired(bool required)
626 {
627  if (required) {
628  if (!m_minOccurrences) {
629  m_minOccurrences = 1;
630  }
631  } else {
632  m_minOccurrences = 0;
633  }
634 }
635 
644 inline bool Argument::isCombinable() const
645 {
646  return m_combinable;
647 }
648 
657 inline void Argument::setCombinable(bool value)
658 {
659  m_combinable = value;
660 }
661 
672 inline bool Argument::denotesOperation() const
673 {
674  return m_denotesOperation;
675 }
676 
681 inline void Argument::setDenotesOperation(bool denotesOperation)
682 {
683  m_denotesOperation = denotesOperation;
684 }
685 
691 {
692  return m_callbackFunction;
693 }
694 
702 {
703  m_callbackFunction = callback;
704 }
705 
713 {
714  return m_subArgs;
715 }
716 
723 inline bool Argument::hasSubArguments() const
724 {
725  return !m_subArgs.empty();
726 }
727 
738 inline const ArgumentVector Argument::parents() const
739 {
740  return m_parents;
741 }
742 
749 inline bool Argument::isMainArgument() const
750 {
751  return m_isMainArg;
752 }
753 
761 {
762  return m_valueCompletionBehavior;
763 }
764 
772 {
773  m_valueCompletionBehavior = completionValues;
774 }
775 
779 inline const char *Argument::preDefinedCompletionValues() const
780 {
781  return m_preDefinedCompletionValues;
782 }
783 
787 inline void Argument::setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
788 {
789  m_preDefinedCompletionValues = preDefinedCompletionValues;
790 }
791 
795 inline void Argument::reset()
796 {
797  m_occurrences.clear();
798 }
799 
804 inline const std::vector<ArgumentOccurrence> &Argument::occurrenceInfo() const
805 {
806  return m_occurrences;
807 }
808 
815 inline std::vector<ArgumentOccurrence> &Argument::occurrenceInfo()
816 {
817  return m_occurrences;
818 }
819 
825 {
826  return m_mainArgs;
827 }
828 
832 inline unsigned int ArgumentParser::actualArgumentCount() const
833 {
834  return m_actualArgc;
835 }
836 
840 inline const char *ArgumentParser::executable() const
841 {
842  return m_executable;
843 }
844 
851 {
852  return m_unknownArgBehavior;
853 }
854 
861 {
862  m_unknownArgBehavior = behavior;
863 }
864 
870 {
871  return m_defaultArg;
872 }
873 
879 {
880  m_defaultArg = argument;
881 }
882 
889 {
890  checkConstraints(m_mainArgs);
891 }
892 
898 {
899  invokeCallbacks(m_mainArgs);
900 }
901 
903 public:
904  HelpArgument(ArgumentParser &parser);
905 };
906 
908 public:
909  OperationArgument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
910 };
911 
912 inline OperationArgument::OperationArgument(const char *name, char abbreviation, const char *description, const char *example)
913  : Argument(name, abbreviation, description, example)
914 {
915  setDenotesOperation(true);
916 }
917 
919 public:
920  ConfigValueArgument(const char *name, char abbreviation = '\0', const char *description = nullptr,
921  std::initializer_list<const char *> valueNames = std::initializer_list<const char *>());
922 };
923 
928  const char *name, char abbreviation, const char *description, std::initializer_list<const char *> valueNames)
929  : Argument(name, abbreviation, description)
930 {
931  setCombinable(true);
934 }
935 
937  friend ArgumentParserTests;
938 
939 public:
940  NoColorArgument();
941  ~NoColorArgument();
942  static void apply();
943 
944 private:
945  static NoColorArgument *s_instance;
946 };
947 
948 } // namespace ApplicationUtilities
949 
950 #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.
const std::vector< ArgumentOccurrence > & occurrenceInfo() const
Returns information about all occurrences of the argument which have been detected when parsing...
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.
ParseArgumentBehavior
The ParseArgumentBehavior enum specifies the behavior when parsing arguments.
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.
static constexpr std::size_t varValueCount
Denotes a variable number of values.
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.