3 #include "../conversion/stringconversion.h"
34 Argument::Argument(
const std::string &name,
const std::string abbreviation,
const std::string &description) :
37 m_requiredValueCount(0),
54 m_requiredValueCount(0),
82 int valueNamesPrint = 0;
84 os <<
" [" << *i <<
"]";
88 os <<
" [value " << (valueNamesPrint + 1) <<
"]";
92 os <<
" [" << *i <<
"]";
101 os << endl <<
"This argument is required.";
113 if(arg != except && arg->
isPresent() && !arg->isCombinable()) {
135 for(
Argument *arg : m_secondaryArgs) {
136 m_parents.erase(
remove(arg->m_parents.begin(), arg->m_parents.end(),
this), m_parents.end());
139 m_secondaryArgs.assign(secondaryArguments);
142 for(
Argument *arg : m_secondaryArgs) {
143 if(find(arg->m_parents.cbegin(), arg->m_parents.cend(),
this) == arg->m_parents.cend()) {
144 arg->m_parents.push_back(
this);
157 if(m_parents.size()) {
158 vector<string> names;
159 names.reserve(m_parents.size());
160 for(
const Argument *parent : m_parents) {
161 names.push_back(parent->name());
175 if(parent->isPresent()) {
191 if(sibling !=
this && sibling->isPresent() && !sibling->isCombinable()) {
218 m_ignoreUnknownArgs(true)
230 for(
Argument *arg : mainArguments) {
231 arg->m_isMainArg =
true;
233 m_mainArgs.assign(mainArguments);
241 if(!m_mainArgs.size())
243 os <<
"Available parameters:\n\n";
244 for(
const Argument *arg : m_mainArgs) {
255 return findArg(m_mainArgs, predicate);
267 }
else if(
Argument *subarg =
findArg(arg->secondaryArguments(), predicate)) {
288 vector<Argument *> verifiedArgs;
289 vector<string> abbreviations;
290 vector<string> names;
291 function<void (const ArgumentVector &args)> checkArguments;
292 checkArguments = [&verifiedArgs, &abbreviations, &names, &checkArguments] (
const ArgumentVector &args) {
294 if(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) != verifiedArgs.cend())
296 if(arg->isMainArgument() && arg->parents().size())
297 throw invalid_argument(
"Argument \"" + arg->name() +
"\" can not be used as main argument and sub argument at the same time.");
298 if(!arg->abbreviation().empty() && find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) != abbreviations.cend())
299 throw invalid_argument(
"Abbreviation \"" + arg->abbreviation() +
"\" has been used more then once.");
300 if(find(names.cbegin(), names.cend(), arg->name()) != names.cend())
301 throw invalid_argument(
"Name \"" + arg->name() +
"\" has been used more then once.");
302 abbreviations.push_back(arg->abbreviation());
303 names.push_back(arg->name());
304 verifiedArgs.push_back(arg);
307 checkArguments(m_mainArgs);
328 unsigned int actualArgc = 0;
329 int valuesToRead = 0;
332 m_currentDirectory = string(*argv);
334 m_currentDirectory.clear();
340 for(
char **i = argv + 1, ** end = argv + argc; i != end; ++i) {
342 if(!givenArg.empty()) {
343 if(valuesToRead <= 0 && givenArg.size() > 1 && givenArg.at(0) ==
'-') {
347 size_t equationPos = givenArg.find(
'=');
348 if(givenArg.size() > 2 && givenArg.at(1) ==
'-') {
351 pred = [&givenArg, equationPos] (
Argument *arg) {
352 return arg->name() == givenArg.substr(2, equationPos);
357 pred = [&givenArg, equationPos] (
Argument *arg) {
358 return arg->abbreviation() == givenArg.substr(1, equationPos);
367 if(currentArg->m_present) {
369 throw Failure(
"The argument \"" + currentArg->
name() +
"\" has been given more then one time.");
372 currentArg->m_present =
true;
376 if(equationPos != string::npos) {
378 string value = givenArg.substr(equationPos + 1);
379 if(valuesToRead != 0) {
380 currentArg->m_values.push_back(value);
381 if(valuesToRead > 0) {
385 throw Failure(
"Invalid extra information \"" + value +
"\" (specified using \"--argument=value\" syntax) for the argument \"" + currentArg->
name() +
"\" given.");
391 if(valuesToRead < 0) {
399 }
else if(currentArg) {
402 if(valuesToRead == 0) {
403 throw Failure(
"Invalid extra information \"" + givenArg +
"\" for the argument \"" + currentArg->
name() +
"\" given.");
404 }
else if(valuesToRead < 0) {
405 currentArg->m_values.push_back(givenArg);
407 currentArg->m_values.push_back(givenArg);
414 string msg(
"The given argument \"" + givenArg +
"\" is unknown.");
415 if(m_ignoreUnknownArgs) {
416 cout << msg <<
" It will be ignored." << endl;
425 function<void(Argument *, const ArgumentVector &, const function<void (Argument *, Argument *)> &)> foreachArg;
426 foreachArg = [&foreachArg] (
Argument *parent,
const ArgumentVector &args,
const function<void (Argument *, Argument *)> &proc) {
429 foreachArg(arg, arg->secondaryArguments(), proc);
436 if(arg->
parents().size() > 1) {
437 throw Failure(
"The argument \"" + arg->
name() +
"\" needs to be used together with one the following arguments: " + arg->
parentNames());
439 throw Failure(
"The argument \"" + arg->
name() +
"\" needs to be used together with the argument \"" + arg->
parents().at(0)->name() +
"\".");
442 Argument *conflictingArgument =
nullptr;
448 if(conflictingArgument) {
449 throw Failure(
"The argument \"" + conflictingArgument->
name() +
"\" can not be combined with \"" + arg->
name() +
"\".");
452 stringstream ss(stringstream::in | stringstream::out);
453 ss <<
"Not all required information for the given argument \"" << arg->
name() <<
"\" provided. You have to give the following information:";
454 int valueNamesPrint = 0;
455 for(
auto i = arg->m_valueNames.cbegin(), end = arg->m_valueNames.cend(); i != end; ++i) {
459 for(; valueNamesPrint < arg->m_requiredValueCount; ++valueNamesPrint) {
460 ss <<
"\nvalue " << (valueNamesPrint + 1);
465 throw Failure(
"The argument \"" + arg->
name() +
"\" is required but not given.");
469 m_actualArgc = actualArgc;
472 if(arg->
isPresent() && arg->m_callbackFunction) {
473 arg->m_callbackFunction(arg->
values());
void parseArgs(int argc, char *argv[])
This method invokes verifySetup() before parsing.
std::initializer_list< Argument * > ArgumentInitializerList
void setDescription(const std::string &description)
Sets the description of the argument.
bool isPresent() const
Returns an indication whether the argument could be detected when parsing.
ArgumentParser()
Constructs a new ArgumentParser.
const StringVector & values() const
Returns the additional values for the argument.
const ArgumentVector & secondaryArguments() const
Returns the secondary arguments for this argument.
const ArgumentVector parents() const
Returns the parents of this argument.
Contains currently only ArgumentParser and related classes.
const std::string & abbreviation() const
Returns the abbreviation of the argument.
Argument * conflictsWithArgument() const
Checks if this arguments conflicts with other arguments.
std::string parentNames() const
Returns the names of the parents in the form "parent1", "parent2, "parent3", ...
void setMainArguments(const ArgumentInitializerList &mainArguments)
Sets the main arguments for the parser.
Argument * firstPresentUncombinableArg(const ArgumentVector &args, const Argument *except)
This function return the first present and uncombinable argument of the given list of arguments...
LIB_EXPORT std::string concateStrings(const Container &strings, const std::string &delimiter=std::string(), bool skipEmpty=false, const std::string &leftClosure=std::string(), const std::string &rightClosure=std::string())
Concates the given strings using the specified delimiter.
~Argument()
Destroys the Argument.
void printInfo(std::ostream &os) const
Appends the name, the abbreviation and the description of the Argument to the give ostream...
Argument(const std::string &name, const std::string abbreviation=std::string(), const std::string &description=std::string())
Constructs an Argument with the given name, abbreviation and description.
std::function< bool(Argument *)> ArgumentPredicate
bool isRequired() const
Returns an indication whether the argument is mandatory.
void printHelp(std::ostream &os) const
Prints help information for all main arguments which have been set using setMainArguments().
bool isCombinable() const
Returns an indication whether the argument is combinable.
void setSecondaryArguments(const ArgumentInitializerList &secondaryArguments)
Sets the secondary arguments for this arguments.
void setName(const std::string &name)
Sets the name of the argument.
void setAbbreviation(const std::string &abbreviation)
Sets the abbreviation of the argument.
const std::string & name() const
Returns the name of the argument.
bool isMainArgument() const
Returns an indication whether the argument is used as main argument.
bool allRequiredValuesPresent() const
Returns an indication whether all required values are present.
The Argument class is a wrapper for command line argument information.
const StringList & valueNames() const
Returns the names of the requried values.
Argument * findArg(const ArgumentPredicate &predicate) const
Returns the first argument definition which matches the predicate.
const std::string & description() const
Returns the description of the argument.
void verifySetup() const
This method is used to verify the setup of the command line parser before parsing.
The exception that is thrown by an ArgumentParser when a parsing error occurs.
int requiredValueCount() const
Returns the number of values which are required to be given for this argument.
bool isParentPresent() const
Returns true if at least one of the parents is present.
std::vector< Argument * > ArgumentVector