C++ Utilities  4.9.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  friend ArgumentParserTests;
147 
148 public:
149  typedef std::function<void(const ArgumentOccurrence &)> CallbackFunction;
150 
151  Argument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
152  ~Argument();
153 
154  const char *name() const;
155  void setName(const char *name);
156  char abbreviation() const;
157  void setAbbreviation(char abbreviation);
158  const char *environmentVariable() const;
159  void setEnvironmentVariable(const char *environmentVariable);
160  const char *description() const;
161  void setDescription(const char *description);
162  const char *example() const;
163  void setExample(const char *example);
164  const std::vector<const char *> &values(std::size_t occurrence = 0) const;
165  const char *firstValue() const;
166  std::size_t requiredValueCount() const;
167  void setRequiredValueCount(std::size_t requiredValueCount);
168  const std::vector<const char *> &valueNames() const;
169  void setValueNames(std::initializer_list<const char *> valueNames);
170  void appendValueName(const char *valueName);
171  bool allRequiredValuesPresent(std::size_t occurrence = 0) const;
172  bool isPresent() const;
173  std::size_t occurrences() const;
174  std::size_t index(std::size_t occurrence) const;
175  std::size_t minOccurrences() const;
176  std::size_t maxOccurrences() const;
177  void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
178  const std::vector<Argument *> &path(std::size_t occurrence = 0) const;
179  bool isRequired() const;
180  void setRequired(bool required);
181  bool isCombinable() const;
182  void setCombinable(bool value);
183  bool isImplicit() const;
184  void setImplicit(bool value);
185  bool denotesOperation() const;
186  void setDenotesOperation(bool denotesOperation);
187  void setCallback(CallbackFunction callback);
188  void printInfo(std::ostream &os, unsigned char indentation = 0) const;
189  const ArgumentVector &subArguments() const;
190  void setSubArguments(const ArgumentInitializerList &subArguments);
191  void addSubArgument(Argument *arg);
192  bool hasSubArguments() const;
193  const ArgumentVector parents() const;
194  bool isMainArgument() const;
195  bool isParentPresent() const;
196  ValueCompletionBehavior valueCompletionBehaviour() const;
197  void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour);
198  const char *preDefinedCompletionValues() const;
199  void setPreDefinedCompletionValues(const char *preDefinedCompletionValues);
200  Argument *conflictsWithArgument() const;
201  Argument *wouldConflictWithArgument() const;
202  void reset();
203  void resetRecursively();
204 
209  static constexpr std::size_t varValueCount = std::numeric_limits<std::size_t>::max();
210 
211 private:
212  const char *m_name;
213  char m_abbreviation;
214  const char *m_environmentVar;
215  const char *m_description;
216  const char *m_example;
217  std::size_t m_minOccurrences;
218  std::size_t m_maxOccurrences;
219  bool m_combinable;
220  bool m_denotesOperation;
221  std::size_t m_requiredValueCount;
222  std::vector<const char *> m_valueNames;
223  bool m_implicit;
224  std::vector<ArgumentOccurrence> m_occurrences;
225  ArgumentVector m_subArgs;
226  CallbackFunction m_callbackFunction;
227  ArgumentVector m_parents;
228  bool m_isMainArg;
229  ValueCompletionBehavior m_valueCompletionBehavior;
230  const char *m_preDefinedCompletionValues;
231 };
232 
234  friend ArgumentParserTests;
235  friend ArgumentReader;
236 
237 public:
238  ArgumentParser();
239 
240  const ArgumentVector &mainArguments() const;
241  void setMainArguments(const ArgumentInitializerList &mainArguments);
242  void addMainArgument(Argument *argument);
243  void printHelp(std::ostream &os) const;
244  void parseArgs(int argc, const char *const *argv);
245  void readArgs(int argc, const char *const *argv);
246  void resetArgs();
247  unsigned int actualArgumentCount() const;
248  const char *executable() const;
249  UnknownArgumentBehavior unknownArgumentBehavior() const;
250  void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior);
251  Argument *defaultArgument() const;
252  void setDefaultArgument(Argument *argument);
253  void checkConstraints();
254  void invokeCallbacks();
255  bool isUncombinableMainArgPresent() const;
256 
257 private:
258  IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args, std::vector<char> abbreviations, std::vector<const char *> names);)
259  void printBashCompletion(int argc, const char *const *argv, unsigned int cursorPos, const ArgumentReader &reader);
260  void checkConstraints(const ArgumentVector &args);
261  void invokeCallbacks(const ArgumentVector &args);
262 
263  ArgumentVector m_mainArgs;
264  unsigned int m_actualArgc;
265  const char *m_executable;
266  UnknownArgumentBehavior m_unknownArgBehavior;
267  Argument *m_defaultArg;
268 };
269 
275 inline const char *Argument::name() const
276 {
277  return m_name;
278 }
279 
287 inline void Argument::setName(const char *name)
288 {
289 #ifdef DEBUG_BUILD
290  if (name && *name) {
291  assert(*name != '-');
292  for (const char *c = name; *c; ++c) {
293  assert(*c != ' ' && *c != '=' && *c != '\'' && *c != '\"' && *c != '\n' && *c != '\r');
294  }
295  }
296 #endif
297  m_name = name;
298 }
299 
305 inline char Argument::abbreviation() const
306 {
307  return m_abbreviation;
308 }
309 
317 inline void Argument::setAbbreviation(char abbreviation)
318 {
319  IF_DEBUG_BUILD(assert(abbreviation != ' ' && abbreviation != '=' && abbreviation != '-' && abbreviation != '\'' && abbreviation != '"'
320  && abbreviation != '\n' && abbreviation != '\r'));
321  m_abbreviation = abbreviation;
322 }
323 
328 inline const char *Argument::environmentVariable() const
329 {
330  return m_environmentVar;
331 }
332 
337 inline void Argument::setEnvironmentVariable(const char *environmentVariable)
338 {
339  m_environmentVar = environmentVariable;
340 }
341 
347 inline const char *Argument::description() const
348 {
349  return m_description;
350 }
351 
357 inline void Argument::setDescription(const char *description)
358 {
359  m_description = description;
360 }
361 
367 inline const char *Argument::example() const
368 {
369  return m_example;
370 }
371 
377 inline void Argument::setExample(const char *example)
378 {
379  m_example = example;
380 }
381 
388 inline const std::vector<const char *> &Argument::values(std::size_t occurrence) const
389 {
390  return m_occurrences[occurrence].values;
391 }
392 
406 inline std::size_t Argument::requiredValueCount() const
407 {
408  return m_requiredValueCount;
409 }
410 
423 inline void Argument::setRequiredValueCount(std::size_t requiredValueCount)
424 {
425  m_requiredValueCount = requiredValueCount;
426 }
427 
436 inline const std::vector<const char *> &Argument::valueNames() const
437 {
438  return m_valueNames;
439 }
440 
454 inline void Argument::setValueNames(std::initializer_list<const char *> valueNames)
455 {
456  m_valueNames.assign(valueNames);
457 }
458 
465 inline void Argument::appendValueName(const char *valueName)
466 {
467  m_valueNames.emplace_back(valueName);
468 }
469 
473 inline bool Argument::allRequiredValuesPresent(std::size_t occurrence) const
474 {
475  return m_requiredValueCount == static_cast<std::size_t>(-1)
476  || (m_occurrences[occurrence].values.size() >= static_cast<std::size_t>(m_requiredValueCount));
477 }
478 
483 inline bool Argument::isImplicit() const
484 {
485  return m_implicit;
486 }
487 
492 inline void Argument::setImplicit(bool implicit)
493 {
494  m_implicit = implicit;
495 }
496 
500 inline bool Argument::isPresent() const
501 {
502  return !m_occurrences.empty();
503 }
504 
508 inline std::size_t Argument::occurrences() const
509 {
510  return m_occurrences.size();
511 }
512 
516 inline std::size_t Argument::index(std::size_t occurrence) const
517 {
518  return m_occurrences[occurrence].index;
519 }
520 
526 inline std::size_t Argument::minOccurrences() const
527 {
528  return m_minOccurrences;
529 }
530 
536 inline std::size_t Argument::maxOccurrences() const
537 {
538  return m_maxOccurrences;
539 }
540 
546 inline void Argument::setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
547 {
548  m_minOccurrences = minOccurrences;
549  m_maxOccurrences = maxOccurrences;
550 }
551 
555 inline const std::vector<Argument *> &Argument::path(std::size_t occurrence) const
556 {
557  return m_occurrences[occurrence].path;
558 }
559 
569 inline bool Argument::isRequired() const
570 {
571  return m_minOccurrences;
572 }
573 
581 inline void Argument::setRequired(bool required)
582 {
583  if (required) {
584  if (!m_minOccurrences) {
585  m_minOccurrences = 1;
586  }
587  } else {
588  m_minOccurrences = 0;
589  }
590 }
591 
600 inline bool Argument::isCombinable() const
601 {
602  return m_combinable;
603 }
604 
613 inline void Argument::setCombinable(bool value)
614 {
615  m_combinable = value;
616 }
617 
628 inline bool Argument::denotesOperation() const
629 {
630  return m_denotesOperation;
631 }
632 
637 inline void Argument::setDenotesOperation(bool denotesOperation)
638 {
639  m_denotesOperation = denotesOperation;
640 }
641 
648 {
649  m_callbackFunction = callback;
650 }
651 
658 inline const ArgumentVector &Argument::subArguments() const
659 {
660  return m_subArgs;
661 }
662 
669 inline bool Argument::hasSubArguments() const
670 {
671  return !m_subArgs.empty();
672 }
673 
684 inline const ArgumentVector Argument::parents() const
685 {
686  return m_parents;
687 }
688 
695 inline bool Argument::isMainArgument() const
696 {
697  return m_isMainArg;
698 }
699 
704 {
705  return m_valueCompletionBehavior;
706 }
707 
712 {
713  m_valueCompletionBehavior = completionValues;
714 }
715 
719 inline const char *Argument::preDefinedCompletionValues() const
720 {
721  return m_preDefinedCompletionValues;
722 }
723 
727 inline void Argument::setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
728 {
729  m_preDefinedCompletionValues = preDefinedCompletionValues;
730 }
731 
735 inline void Argument::reset()
736 {
737  m_occurrences.clear();
738 }
739 
744 inline const ArgumentVector &ArgumentParser::mainArguments() const
745 {
746  return m_mainArgs;
747 }
748 
752 inline unsigned int ArgumentParser::actualArgumentCount() const
753 {
754  return m_actualArgc;
755 }
756 
760 inline const char *ArgumentParser::executable() const
761 {
762  return m_executable;
763 }
764 
771 {
772  return m_unknownArgBehavior;
773 }
774 
781 {
782  m_unknownArgBehavior = behavior;
783 }
784 
790 {
791  return m_defaultArg;
792 }
793 
799 {
800  m_defaultArg = argument;
801 }
802 
809 {
810  checkConstraints(m_mainArgs);
811 }
812 
818 {
819  invokeCallbacks(m_mainArgs);
820 }
821 
823 public:
824  HelpArgument(ArgumentParser &parser);
825 };
826 
828 public:
829  OperationArgument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
830 };
831 
832 inline OperationArgument::OperationArgument(const char *name, char abbreviation, const char *description, const char *example)
833  : Argument(name, abbreviation, description, example)
834 {
835  setDenotesOperation(true);
836 }
837 
839 public:
840  ConfigValueArgument(const char *name, char abbreviation = '\0', const char *description = nullptr,
841  std::initializer_list<const char *> valueNames = std::initializer_list<const char *>());
842 };
843 
848  const char *name, char abbreviation, const char *description, std::initializer_list<const char *> valueNames)
849  : Argument(name, abbreviation, description)
850 {
851  setCombinable(true);
852  setRequiredValueCount(valueNames.size());
853  setValueNames(valueNames);
854 }
855 }
856 
857 #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.