added missing initialization of m_denotesOperation, small adjustments
This commit is contained in:
parent
9f25d76afe
commit
8896fb7673
|
@ -59,6 +59,7 @@ Argument::Argument(const char *name, const char *abbreviation, const char *descr
|
||||||
m_required(false),
|
m_required(false),
|
||||||
m_combinable(false),
|
m_combinable(false),
|
||||||
m_implicit(false),
|
m_implicit(false),
|
||||||
|
m_denotesOperation(false),
|
||||||
m_requiredValueCount(0),
|
m_requiredValueCount(0),
|
||||||
m_default(false),
|
m_default(false),
|
||||||
m_present(false),
|
m_present(false),
|
||||||
|
@ -168,14 +169,15 @@ Argument *firstPresentUncombinableArg(const ArgumentVector &args, const Argument
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the secondary arguments for this arguments. The given arguments will be considered as
|
* 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
|
* secondary arguments of this argument by the argument parser. This means that the parser
|
||||||
* will complain if these arguments are given, but not their parent. If secondary arguments are
|
* will complain if these arguments are given, but not this argument. If secondary arguments are
|
||||||
* labeled as mandatory their parent is also mandatory.
|
* 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
|
* The Argument does not take ownership. Do not destroy the given arguments as long as they are
|
||||||
* used as secondary arguments.
|
* used as secondary arguments.
|
||||||
*
|
*
|
||||||
* \sa secondaryArguments()
|
* \sa secondaryArguments()
|
||||||
|
* \sa addSecondaryArgument()
|
||||||
* \sa hasSecondaryArguments()
|
* \sa hasSecondaryArguments()
|
||||||
*/
|
*/
|
||||||
void Argument::setSecondaryArguments(const ArgumentInitializerList &secondaryArguments)
|
void Argument::setSecondaryArguments(const ArgumentInitializerList &secondaryArguments)
|
||||||
|
@ -195,6 +197,23 @@ void Argument::setSecondaryArguments(const ArgumentInitializerList &secondaryArg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Adds \a arg as a secondary argument for this argument.
|
||||||
|
*
|
||||||
|
* \sa secondaryArguments()
|
||||||
|
* \sa setSecondaryArguments()
|
||||||
|
* \sa hasSecondaryArguments()
|
||||||
|
*/
|
||||||
|
void Argument::addSecondaryArgument(Argument *arg)
|
||||||
|
{
|
||||||
|
if(find(m_secondaryArgs.cbegin(), m_secondaryArgs.cend(), arg) == m_secondaryArgs.cend()) {
|
||||||
|
m_secondaryArgs.push_back(arg);
|
||||||
|
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 the names of the parents in the form "parent1", "parent2, "parent3", ...
|
||||||
* Returns an empty string if this Argument has no parents.
|
* Returns an empty string if this Argument has no parents.
|
||||||
|
@ -338,19 +357,32 @@ void ArgumentParser::verifySetup() const
|
||||||
vector<Argument *> verifiedArgs;
|
vector<Argument *> verifiedArgs;
|
||||||
vector<string> abbreviations;
|
vector<string> abbreviations;
|
||||||
vector<string> names;
|
vector<string> names;
|
||||||
|
const Argument *implicitArg = nullptr;
|
||||||
function<void (const ArgumentVector &args)> checkArguments;
|
function<void (const ArgumentVector &args)> checkArguments;
|
||||||
checkArguments = [&verifiedArgs, &abbreviations, &names, &checkArguments, this] (const ArgumentVector &args) {
|
checkArguments = [&verifiedArgs, &abbreviations, &names, &checkArguments, &implicitArg, this] (const ArgumentVector &args) {
|
||||||
for(Argument *arg : args) {
|
for(Argument *arg : args) {
|
||||||
if(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) != verifiedArgs.cend())
|
if(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) != verifiedArgs.cend()) {
|
||||||
continue; // do not verify the same argument twice
|
continue; // do not verify the same argument twice
|
||||||
if(arg->isMainArgument() && arg->parents().size())
|
}
|
||||||
|
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.");
|
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())
|
}
|
||||||
|
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.");
|
throw invalid_argument("Abbreviation \"" + arg->abbreviation() + "\" has been used more then once.");
|
||||||
if(find(names.cbegin(), names.cend(), arg->name()) != names.cend())
|
}
|
||||||
|
if(find(names.cbegin(), names.cend(), arg->name()) != names.cend()) {
|
||||||
throw invalid_argument("Name \"" + arg->name() + "\" has been used more then once.");
|
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()))
|
}
|
||||||
|
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.");
|
throw invalid_argument("Default argument \"" + arg->name() + "\" doesn't provide the required number of default values.");
|
||||||
|
}
|
||||||
|
if(arg->isImplicit()) {
|
||||||
|
if(implicitArg) {
|
||||||
|
throw invalid_argument("The arguments \"" + implicitArg->name() + "\" and \"" + arg->name() + "\" can not be both implicit.");
|
||||||
|
} else {
|
||||||
|
implicitArg = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
abbreviations.push_back(arg->abbreviation());
|
abbreviations.push_back(arg->abbreviation());
|
||||||
names.push_back(arg->name());
|
names.push_back(arg->name());
|
||||||
verifiedArgs.push_back(arg);
|
verifiedArgs.push_back(arg);
|
||||||
|
@ -386,11 +418,19 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||||
} else {
|
} else {
|
||||||
m_currentDirectory.clear();
|
m_currentDirectory.clear();
|
||||||
}
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
// parse given arguments
|
// parse given arguments
|
||||||
if(argc >= 2) {
|
if(argc >= 2) {
|
||||||
Argument *currentArg = nullptr;
|
Argument *currentArg = nullptr;
|
||||||
// iterate through given arguments
|
// iterate through given arguments
|
||||||
for(char **i = argv + 1, ** end = argv + argc; i != end; ++i) {
|
for(char **i = argv + 1, **end = argv + argc; i != end; ++i) {
|
||||||
string givenArg(*i); // convert argument to string
|
string givenArg(*i); // convert argument to string
|
||||||
if(!givenArg.empty()) { // skip empty entries
|
if(!givenArg.empty()) { // skip empty entries
|
||||||
if(valuesToRead <= 0 && givenArg.size() > 1 && givenArg.front() == '-') {
|
if(valuesToRead <= 0 && givenArg.size() > 1 && givenArg.front() == '-') {
|
||||||
|
@ -414,13 +454,13 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||||
return arg->abbreviation() == givenId;
|
return arg->abbreviation() == givenId;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// find the corresponding instande of the Argument class
|
// find the corresponding instance of the Argument class
|
||||||
currentArg = findArg(pred);
|
currentArg = findArg(pred);
|
||||||
if(currentArg) {
|
if(currentArg) {
|
||||||
// the corresponding instance of Argument class has been found
|
// the corresponding instance of Argument class has been found
|
||||||
if(currentArg->m_present) {
|
if(currentArg->m_present) {
|
||||||
// the argument has been provided more then once
|
// the argument has been provided more then once
|
||||||
throw Failure("The argument \"" + currentArg->name() + "\" has been given more then one time.");
|
throw Failure("The argument \"" + currentArg->name() + "\" has been specified more than one time.");
|
||||||
} else {
|
} else {
|
||||||
// set present flag of argument
|
// set present flag of argument
|
||||||
currentArg->m_present = true;
|
currentArg->m_present = true;
|
||||||
|
@ -464,6 +504,7 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(currentArg) {
|
if(currentArg) {
|
||||||
|
cout << "first arg found" << endl;
|
||||||
currentArg->m_present = true;
|
currentArg->m_present = true;
|
||||||
++actualArgc; // we actually found an argument
|
++actualArgc; // we actually found an argument
|
||||||
// now we might need to read values tied to that argument
|
// now we might need to read values tied to that argument
|
||||||
|
@ -472,16 +513,19 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// -> check if there's an implicit argument definition
|
// -> check if there's an implicit argument definition
|
||||||
for(Argument *arg : m_mainArgs) {
|
try {
|
||||||
if(!arg->isPresent() && arg->isImplicit()) {
|
foreachArg(nullptr, m_mainArgs, [&actualArgc, &valuesToRead, ¤tArg, this] (Argument *, Argument *arg) {
|
||||||
// set present flag of argument
|
if(!arg->isPresent() && arg->isImplicit()) {
|
||||||
arg->m_present = true;
|
throw arg;
|
||||||
++actualArgc; // we actually found an argument
|
}
|
||||||
// now we might need to read values tied to that argument
|
});
|
||||||
valuesToRead = arg->requiredValueCount();
|
} catch(Argument *arg) {
|
||||||
currentArg = arg;
|
// set present flag of argument
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(currentArg) {
|
if(currentArg) {
|
||||||
|
@ -509,16 +553,23 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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
|
// iterate actually through all arguments using previously defined function to check gathered arguments
|
||||||
foreachArg(nullptr, m_mainArgs, [this] (Argument *parent, Argument *arg) {
|
foreachArg(nullptr, m_mainArgs, [this] (Argument *parent, Argument *arg) {
|
||||||
|
if(!arg->isPresent()) {
|
||||||
|
// 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
foreachArg(nullptr, m_mainArgs, [this] (Argument *, Argument *arg) {
|
||||||
if(arg->isPresent()) {
|
if(arg->isPresent()) {
|
||||||
if(!arg->isMainArgument() && arg->parents().size() && !arg->isParentPresent()) {
|
if(!arg->isMainArgument() && arg->parents().size() && !arg->isParentPresent()) {
|
||||||
if(arg->parents().size() > 1) {
|
if(arg->parents().size() > 1) {
|
||||||
|
@ -551,18 +602,6 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
throw Failure(ss.str());
|
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
|
// set actual argument count
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
void printInfo(std::ostream &os, unsigned char indentionLevel = 0) const;
|
void printInfo(std::ostream &os, unsigned char indentionLevel = 0) const;
|
||||||
const ArgumentVector &secondaryArguments() const;
|
const ArgumentVector &secondaryArguments() const;
|
||||||
void setSecondaryArguments(const ArgumentInitializerList &secondaryArguments);
|
void setSecondaryArguments(const ArgumentInitializerList &secondaryArguments);
|
||||||
|
void addSecondaryArgument(Argument *arg);
|
||||||
bool hasSecondaryArguments() const;
|
bool hasSecondaryArguments() const;
|
||||||
const ArgumentVector parents() const;
|
const ArgumentVector parents() const;
|
||||||
bool isMainArgument() const;
|
bool isMainArgument() const;
|
||||||
|
@ -174,7 +175,7 @@ inline void Argument::setDescription(const std::string &description)
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the additional values for the argument.
|
* \brief Returns the additional values for the argument.
|
||||||
*
|
*
|
||||||
* These values set by the parser when the command line arguments.
|
* These values set by the parser when parsing the command line arguments.
|
||||||
*/
|
*/
|
||||||
inline const StringVector &Argument::values() const
|
inline const StringVector &Argument::values() const
|
||||||
{
|
{
|
||||||
|
@ -184,7 +185,7 @@ inline const StringVector &Argument::values() const
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the value with the give \a index.
|
* \brief Returns the value with the give \a index.
|
||||||
*
|
*
|
||||||
* These values set by the parser when the command line arguments.
|
* These values set by the parser when parsing the command line arguments.
|
||||||
*/
|
*/
|
||||||
inline const std::string &Argument::value(StringVector::size_type index) const
|
inline const std::string &Argument::value(StringVector::size_type index) const
|
||||||
{
|
{
|
||||||
|
@ -262,7 +263,7 @@ inline const StringList &Argument::valueNames() const
|
||||||
*/
|
*/
|
||||||
inline void Argument::setValueNames(std::initializer_list<std::string> valueNames)
|
inline void Argument::setValueNames(std::initializer_list<std::string> valueNames)
|
||||||
{
|
{
|
||||||
m_valueNames = std::list<std::string>(valueNames);
|
m_valueNames.assign(valueNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -302,9 +303,9 @@ inline bool Argument::allRequiredValuesPresent() const
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns an indication whether the argument is a default argument.
|
* \brief Returns an indication whether the argument is a default argument.
|
||||||
*
|
*
|
||||||
* A default argument will be flagged as present when parsing arguments event
|
* A default argument will be flagged as present when parsing arguments even
|
||||||
* if it is not actually present if there is no uncombinable argument present
|
* if it is not actually present and there is no uncombinable argument present
|
||||||
* and it is a main argument or the parent is present.
|
* and the it is a main argument or the parent is present.
|
||||||
*
|
*
|
||||||
* The callback function will be invoked in this case as the argument where
|
* The callback function will be invoked in this case as the argument where
|
||||||
* actually present.
|
* actually present.
|
||||||
|
@ -418,7 +419,8 @@ inline void Argument::setCombinable(bool value)
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns an indication whether the argument can be specified implicitely.
|
* \brief Returns an indication whether the argument can be specified implicitely.
|
||||||
*
|
*
|
||||||
* An implicit main argument is assumed to be present even if only its value is present.
|
* An implicit argument is assumed to be present even if only its value is present.
|
||||||
|
* Only one argument can be implicit.
|
||||||
*
|
*
|
||||||
* \sa setImplicit()
|
* \sa setImplicit()
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue