First commit

experiment/meta_header
Martchus 7 years ago
commit 24ba96a17f
  1. 581
      application/argumentparser.cpp
  2. 581
      application/argumentparser.h
  3. 44
      application/failure.cpp
  4. 26
      application/failure.h
  5. 11
      application/fakeqtconfigarguments.cpp
  6. 44
      application/fakeqtconfigarguments.h
  7. 77
      application/global.h
  8. 2310
      c++utilities.doxygen
  9. 66
      c++utilities.pro
  10. 275
      chrono/datetime.cpp
  11. 404
      chrono/datetime.h
  12. 34
      chrono/period.cpp
  13. 49
      chrono/period.h
  14. 116
      chrono/timespan.cpp
  15. 305
      chrono/timespan.h
  16. 46
      conversion/binaryconversion.cpp
  17. 150
      conversion/binaryconversion.h
  18. 307
      conversion/binaryconversionprivate.h
  19. 31
      conversion/conversionexception.cpp
  20. 21
      conversion/conversionexception.h
  21. 183
      conversion/stringconversion.cpp
  22. 204
      conversion/stringconversion.h
  23. 74
      conversion/types.h
  24. 59
      conversion/widen.h
  25. 118
      doc/html/annotated.html
  26. 133
      doc/html/argumentparser_8cpp.html
  27. 9
      doc/html/argumentparser_8cpp__incl.map
  28. 1
      doc/html/argumentparser_8cpp__incl.md5
  29. 382
      doc/html/argumentparser_8cpp__incl.svg
  30. 294
      doc/html/argumentparser_8cpp__incl_org.svg
  31. 502
      doc/html/argumentparser_8cpp_source.html
  32. 163
      doc/html/argumentparser_8h.html
  33. 3
      doc/html/argumentparser_8h__dep__incl.map
  34. 1
      doc/html/argumentparser_8h__dep__incl.md5
  35. 31
      doc/html/argumentparser_8h__dep__incl.svg
  36. 3
      doc/html/argumentparser_8h__incl.map
  37. 1
      doc/html/argumentparser_8h__incl.md5
  38. 91
      doc/html/argumentparser_8h__incl.svg
  39. 415
      doc/html/argumentparser_8h_source.html
  40. BIN
      doc/html/bc_s.png
  41. BIN
      doc/html/bdwn.png
  42. 182
      doc/html/binaryconversion_8cpp.html
  43. 6
      doc/html/binaryconversion_8cpp__incl.map
  44. 1
      doc/html/binaryconversion_8cpp__incl.md5
  45. 115
      doc/html/binaryconversion_8cpp__incl.svg
  46. 486
      doc/html/binaryconversion_8cpp_source.html
  47. 196
      doc/html/binaryconversion_8h.html
  48. 14
      doc/html/binaryconversion_8h__dep__incl.map
  49. 1
      doc/html/binaryconversion_8h__dep__incl.md5
  50. 267
      doc/html/binaryconversion_8h__dep__incl.svg
  51. 179
      doc/html/binaryconversion_8h__dep__incl_org.svg
  52. 4
      doc/html/binaryconversion_8h__incl.map
  53. 1
      doc/html/binaryconversion_8h__incl.md5
  54. 54
      doc/html/binaryconversion_8h__incl.svg
  55. 192
      doc/html/binaryconversion_8h_source.html
  56. 122
      doc/html/binaryreader_8cpp.html
  57. 7
      doc/html/binaryreader_8cpp__incl.map
  58. 1
      doc/html/binaryreader_8cpp__incl.md5
  59. 261
      doc/html/binaryreader_8cpp__incl.svg
  60. 173
      doc/html/binaryreader_8cpp__incl_org.svg
  61. 553
      doc/html/binaryreader_8cpp_source.html
  62. 137
      doc/html/binaryreader_8h.html
  63. 5
      doc/html/binaryreader_8h__dep__incl.map
  64. 1
      doc/html/binaryreader_8h__dep__incl.md5
  65. 57
      doc/html/binaryreader_8h__dep__incl.svg
  66. 5
      doc/html/binaryreader_8h__incl.map
  67. 1
      doc/html/binaryreader_8h__incl.md5
  68. 107
      doc/html/binaryreader_8h__incl.svg
  69. 183
      doc/html/binaryreader_8h_source.html
  70. 113
      doc/html/binarywriter_8cpp.html
  71. 386
      doc/html/binarywriter_8cpp_source.html
  72. 5
      doc/html/binarywriter_8h__incl.map
  73. 32
      doc/html/classApplicationUtilities_1_1Failure__coll__graph.svg
  74. 45
      doc/html/classConversionUtilities_1_1ConversionException__coll__graph.svg
  75. 120
      doc/html/classes.html
  76. 223
      doc/html/conversionexception_8h__dep__incl.svg
  77. 1
      doc/html/datetime_8cpp__incl.md5
  78. 327
      doc/html/datetime_8cpp__incl.svg
  79. 239
      doc/html/datetime_8cpp__incl_org.svg
  80. 169
      doc/html/datetime_8h.html
  81. 5
      doc/html/datetime_8h__dep__incl.map
  82. 1
      doc/html/datetime_8h__dep__incl.md5
  83. 57
      doc/html/datetime_8h__dep__incl.svg
  84. 5
      doc/html/datetime_8h__incl.map
  85. 1
      doc/html/datetime_8h__incl.md5
  86. 87
      doc/html/datetime_8h__incl.svg
  87. 439
      doc/html/datetime_8h_source.html
  88. 91
      doc/html/dir_000000_000002.html
  89. 91
      doc/html/dir_000001_000000.html
  90. 91
      doc/html/dir_000001_000002.html
  91. 91
      doc/html/dir_000002_000000.html
  92. 91
      doc/html/dir_000003_000000.html
  93. 108
      doc/html/dir_a52f4d3d586a58b02f3a4ddf0a992157.html
  94. 1
      doc/html/dir_d75c23162a2652451dce46d2e7e8aead_dep.md5
  95. 51
      doc/html/failure_8h__incl.svg
  96. 159
      doc/html/functions_func_i.html
  97. 149
      doc/html/functions_func_m.html
  98. 137
      doc/html/functions_func_n.html
  99. 179
      doc/html/functions_func_o.html
  100. 152
      doc/html/functions_func_p.html
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,581 @@
#include "argumentparser.h"
#include "failure.h"
#include "../conversion/stringconversion.h"
#include "../misc/random.h"
#include <algorithm>
#include <vector>
#include <iostream>
#include <sstream>
#include <stdexcept>
using namespace std;
using namespace std::placeholders;
/*!
\namespace ApplicationUtilities
\brief Contains currently only ArgumentParser and related classes.
*/
namespace ApplicationUtilities {
/*!
* \class ApplicationUtilities::Argument
* \brief The Argument class is a wrapper for command line argument information.
*
* Instaces of the Argument class are used as definition when parsing command line
* arguments. Arguments can be assigned to an ArgumentParser using
* ArgumentParser::setMainArguments() and to another Argument instance using
* Argument::setSecondaryArguments().
*/
/*!
* Constructs an Argument with the given \a name, \a abbreviation and \a description.
*
* The \a name and the abbreviation mustn't contain any whitespaces.
* The \a name mustn't be empty. The \a abbreviation and the \a description might be empty.
*/
Argument::Argument(const std::string &name, const std::string abbreviation, const std::string &description) :
m_required(false),
m_combinable(false),
m_implicit(false),
m_requiredValueCount(0),
m_default(false),
m_present(false),
m_isMainArg(false)
{
setName(name);
setAbbreviation(abbreviation);
setDescription(description);
}
/*!
* Constructs an Argument with the given \a name, \a abbreviation and \a description.
* The \a name and the abbreviation mustn't contain any whitespaces.
* The \a name mustn't be empty. The \a abbreviation and the \a description might be empty.
*/
Argument::Argument(const char *name, const char *abbreviation, const char *description) :
m_required(false),
m_combinable(false),
m_implicit(false),
m_requiredValueCount(0),
m_default(false),
m_present(false),
m_isMainArg(false)
{
setName(name);
setAbbreviation(abbreviation);
setDescription(description);
}
/*!
* Destroys the Argument.
*/
Argument::~Argument()
{}
///*!
// * \brief Checks whether the argument is ambigious.
// * \returns Returns zero if the argument is not ambigious. Returns 1 if the name
// * is ambiguous and 2 if the abbreviation is ambiguous.
// */
//unsigned char Argument::isAmbiguous(const ArgumentParser &parser) const
//{
// function<unsigned char (const ArgumentVector &args, const Argument *toCheck)> check;
// check = [&check] (const ArgumentVector &args, const Argument *toCheck) -> unsigned char {
// for(const auto *arg : args) {
// if(arg != toCheck) {
// if(!toCheck->name().empty() && arg->name() == toCheck->name()) {
// return 1;
// } else if(!toCheck->abbreviation().empty() && arg->abbreviation() == toCheck->abbreviation()) {
// return 2;
// }
// }
// if(auto res = check(arg->parents(), toCheck)) {
// return res;
// }
// }
// return 0;
// };
// if(auto res = check(parser.mainArguments(), this)) {
// return res;
// }
// return check(parents(), this);
//}
/*!
* Appends the name, the abbreviation and the description of the Argument
* to the give ostream.
*/
void Argument::printInfo(ostream &os, unsigned char indentionLevel) const
{
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
if(!name().empty()) {
os << "--" << name();
}
if(!name().empty() && !abbreviation().empty()) {
os << ", ";
}
if(!abbreviation().empty()) {
os << "-" << abbreviation();
}
if(requiredValueCount() > 0) {
int valueNamesPrint = 0;
for(auto i = valueNames().cbegin(), end = valueNames().cend(); i != end && valueNamesPrint < requiredValueCount(); ++i) {
os << " [" << *i << "]";
++valueNamesPrint;
}
for(; valueNamesPrint < requiredValueCount(); ++valueNamesPrint) {
os << " [value " << (valueNamesPrint + 1) << "]";
}
} else if(requiredValueCount() < 0) {
for(auto i = valueNames().cbegin(), end = valueNames().cend(); i != end; ++i) {
os << " [" << *i << "]";
}
os << " ...";
}
++indentionLevel;
if(!description().empty()) {
os << endl;
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
os << description();
}
if(isRequired()) {
os << endl;
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
os << "This argument is required.";
}
os << endl;
for(const Argument *arg : secondaryArguments()) {
arg->printInfo(os, indentionLevel + 1);
}
}
/*!
* This function return the first present and uncombinable argument of the given list of arguments.
* The Argument \a except will be ignored.
*/
Argument *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except)
{
for(Argument *arg : args) {
if(arg != except && arg->isPresent() && !arg->isCombinable()) {
return arg;
}
}
return nullptr;
}
/*!
* Sets the secondary arguments for this arguments. The given arguments will be considered as
* secondary arguments of this argument by the ArgumentParser. This means that the parser
* will complain if these arguments are given, but not their parent. If secondary arguments are
* labeled as mandatory their parent is also mandatory.
*
* The Argument does not take ownership. Do not destroy the given arguments as long as they are
* used as secondary arguments.
*
* \sa secondaryArguments()
* \sa hasSecondaryArguments()
*/
void Argument::setSecondaryArguments(const ArgumentInitializerList &secondaryArguments)
{
// remove this argument from the parents list of the previous secondary arguments
for(Argument *arg : m_secondaryArgs) {
arg->m_parents.erase(remove(arg->m_parents.begin(), arg->m_parents.end(), this), arg->m_parents.end());
}
// assign secondary arguments
m_secondaryArgs.assign(secondaryArguments);
// add this argument to the parents list of the assigned secondary arguments
// and set the parser
for(Argument *arg : m_secondaryArgs) {
if(find(arg->m_parents.cbegin(), arg->m_parents.cend(), this) == arg->m_parents.cend()) {
arg->m_parents.push_back(this);
}
}
}
/*!
* Returns the names of the parents in the form "parent1", "parent2, "parent3", ...
* Returns an empty string if this Argument has no parents.
* \sa parents()
*/
string Argument::parentNames() const
{
string res;
if(m_parents.size()) {
vector<string> names;
names.reserve(m_parents.size());
for(const Argument *parent : m_parents) {
names.push_back(parent->name());
}
res.assign(ConversionUtilities::joinStrings(names, ", "));
}
return res;
}
/*!
* Returns true if at least one of the parents is present.
* Returns false if this argument has no parents or none of its parents is present.
*/
bool Argument::isParentPresent() const
{
for(Argument *parent : m_parents) {
if(parent->isPresent()) {
return true;
}
}
return false;
}
/*!
* Checks if this arguments conflicts with other arguments. If the argument is in conflict
* with an other argument this argument will be returned. Otherwise nullptr will be returned.
*/
Argument *Argument::conflictsWithArgument() const
{
if(!isCombinable() && isPresent()) {
for(Argument *parent : m_parents) {
for(Argument *sibling : parent->secondaryArguments()) {
if(sibling != this && sibling->isPresent() && !sibling->isCombinable()) {
return sibling;
}
}
}
}
return nullptr;
}
/*!
* \class ApplicationUtilities::ArgumentParser
* \brief The ArgumentParser class provides a means for handling command line arguments.
*
* To setup the parser create instances of ApplicationUtilities::Argument to define a
* set of known arguments and assign these to the parser using setMainArguments().
*
* To invoke parsing call parseArgs(). The parser will verify the previously
* assigned definitions (and might throw std::invalid_argument) and then parse the
* given command line arguments according the definitions (and might throw
* ApplicationUtilities::Failure).
*/
/*!
* Constructs a new ArgumentParser.
*/
ArgumentParser::ArgumentParser() :
m_actualArgc(0),
m_ignoreUnknownArgs(false)
{}
/*!
* Sets the main arguments for the parser. The parser will use these argument definitions
* to when parsing the command line arguments and when printing help information.
*
* The parser does not take ownership. Do not destroy the arguments as long as they are used as
* main arguments.
*/
void ArgumentParser::setMainArguments(const ArgumentInitializerList &mainArguments)
{
for(Argument *arg : mainArguments) {
arg->m_isMainArg = true;
}
m_mainArgs.assign(mainArguments);
}
/*!
* Prints help information for all main arguments which have been set using setMainArguments().
*/
void ArgumentParser::printHelp(ostream &os) const
{
if(!m_mainArgs.size()) {
return;
}
os << "Available arguments:\n";
for(const Argument *arg : m_mainArgs) {
arg->printInfo(os);
}
}
/*!
* Returns the first argument definition which matches the predicate.
* The search includes all assigned main argument definitions and their sub arguments.
*/
Argument *ArgumentParser::findArg(const ArgumentPredicate &predicate) const
{
return findArg(m_mainArgs, predicate);
}
/*!
* Returns the first argument definition which matches the predicate.
* The search includes all provided \a arguments and their sub arguments.
*/
Argument *ArgumentParser::findArg(const ArgumentVector &arguments, const ArgumentPredicate &predicate)
{
for(Argument *arg : arguments) {
if(predicate(arg)) {
return arg; // argument matches
} else if(Argument *subarg = findArg(arg->secondaryArguments(), predicate)) {
return subarg; // a secondary argument matches
}
}
return nullptr; // no argument matches
}
/*!
* This method is used to verify the setup of the command line parser before parsing.
*
* This function will throw std::invalid_argument when a mismatch is detected:
* - An argument is used as main argument and as sub argument at the same time.
* - An argument abbreviation is used more then once.
* - An argument name is used more then once.
* If none of these conditions are met, this method will do nothing.
*
* \remarks Usually you don't need to call this function manually because it is called by
* parse() automatically befor the parsing is performed.
*/
void ArgumentParser::verifySetup() const
{
vector<Argument *> verifiedArgs;
vector<string> abbreviations;
vector<string> names;
function<void (const ArgumentVector &args)> checkArguments;
checkArguments = [&verifiedArgs, &abbreviations, &names, &checkArguments, this] (const ArgumentVector &args) {
for(Argument *arg : args) {
if(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) != verifiedArgs.cend())
continue; // do not verify the same argument twice
if(arg->isMainArgument() && arg->parents().size())
throw invalid_argument("Argument \"" + arg->name() + "\" can not be used as main argument and sub argument at the same time.");
if(!arg->abbreviation().empty() && find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) != abbreviations.cend())
throw invalid_argument("Abbreviation \"" + arg->abbreviation() + "\" has been used more then once.");
if(find(names.cbegin(), names.cend(), arg->name()) != names.cend())
throw invalid_argument("Name \"" + arg->name() + "\" has been used more then once.");
if(arg->isDefault() && arg->requiredValueCount() > 0 && arg->defaultValues().size() < static_cast<size_t>(arg->requiredValueCount()))
throw invalid_argument("Default argument \"" + arg->name() + "\" doesn't provide the required number of default values.");
abbreviations.push_back(arg->abbreviation());
names.push_back(arg->name());
verifiedArgs.push_back(arg);
checkArguments(arg->secondaryArguments());
}
};
checkArguments(m_mainArgs);
}
/*!
* This method invokes verifySetup() before parsing. See its do documentation for more
* information about execptions that might be thrown to indicate an invalid setup of the parser.
*
* If the parser is setup properly this method will parse the given command line arguments using
* the previsously set argument definitions.
* If one of the previsously defined arguments has been found, its present flag will be set to true
* and the parser reads all values tied to this argument.
* If an argument has been found which does not match any of the previous definitions it will be
* considered as unknown.
* If the given command line arguments are not valid according the defined arguments an
* Failure will be thrown.
*/
void ArgumentParser::parseArgs(int argc, char *argv[])
{
// initiate parser
verifySetup();
m_actualArgc = 0; // reset actual agument count
unsigned int actualArgc = 0;
int valuesToRead = 0;
// read current directory
if(argc >= 1) {
m_currentDirectory = string(*argv);
} else {
m_currentDirectory.clear();
}
// parse given arguments
if(argc >= 2) {
Argument *currentArg = nullptr;
// iterate through given arguments
for(char **i = argv + 1, ** end = argv + argc; i != end; ++i) {
string givenArg(*i); // convert argument to string
if(!givenArg.empty()) { // skip empty entries
if(valuesToRead <= 0 && givenArg.size() > 1 && givenArg.front() == '-') {
// we have no values left to read and the given arguments starts with '-'
// -> the next "value" is a main argument or a sub argument
ArgumentPredicate pred;
string givenId;
size_t equationPos = givenArg.find('=');
if(givenArg.size() > 2 && givenArg[1] == '-') {
// the argument starts with '--'
// -> the full argument name has been provided
givenId = givenArg.substr(2, equationPos - 2);
pred = [&givenId, equationPos] (Argument *arg) {
return arg->name() == givenId;
};
} else {
// the argument starts with a single '-'
// -> the abbreviation has been provided
givenId = givenArg.substr(1, equationPos - 1);
pred = [&givenId, equationPos] (Argument *arg) {
return arg->abbreviation() == givenId;
};
}
// find the corresponding instande of the Argument class
currentArg = findArg(pred);
if(currentArg) {
// the corresponding instance of Argument class has been found
if(currentArg->m_present) {
// the argument has been provided more then once
throw Failure("The argument \"" + currentArg->name() + "\" has been given more then one time.");
} else {
// set present flag of argument
currentArg->m_present = true;
++actualArgc; // we actually found an argument
// now we might need to read values tied to that argument
valuesToRead = currentArg->requiredValueCount();
if(equationPos != string::npos) {
// a value has been specified using the --argument=value syntax
string value = givenArg.substr(equationPos + 1);
if(valuesToRead != 0) {
currentArg->m_values.push_back(value);
if(valuesToRead > 0) {
--valuesToRead;
}
} else {
throw Failure("Invalid extra information \"" + value + "\" (specified using \"--argument=value\" syntax) for the argument \"" + currentArg->name() + "\" given.");
}
}
}
} else {
// the given argument seems to be unknown
if(valuesToRead < 0) {
// we have a variable number of values to expect -> treat "unknown argument" as value
goto readValue;
} else {
// we have no more values to expect so we need to complain about the unknown argument
goto invalidArg;
}
}
} else {
readValue:
if(!currentArg) {
// we have not parsed an argument before -> check if there's an implicit argument definition
for(Argument *arg : m_mainArgs) {
if(!arg->isPresent() && arg->isImplicit()) {
// set present flag of argument
arg->m_present = true;
++actualArgc; // we actually found an argument
// now we might need to read values tied to that argument
valuesToRead = arg->requiredValueCount();
currentArg = arg;
break;
}
}
}
if(currentArg) {
// check if the given value is tied to the most recently parsed argument
if(valuesToRead == 0) {
throw Failure("Invalid extra information \"" + givenArg + "\" for the argument \"" + currentArg->name() + "\" given.");
} else if(valuesToRead < 0) {
currentArg->m_values.push_back(givenArg);
} else {
currentArg->m_values.push_back(givenArg);
--valuesToRead; // one value less to be read
}
} else {
// there is no implicit argument definition -> the "value" has to be an argument
// but does not start with '-' or '--'
invalidArg:
string msg("The given argument \"" + givenArg + "\" is unknown.");
if(m_ignoreUnknownArgs) {
cout << msg << " It will be ignored." << endl;
} else {
throw Failure(msg);
}
}
}
}
}
}
// function for iterating through all arguments
function<void(Argument *, const ArgumentVector &, const function<void (Argument *, Argument *)> &)> foreachArg;
foreachArg = [&foreachArg] (Argument *parent, const ArgumentVector &args, const function<void (Argument *, Argument *)> &proc) {
for(Argument *arg : args) {
proc(parent, arg);
foreachArg(arg, arg->secondaryArguments(), proc);
}
};
// iterate actually through all arguments using previously defined function to check gathered arguments
foreachArg(nullptr, m_mainArgs, [this] (Argument *parent, Argument *arg) {
if(arg->isPresent()) {
if(!arg->isMainArgument() && arg->parents().size() && !arg->isParentPresent()) {
if(arg->parents().size() > 1) {
throw Failure("The argument \"" + arg->name() + "\" needs to be used together with one the following arguments: " + arg->parentNames());
} else {
throw Failure("The argument \"" + arg->name() + "\" needs to be used together with the argument \"" + arg->parents().front()->name() + "\".");
}
}
Argument *conflictingArgument = nullptr;
if(arg->isMainArgument()) {
if(!arg->isCombinable() && arg->isPresent()) {
conflictingArgument = firstPresentUncombinableArg(m_mainArgs, arg);
}
} else {
conflictingArgument = arg->conflictsWithArgument();
}
if(conflictingArgument) {
throw Failure("The argument \"" + conflictingArgument->name() + "\" can not be combined with \"" + arg->name() + "\".");
}
if(!arg->allRequiredValuesPresent()) {
stringstream ss(stringstream::in | stringstream::out);
ss << "Not all required information for the given argument \"" << arg->name() << "\" provided. You have to give the following information:";
int valueNamesPrint = 0;
for(const auto &name : arg->m_valueNames) {
ss << "\n" << name;
++valueNamesPrint;
}
while(valueNamesPrint < arg->m_requiredValueCount) {
ss << "\nvalue " << (++valueNamesPrint);
}
throw Failure(ss.str());
}
} else { // argument not present
// the argument might be flagged as present if its a default argument
if(arg->isDefault() && (arg->isMainArgument() || (parent && parent->isPresent()))) {
arg->m_present = true;
if(firstPresentUncombinableArg(arg->isMainArgument() ? m_mainArgs : parent->secondaryArguments(), arg)) {
arg->m_present = false;
}
}
// throw an error if mandatory argument is not present
if(!arg->isPresent() && (arg->isRequired() && (arg->isMainArgument() || (parent && parent->isPresent())))) {
throw Failure("The argument \"" + arg->name() + "\" is required but not given.");
}
}
});
// set actual argument count
m_actualArgc = actualArgc;
// interate through all arguments again to invoke callback functions
foreachArg(nullptr, m_mainArgs, [] (Argument *parent, Argument *arg) {
if(arg->m_callbackFunction) {
if(arg->isMainArgument() || (parent && parent->isPresent())) {
// only invoke if its a main argument or the parent is present
if(arg->isPresent()) {
if(arg->isDefault() && !arg->values().size()) {
arg->m_callbackFunction(arg->defaultValues());
} else {
arg->m_callbackFunction(arg->values());
}
}
}
}
});
}
/*!
* \brief The HelpArgument class prints help information for an argument parser
* when present (--help, -h).
*/
/*!
* \brief Constructs a new help argument for the specified parser.
*/
HelpArgument::HelpArgument(ArgumentParser &parser) :
Argument("help", "h", "shows this information")
{
setCallback([&parser] (const StringVector &) {parser.printHelp(cout);});
}
}

@ -0,0 +1,581 @@
#ifndef ARGUMENTPARSER_H
#define ARGUMENTPARSER_H
#include "global.h"
#include <string>
#include <vector>
#include <list>
#include <initializer_list>
#include <functional>
#include <stdexcept>
namespace ApplicationUtilities {
class Argument;
class ArgumentParser;
typedef std::initializer_list<Argument *> ArgumentInitializerList;
typedef std::vector<Argument *> ArgumentVector;
typedef std::vector<std::string> StringVector;
typedef std::list<std::string> StringList;
typedef std::function<bool (Argument *)> ArgumentPredicate;
Argument LIB_EXPORT *firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except);
class LIB_EXPORT Argument
{
friend class ArgumentParser;
public:
typedef std::function <void (const StringVector &)> CallbackFunction;
Argument(const std::string &name, const std::string abbreviation = std::string(), const std::string &description = std::string());
Argument(const char *name, const char *abbreviation = nullptr, const char *description = nullptr);
~Argument();
const std::string &name() const;
void setName(const std::string &name);
const std::string &abbreviation() const;
void setAbbreviation(const std::string &abbreviation);
//unsigned char isAmbiguous(const ArgumentParser &parser) const;
const std::string &description() const;
void setDescription(const std::string &description);
const StringVector &values() const;
const std::string &value(StringVector::size_type index) const;
StringVector::size_type valueCount() const;
int requiredValueCount() const;
void setRequiredValueCount(int requiredValueCount);
const StringList &valueNames() const;
void setValueNames(std::initializer_list<std::string> valueNames);
void appendValueName(const char *valueName);
void appendValueName(const std::string &valueName);
bool allRequiredValuesPresent() const;
bool isDefault() const;
void setDefault(bool value);
const StringVector &defaultValues() const;
void setDefaultValues(const StringVector &defaultValues);
bool isPresent() const;
bool isRequired() const;
void setRequired(bool value);
bool isCombinable() const;
void setCombinable(bool value);
bool isImplicit() const;
void setImplicit(bool value);
void setCallback(CallbackFunction callback);
void printInfo(std::ostream &os, unsigned char indentionLevel = 0) const;
const ArgumentVector &secondaryArguments() const;
void setSecondaryArguments(const ArgumentInitializerList &secondaryArguments);
bool hasSecondaryArguments() const;
const ArgumentVector parents() const;
bool isMainArgument() const;
std::string parentNames() const;
bool isParentPresent() const;
Argument *conflictsWithArgument() const;
private:
std::string m_name;
std::string m_abbreviation;
std::string m_description;
bool m_required;
bool m_combinable;
bool m_implicit;
int m_requiredValueCount;
StringList m_valueNames;
bool m_default;
StringVector m_defaultValues;
bool m_present;
StringVector m_values;
ArgumentVector m_secondaryArgs;
CallbackFunction m_callbackFunction;
ArgumentVector m_parents;
bool m_isMainArg;
};
/*!
* \brief Returns the name of the argument.
*
* The parser compares the name with the characters following a "--" prefix to
* identify arguments.
*/
inline const std::string &Argument::name() const
{
return m_name;
}
/*!
* \brief Sets the name of the argument.
*
* The name mustn't be empty or contain white spaces or equation chars.
*
* The parser compares the name with the characters following a "--" prefix to
* identify arguments.
*/
inline void Argument::setName(const std::string &name)
{
if(name.empty() || name.find(' ') != std::string::npos || name.find('=') != std::string::npos) {
throw std::invalid_argument("name mustn't be empty or contain white spaces or equation chars");
}
m_name = name;
}
/*!
* \brief Returns the abbreviation of the argument.
*
* The parser compares the abbreviation with the characters following a "-" prefix to
* identify arguments.
*/
inline const std::string &Argument::abbreviation() const
{
return m_abbreviation;
}
/*!
* \brief Sets the abbreviation of the argument.
*
* The abbreviation might be empty but mustn't contain any white spaces or
* equation chars when provided.
*
* The parser compares the abbreviation with the characters following a "-" prefix to
* identify arguments.
*/
inline void Argument::setAbbreviation(const std::string &abbreviation)
{
if(!abbreviation.empty() && (abbreviation.find(' ') != std::string::npos || abbreviation.find('=') != std::string::npos)) {
throw std::invalid_argument("abbreviation mustn't contain white spaces or equation chars");
}
m_abbreviation = abbreviation;
}
/*!
* \brief Returns the description of the argument.
*
* The parser uses the description when printing help information.
*/
inline const std::string &Argument::description() const
{
return m_description;
}
/*!
* \brief Sets the description of the argument.
*
* The parser uses the description when printing help information.
*/
inline void Argument::setDescription(const std::string &description)
{
m_description = description;
}
/*!
* \brief Returns the additional values for the argument.
*
* These values set by the parser when the command line arguments.
*/
inline const StringVector &Argument::values() const
{
return m_values;
}
/*!
* \brief Returns the value with the give \a index.
*
* These values set by the parser when the command line arguments.
*/
inline const std::string &Argument::value(StringVector::size_type index) const
{
return m_values[index];
}
/*!
* Returns the number of values which could be found when parsing
* the command line arguments.
*/
inline StringVector::size_type Argument::valueCount() const
{
return m_values.size();
}
/*!
* \brief Returns the number of values which are required to be given
* for this argument.
*
* The parser will expect that many values when parsing command line arguments.
* A negative value indicates a variable number of arguments to be expected.
*
* The default value is 0.
*
* \sa setRequiredValueCount()
* \sa valueNames()
* \sa setValueNames()
*/
inline int Argument::requiredValueCount() const
{
return m_requiredValueCount;
}
/*!
* \brief Sets the number of values which are required to be given
* for this argument.
*
* The parser will expect that many values when parsing command line arguments.
* A negative value indicates a variable number of arguments to be expected.
*
* \sa requiredValueCount()
* \sa valueNames()
* \sa setValueNames()
*/
inline void Argument::setRequiredValueCount(int requiredValueCount)
{
m_requiredValueCount = requiredValueCount;
}
/*!
* \brief Returns the names of the requried values.
*
* These names will be shown when printing information about the argument.
*
* \sa setValueNames()
* \sa appendValueNames()
*/
inline const StringList &Argument::valueNames() const
{
return m_valueNames;
}
/*!
* \brief Sets the names of the requried values. These names will be used
* when printing information about the argument.
*
* If the number of value names is higher then the number of requried values
* the additional value names will be ignored.
* If the number of value names is lesser then the number of requried values
* generic values will be used for the missing names.
*
* \sa appendValueName()
* \sa valueNames()
* \sa requiredValueCount()
*/
inline void Argument::setValueNames(std::initializer_list<std::string> valueNames)
{
m_valueNames = std::list<std::string>(valueNames);
}
/*!
* \brief Appends a value name. The value names names will be shown
* when printing information about the argument.
*/
inline void Argument::appendValueName(const char *valueName)
{
m_valueNames.emplace_back(valueName);
}
/*!
* \brief Appends a value name. The value names names will be shown
* when printing information about the argument.
*
* \sa setValueNames()
* \sa valueNames()
*/
inline void Argument::appendValueName(const std::string &valueName)
{
m_valueNames.push_back(valueName);
}
/*!
* \brief Returns an indication whether all required values are present.
*/
inline bool Argument::allRequiredValuesPresent() const
{
if(m_requiredValueCount > 0) {
return (m_values.size() >= static_cast<size_t>(m_requiredValueCount))
|| (m_default && m_defaultValues.size() >= static_cast<size_t>(m_requiredValueCount));
} else {
return true;
}
}
/*!
* \brief Returns an indication whether the argument is a default argument.
*
* A default argument will be flagged as present when parsing arguments event
* if it is not actually present if there is no uncombinable argument present
* and it is a main argument or the parent is present.
*
* The callback function will be invoked in this case as the argument where
* actually present.
*
* The default value (for this property) is false.
*
* \sa setDefault()
*/
inline bool Argument::isDefault() const
{
return m_default;
}
/*!
* \brief Sets whether the argument is a default argument.
* \sa isDefault()
*/
inline void Argument::setDefault(bool value)
{
m_default = value;
}
/*!
* \brief Returns the default values.
* \sa isDefault()
* \sa setDefault()
* \sa setDefaultValues()
*/
inline const StringVector &Argument::defaultValues() const
{
return m_defaultValues;
}
/*!
* \brief Sets the default values.
*
* There must be as many default values as required values
* if the argument is a default argument.
*
* \sa isDefault()
* \sa setDefault()
* \sa defaultValues()
*/
inline void Argument::setDefaultValues(const StringVector &defaultValues)
{
m_defaultValues = defaultValues;
}
/*!
* \brief Returns an indication whether the argument could be detected
* when parsing.
*/
inline bool Argument::isPresent() const
{
return m_present;
}
/*!
* \brief Returns an indication whether the argument is mandatory.
*
* The parser will complain if a mandatory argument is not present.
*
* The default value is false.
*
* \sa setRequired()
*/
inline bool Argument::isRequired() const
{
return m_required;
}
/*!
* \brief Sets if this argument is mandatory or not.
*
* The parser will complain if a mandatory argument is not present.
*
* * \sa isRequired()
*/
inline void Argument::setRequired(bool value)
{
m_required = value;
}
/*!
* \brief Returns an indication whether the argument is combinable.
*
* The parser will complain if two arguments labeled as uncombinable are
* present at the same time.
*
* \sa setCombinable()
*/
inline bool Argument::isCombinable() const
{
return m_combinable;
}
/*!
* \brief Sets if this argument can be combined.
*
* The parser will complain if two arguments labeled as uncombinable are
* present at the same time.
*
* \sa isCombinable()
*/
inline void Argument::setCombinable(bool value)
{
m_combinable = value;
}
/*!
* \brief Returns an indication whether the argument can be specified implicitely.
*
* \sa setImplicit()
*/
inline bool Argument::isImplicit() const
{
return m_implicit;
}
/*!
* \brief Sets if this argument can be specified implicitely.
*
* \sa isImplicit()
*/
inline void Argument::setImplicit(bool value)
{
m_implicit = value;
}
/*!
* \brief Sets a \a callback function which will be called by the parser if
* the argument could be found and no parsing errors occured.
*/
inline void Argument::setCallback(Argument::CallbackFunction callback)
{
m_callbackFunction = callback;
}
/*!
* \brief Returns the secondary arguments for this argument.
*
* \sa setSecondaryArguments()
* \sa hasSecondaryArguments()
*/
inline const ArgumentVector &Argument::secondaryArguments() const
{
return m_secondaryArgs;
}
/*!
* \brief Returns an indication whether the argument has secondary arguments.
*
* \sa secondaryArguments()
* \sa setSecondaryArguments()
*/
inline bool Argument::hasSecondaryArguments() const
{
return !m_secondaryArgs.empty();
}
/*!
* \brief Returns the parents of this argument.
*
* If this argument is used as secondary argument, the arguments which
* contain this argument as secondary arguments are returned
* as "parents" of this argument.
*
* If this argument is used as a main argument shouldn't be used as
* secondary argument at the same time and thus have no parents.
*/
inline const ArgumentVector Argument::parents() const
{
return m_parents;
}
/*!
* \brief Returns an indication whether the argument is used as main argument.
*
* An argument used as main argument shouldn't be used as secondary
* arguments at the same time.
*/
inline bool Argument::isMainArgument() const
{
return m_isMainArg;
}
class LIB_EXPORT ArgumentParser
{
public:
ArgumentParser();
const ArgumentVector &mainArguments() const;
void setMainArguments(const ArgumentInitializerList &mainArguments);
void printHelp(std::ostream &os) const;
Argument *findArg(const ArgumentPredicate &predicate) const;
static Argument *findArg(const ArgumentVector &arguments, const ArgumentPredicate &predicate);
void verifySetup() const;
void parseArgs(int argc, char *argv[]);
unsigned int actualArgumentCount() const;
const std::string &currentDirectory() const;
bool areUnknownArgumentsIgnored() const;
void setIgnoreUnknownArguments(bool ignore);
private:
ArgumentVector m_mainArgs;
unsigned int m_actualArgc;
std::string m_currentDirectory;
bool m_ignoreUnknownArgs;
};
/*!
* \brief Returns the main arguments.
* \sa setMainArguments()
*/
inline const ArgumentVector &ArgumentParser::mainArguments() const
{
return m_mainArgs;
}
/*!
* \brief Returns the actual number of arguments that could be found when parsing.
*/
inline unsigned int ArgumentParser::actualArgumentCount() const
{
return m_actualArgc;
}
/*!
* \brief Returns the current directory.
*/
inline const std::string &ArgumentParser::currentDirectory() const
{
return m_currentDirectory;
}
/*!
* \brief Returns an indication whether unknown arguments detected
* when parsing should be ignored.
*
* If unknown arguments are not ignored the parser will throw a
* Failure when an unknown argument is detected.
* Otherwise only a warning will be shown.
*
* The default value is false.
*
* \sa setIgnoreUnknownArguments()
*/
inline bool ArgumentParser::areUnknownArgumentsIgnored() const
{
return m_ignoreUnknownArgs;
}
/*!
* \brief Sets whether the parser should ignore unknown arguments
* when parsing.
*
* If set to false the parser should throw a Failure object
* when an unknown argument is found. Otherwise only a warning
* will be printed.
*
* \sa areUnknownArgumentsIgnored()
*/
inline void ArgumentParser::setIgnoreUnknownArguments(bool ignore)
{
m_ignoreUnknownArgs = ignore;
}
class LIB_EXPORT HelpArgument : public Argument
{
public:
HelpArgument(ArgumentParser &parser);
};
}
#endif // ARGUMENTPARSER_H

