C++ Utilities  4.6.1
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 <vector>
7 #include <initializer_list>
8 #include <functional>
9 #ifdef DEBUG_BUILD
10 # include <cassert>
11 #endif
12 
14 
16 
17 CPP_UTILITIES_EXPORT extern const char *applicationName;
18 CPP_UTILITIES_EXPORT extern const char *applicationAuthor;
19 CPP_UTILITIES_EXPORT extern const char *applicationVersion;
20 CPP_UTILITIES_EXPORT extern const char *applicationUrl;
21 
27 #define SET_APPLICATION_INFO \
28  ::ApplicationUtilities::applicationName = APP_NAME; \
29  ::ApplicationUtilities::applicationAuthor = APP_AUTHOR; \
30  ::ApplicationUtilities::applicationVersion = APP_VERSION; \
31  ::ApplicationUtilities::applicationUrl = APP_URL
32 
33 CPP_UTILITIES_EXPORT extern void(*exitFunction)(int);
34 
35 class Argument;
36 class ArgumentParser;
38 
39 typedef std::initializer_list<Argument *> ArgumentInitializerList;
40 typedef std::vector<Argument *> ArgumentVector;
41 typedef std::function<bool (Argument *)> ArgumentPredicate;
42 
48 {
49  Ignore,
50  Warn,
51  Fail
52 };
53 
57 enum class ValueCompletionBehavior : unsigned char
58 {
59  None = 0,
60  PreDefinedValues = 2,
61  Files = 4,
62  Directories = 8,
64  AppendEquationSign = 32
65 };
66 
69 {
70  return static_cast<ValueCompletionBehavior>(static_cast<unsigned char>(lhs) | static_cast<unsigned char>(rhs));
71 }
72 
74 {
75  return static_cast<bool>(static_cast<unsigned char>(lhs) & static_cast<unsigned char>(rhs));
76 }
78 
79 Argument CPP_UTILITIES_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except);
80 
85 {
86  ArgumentOccurrence(std::size_t index);
87  ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent);
88 
92  std::size_t index;
93 
97  std::vector<const char *> values;
98 
103  std::vector<Argument *> path;
104 };
105 
109 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index) :
110  index(index)
111 {}
112 
121 inline ArgumentOccurrence::ArgumentOccurrence(std::size_t index, const std::vector<Argument *> parentPath, Argument *parent) :
122  index(index),
123  path(parentPath)
124 {
125  if(parent) {
126  path.push_back(parent);
127  }
128 }
129 
131 {
132  friend ArgumentParser;
133  friend ArgumentReader;
134 
135 public:
136  typedef std::function <void (const ArgumentOccurrence &)> CallbackFunction;
137 
138  Argument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
139  ~Argument();
140 
141  const char *name() const;
142  void setName(const char *name);
143  char abbreviation() const;
144  void setAbbreviation(char abbreviation);
145  const char *environmentVariable() const;
146  void setEnvironmentVariable(const char *environmentVariable);
147  const char *description() const;
148  void setDescription(const char *description);
149  const char *example() const;
150  void setExample(const char *example);
151  const std::vector<const char *> &values(std::size_t occurrence = 0) const;
152  const char *firstValue() const;
153  std::size_t requiredValueCount() const;
154  void setRequiredValueCount(std::size_t requiredValueCount);
155  const std::vector<const char *> &valueNames() const;
156  void setValueNames(std::initializer_list<const char *> valueNames);
157  void appendValueName(const char *valueName);
158  bool allRequiredValuesPresent(std::size_t occurrence = 0) const;
159  bool isPresent() const;
160  std::size_t occurrences() const;
161  std::size_t index(std::size_t occurrence) const;
162  std::size_t minOccurrences() const;
163  std::size_t maxOccurrences() const;
164  void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
165  const std::vector<Argument *> &path(std::size_t occurrence = 0) const;
166  bool isRequired() const;
167  void setRequired(bool required);
168  bool isCombinable() const;
169  void setCombinable(bool value);
170  bool isImplicit() const;
171  void setImplicit(bool value);
172  bool denotesOperation() const;
173  void setDenotesOperation(bool denotesOperation);
174  void setCallback(CallbackFunction callback);
175  void printInfo(std::ostream &os, unsigned char indentation = 0) const;
176  const ArgumentVector &subArguments() const;
177  void setSubArguments(const ArgumentInitializerList &subArguments);
178  void addSubArgument(Argument *arg);
179  bool hasSubArguments() const;
180  const ArgumentVector parents() const;
181  bool isMainArgument() const;
182  bool isParentPresent() const;
183  ValueCompletionBehavior valueCompletionBehaviour() const;
184  void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour);
185  const char *preDefinedCompletionValues() const;
186  void setPreDefinedCompletionValues(const char *preDefinedCompletionValues);
187  Argument *conflictsWithArgument() const;
188  Argument *wouldConflictWithArgument() const;
189  void reset();
190  void resetRecursively();
191 
192 private:
193  const char *m_name;
194  char m_abbreviation;
195  const char *m_environmentVar;
196  const char *m_description;
197  const char *m_example;
198  std::size_t m_minOccurrences;
199  std::size_t m_maxOccurrences;
200  bool m_combinable;
201  bool m_denotesOperation;
202  std::size_t m_requiredValueCount;
203  std::vector<const char *> m_valueNames;
204  bool m_implicit;
205  std::vector<ArgumentOccurrence> m_occurrences;
206  ArgumentVector m_subArgs;
207  CallbackFunction m_callbackFunction;
208  ArgumentVector m_parents;
209  bool m_isMainArg;
210  ValueCompletionBehavior m_valueCompletionBehavior;
211  const char *m_preDefinedCompletionValues;
212 };
213 
215 {
216  friend ArgumentParserTests;
217  friend ArgumentReader;
218 
219 public:
220  ArgumentParser();
221 
222  const ArgumentVector &mainArguments() const;
223  void setMainArguments(const ArgumentInitializerList &mainArguments);
224  void addMainArgument(Argument *argument);
225  void printHelp(std::ostream &os) const;
226  void parseArgs(int argc, const char *const *argv);
227  void readArgs(int argc, const char *const *argv);
228  void resetArgs();
229  unsigned int actualArgumentCount() const;
230  const char *executable() const;
231  UnknownArgumentBehavior unknownArgumentBehavior() const;
232  void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior);
233  Argument *defaultArgument() const;
234  void setDefaultArgument(Argument *argument);
235  void checkConstraints();
236  void invokeCallbacks();
237  bool isUncombinableMainArgPresent() const;
238 
239 private:
240  IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args, std::vector<char> abbreviations, std::vector<const char *> names);)
241  void printBashCompletion(int argc, const char * const *argv, unsigned int cursorPos, const ArgumentReader &reader);
242  void checkConstraints(const ArgumentVector &args);
243  void invokeCallbacks(const ArgumentVector &args);
244 
245  ArgumentVector m_mainArgs;
246  unsigned int m_actualArgc;
247  const char *m_executable;
248  UnknownArgumentBehavior m_unknownArgBehavior;
249  Argument *m_defaultArg;
250 };
251 
257 inline const char *Argument::name() const
258 {
259  return m_name;
260 }
261 
269 inline void Argument::setName(const char *name)
270 {
271 #ifdef DEBUG_BUILD
272  if(name && *name) {
273  assert(*name != '-');
274  for(const char *c = name; *c; ++c) {
275  assert(*c != ' ' && *c != '=' && *c != '\'' && *c != '\"' && *c != '\n' && *c != '\r');
276  }
277  }
278 #endif
279  m_name = name;
280 }
281 
287 inline char Argument::abbreviation() const
288 {
289  return m_abbreviation;
290 }
291 
299 inline void Argument::setAbbreviation(char abbreviation)
300 {
301  IF_DEBUG_BUILD(assert(abbreviation != ' ' && abbreviation != '=' && abbreviation != '-'
302  && abbreviation != '\'' && abbreviation != '"' && abbreviation != '\n' && abbreviation != '\r'));
303  m_abbreviation = abbreviation;
304 }
305 
310 inline const char *Argument::environmentVariable() const
311 {
312  return m_environmentVar;
313 }
314 
319 inline void Argument::setEnvironmentVariable(const char *environmentVariable)
320 {
321  m_environmentVar = environmentVariable;
322 }
323 
329 inline const char *Argument::description() const
330 {
331  return m_description;
332 }
333 
339 inline void Argument::setDescription(const char *description)
340 {
341  m_description = description;
342 }
343 
349 inline const char *Argument::example() const
350 {
351  return m_example;
352 }
353 
359 inline void Argument::setExample(const char *example)
360 {
361  m_example = example;
362 }
363 
370 inline const std::vector<const char *> &Argument::values(std::size_t occurrence) const
371 {
372  return m_occurrences[occurrence].values;
373 }
374 
388 inline std::size_t Argument::requiredValueCount() const
389 {
390  return m_requiredValueCount;
391 }
392 
404 inline void Argument::setRequiredValueCount(std::size_t requiredValueCount)
405 {
406  m_requiredValueCount = requiredValueCount;
407 }
408 
417 inline const std::vector<const char *> &Argument::valueNames() const
418 {
419  return m_valueNames;
420 }
421 
435 inline void Argument::setValueNames(std::initializer_list<const char *> valueNames)
436 {
437  m_valueNames.assign(valueNames);
438 }
439 
446 inline void Argument::appendValueName(const char *valueName)
447 {
448  m_valueNames.emplace_back(valueName);
449 }
450 
454 inline bool Argument::allRequiredValuesPresent(std::size_t occurrence) const
455 {
456  return m_requiredValueCount == static_cast<std::size_t>(-1)
457  || (m_occurrences[occurrence].values.size() >= static_cast<std::size_t>(m_requiredValueCount));
458 }
459 
464 inline bool Argument::isImplicit() const
465 {
466  return m_implicit;
467 }
468 
473 inline void Argument::setImplicit(bool implicit)
474 {
475  m_implicit = implicit;
476 }
477 
481 inline bool Argument::isPresent() const
482 {
483  return !m_occurrences.empty();
484 }
485 
489 inline std::size_t Argument::occurrences() const
490 {
491  return m_occurrences.size();
492 }
493 
497 inline std::size_t Argument::index(std::size_t occurrence) const
498 {
499  return m_occurrences[occurrence].index;
500 }
501 
507 inline std::size_t Argument::minOccurrences() const
508 {
509  return m_minOccurrences;
510 }
511 
517 inline std::size_t Argument::maxOccurrences() const
518 {
519  return m_maxOccurrences;
520 }
521 
527 inline void Argument::setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
528 {
529  m_minOccurrences = minOccurrences;
530  m_maxOccurrences = maxOccurrences;
531 }
532 
536 inline const std::vector<Argument *> &Argument::path(std::size_t occurrence) const
537 {
538  return m_occurrences[occurrence].path;
539 }
540 
550 inline bool Argument::isRequired() const
551 {
552  return m_minOccurrences;
553 }
554 
562 inline void Argument::setRequired(bool required)
563 {
564  if(required) {
565  if(!m_minOccurrences) {
566  m_minOccurrences = 1;
567  }
568  } else {
569  m_minOccurrences = 0;
570  }
571 }
572 
581 inline bool Argument::isCombinable() const
582 {
583  return m_combinable;
584 }
585 
594 inline void Argument::setCombinable(bool value)
595 {
596  m_combinable = value;
597 }
598 
609 inline bool Argument::denotesOperation() const
610 {
611  return m_denotesOperation;
612 }
613 
618 inline void Argument::setDenotesOperation(bool denotesOperation)
619 {
620  m_denotesOperation = denotesOperation;
621 }
622 
629 {
630  m_callbackFunction = callback;
631 }
632 
639 inline const ArgumentVector &Argument::subArguments() const
640 {
641  return m_subArgs;
642 }
643 
650 inline bool Argument::hasSubArguments() const
651 {
652  return !m_subArgs.empty();
653 }
654 
665 inline const ArgumentVector Argument::parents() const
666 {
667  return m_parents;
668 }
669 
676 inline bool Argument::isMainArgument() const
677 {
678  return m_isMainArg;
679 }
680 
685 {
686  return m_valueCompletionBehavior;
687 }
688 
693 {
694  m_valueCompletionBehavior = completionValues;
695 }
696 
700 inline const char *Argument::preDefinedCompletionValues() const
701 {
702  return m_preDefinedCompletionValues;
703 }
704 
708 inline void Argument::setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
709 {
710  m_preDefinedCompletionValues = preDefinedCompletionValues;
711 }
712 
716 inline void Argument::reset()
717 {
718  m_occurrences.clear();
719 }
720 
725 inline const ArgumentVector &ArgumentParser::mainArguments() const
726 {
727  return m_mainArgs;
728 }
729 
733 inline unsigned int ArgumentParser::actualArgumentCount() const
734 {
735  return m_actualArgc;
736 }
737 
741 inline const char *ArgumentParser::executable() const
742 {
743  return m_executable;
744 }
745 
752 {
753  return m_unknownArgBehavior;
754 }
755 
762 {
763  m_unknownArgBehavior = behavior;
764 }
765 
771 {
772  return m_defaultArg;
773 }
774 
780 {
781  m_defaultArg = argument;
782 }
783 
790 {
791  checkConstraints(m_mainArgs);
792 }
793 
799 {
800  invokeCallbacks(m_mainArgs);
801 }
802 
804 {
805 public:
806  HelpArgument(ArgumentParser &parser);
807 };
808 
810 {
811 public:
812  OperationArgument(const char *name, char abbreviation = '\0', const char *description = nullptr, const char *example = nullptr);
813 };
814 
815 inline OperationArgument::OperationArgument(const char *name, char abbreviation, const char *description, const char *example) :
816  Argument(name, abbreviation, description, example)
817 {
818  setDenotesOperation(true);
819 }
820 
822 {
823 public:
824  ConfigValueArgument(const char *name, char abbreviation = '\0', const char *description = nullptr, std::initializer_list<const char *> valueNames = std::initializer_list<const char *>());
825 };
826 
830 inline ConfigValueArgument::ConfigValueArgument(const char *name, char abbreviation, const char *description, std::initializer_list<const char *> valueNames) :
831  Argument(name, abbreviation, description)
832 {
833  setCombinable(true);
834  setRequiredValueCount(valueNames.size());
835  setValueNames(valueNames);
836 }
837 
838 }
839 
840 #endif // APPLICATION_UTILITIES_ARGUMENTPARSER_H
bool isMainArgument() const
Returns an indication whether the argument is used as main argument.
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:35
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.
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.
std::function< bool(Argument *)> ArgumentPredicate
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.
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.
std::function< void(const ArgumentOccurrence &)> CallbackFunction
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:45
std::vector< const char * > values
The parameter values which have been specified after the occurrence of the argument.