@ -0,0 +1,44 @@
#include "failure.h"
namespace ApplicationUtilities {
/*!
* \class ApplicationUtilities::Failure
* \brief The exception that is thrown by an ArgumentParser when a parsing error occurs.
*
* \sa ApplicationUtilities::ArgumentParser
*/
/*!
* Constructs a new Failure.
*/
Failure::Failure() :
m_what("unspecified parsing exception")
{}
/*!
* Constructs a new Failure. \a what is a std::string
* describing the cause of the Failure.
*/
Failure::Failure(const std::string &what) :
m_what(what)
{}
/*!
* Destroys the Failure.
*/
Failure::~Failure() USE_NOTHROW
{}
/*!
* Returns a C-style character string describing the cause
* of the Failure.
*/
const char *Failure::what() const USE_NOTHROW
{
return m_what.c_str();
}
}

@ -0,0 +1,26 @@
#ifndef FAILURE_H
#define FAILURE_H
#include "global.h"
#include <exception>
#include <string>
namespace ApplicationUtilities {
class LIB_EXPORT Failure : public std::exception
{
public:
Failure();
Failure(const std::string &what);
~Failure() USE_NOTHROW;
virtual const char *what() const USE_NOTHROW;
private:
std::string m_what;
};
}
#endif // FAILURE_H

@ -0,0 +1,11 @@
#include "fakeqtconfigarguments.h"
namespace ApplicationUtilities {
FakeQtConfigArguments::FakeQtConfigArguments() :
m_qtWidgetsGuiArg("qt-widgets-gui", "g", "shows a Qt widgets based graphical user interface (the application has not been built with Qt widgets support)"),
m_qtQuickGuiArg("qt-quick-gui", "q", "shows a Qt quick based graphical user interface (the application has not been built with Qt quick support)")
{}
} // namespace ApplicationUtilities

@ -0,0 +1,44 @@
#ifndef APPLICATIONUTILITIES_FAKEQTCONFIGARGUMENTS_H
#define APPLICATIONUTILITIES_FAKEQTCONFIGARGUMENTS_H
#include "argumentparser.h"
namespace ApplicationUtilities {
class LIB_EXPORT FakeQtConfigArguments
{
public:
FakeQtConfigArguments();
Argument &qtWidgetsGuiArg();
Argument &qtQuickGuiArg();
bool areQtGuiArgsPresent() const;
private:
Argument m_qtWidgetsGuiArg;
Argument m_qtQuickGuiArg;
};
inline Argument &FakeQtConfigArguments::qtWidgetsGuiArg()
{
return m_qtWidgetsGuiArg;
}
inline Argument &FakeQtConfigArguments::qtQuickGuiArg()
{
return m_qtQuickGuiArg;
}
inline bool FakeQtConfigArguments::areQtGuiArgsPresent() const
{
return m_qtWidgetsGuiArg.isPresent() || m_qtQuickGuiArg.isPresent();
}
} // namespace ApplicationUtilities
#ifndef QT_CONFIG_ARGUMENTS
#define QT_CONFIG_ARGUMENTS ApplicationUtilities::FakeQtConfigArguments
#endif
#endif // APPLICATIONUTILITIES_FAKEQTCONFIGARGUMENTS_H

@ -0,0 +1,77 @@
#ifndef MARTCHUSUTILITY_LIBRARY_GLOBAL_H
#define MARTCHUSUTILITY_LIBRARY_GLOBAL_H
/*!
* \def PLATFORM_WINDOWS
* \brief Defined on Windows.
*/
/*!
* \def PLATFORM_UNIX
* \brief Defined on any UNIX system.
*/
/*!
* \def PLATFORM_LINUX
* \brief Defined on Linux.
*/
#ifdef _WIN32
# define PLATFORM_WINDOWS
#elif __unix__
# define PLATFORM_UNIX
#endif