Use C-strings for argument definitions
Argument names and abbreviations are always C-string literals and hence using std::string has no advantage.
This commit is contained in:
parent
2a58a83c3c
commit
f3077ef8e3
|
@ -25,6 +25,11 @@ const char *applicationAuthor = nullptr;
|
|||
const char *applicationVersion = nullptr;
|
||||
const char *applicationUrl = nullptr;
|
||||
|
||||
inline bool notEmpty(const char *str)
|
||||
{
|
||||
return str && *str;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \class ApplicationUtilities::Argument
|
||||
* \brief The Argument class is a wrapper for command line argument information.
|
||||
|
@ -41,7 +46,11 @@ const char *applicationUrl = nullptr;
|
|||
* 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) :
|
||||
Argument::Argument(const char *name, const char *abbreviation, const char *description, const char *example) :
|
||||
m_name(name),
|
||||
m_abbreviation(abbreviation),
|
||||
m_description(description),
|
||||
m_example(example),
|
||||
m_required(false),
|
||||
m_combinable(false),
|
||||
m_implicit(false),
|
||||
|
@ -50,40 +59,7 @@ Argument::Argument(const std::string &name, const std::string abbreviation, cons
|
|||
m_default(false),
|
||||
m_present(false),
|
||||
m_isMainArg(false)
|
||||
{
|
||||
setName(name);
|
||||
setAbbreviation(abbreviation);
|
||||
setDescription(description);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief 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_denotesOperation(false),
|
||||
m_requiredValueCount(0),
|
||||
m_default(false),
|
||||
m_present(false),
|
||||
m_isMainArg(false)
|
||||
{
|
||||
if(name) {
|
||||
setName(name);
|
||||
} else {
|
||||
setName(string());
|
||||
}
|
||||
if(abbreviation) {
|
||||
setAbbreviation(abbreviation);
|
||||
}
|
||||
if(description) {
|
||||
setDescription(description);
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Destroys the Argument.
|
||||
|
@ -126,13 +102,13 @@ Argument::~Argument()
|
|||
void Argument::printInfo(ostream &os, unsigned char indentionLevel) const
|
||||
{
|
||||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
|
||||
if(!name().empty()) {
|
||||
if(notEmpty(name())) {
|
||||
os << "--" << name();
|
||||
}
|
||||
if(!name().empty() && !abbreviation().empty()) {
|
||||
if(notEmpty(name()) && notEmpty(abbreviation())) {
|
||||
os << ", ";
|
||||
}
|
||||
if(!abbreviation().empty()) {
|
||||
if(notEmpty(abbreviation())) {
|
||||
os << "-" << abbreviation();
|
||||
}
|
||||
if(requiredValueCount() > 0) {
|
||||
|
@ -151,7 +127,7 @@ void Argument::printInfo(ostream &os, unsigned char indentionLevel) const
|
|||
os << " ...";
|
||||
}
|
||||
++indentionLevel;
|
||||
if(!description().empty()) {
|
||||
if(notEmpty(description())) {
|
||||
os << endl;
|
||||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
|
||||
os << description();
|
||||
|
@ -161,7 +137,7 @@ void Argument::printInfo(ostream &os, unsigned char indentionLevel) const
|
|||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
|
||||
os << "This argument is required.";
|
||||
}
|
||||
if(!example().empty()) {
|
||||
if(notEmpty(example())) {
|
||||
for(unsigned char i = 0; i < indentionLevel; ++i) os << " ";
|
||||
os << endl << "Usage: " << example();
|
||||
}
|
||||
|
@ -391,6 +367,7 @@ Argument *ArgumentParser::findArg(const ArgumentVector &arguments, const Argumen
|
|||
return nullptr; // no argument matches
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
/*!
|
||||
* \brief This method is used to verify the setup of the command line parser before parsing.
|
||||
*
|
||||
|
@ -416,32 +393,37 @@ void ArgumentParser::verifySetup() const
|
|||
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.");
|
||||
throw invalid_argument("Argument \"" + string(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(notEmpty(arg->abbreviation()) && find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) != abbreviations.cend()) {
|
||||
throw invalid_argument("Abbreviation \"" + string(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.");
|
||||
throw invalid_argument("Name \"" + string(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.");
|
||||
throw invalid_argument("Default argument \"" + string(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.");
|
||||
throw invalid_argument("The arguments \"" + string(implicitArg->name()) + "\" and \"" + string(arg->name()) + "\" can not be both implicit.");
|
||||
} else {
|
||||
implicitArg = arg;
|
||||
}
|
||||
}
|
||||
abbreviations.push_back(arg->abbreviation());
|
||||
names.push_back(arg->name());
|
||||
if(arg->abbreviation()) {
|
||||
abbreviations.push_back(arg->abbreviation());
|
||||
}
|
||||
if(arg->name()) {
|
||||
names.push_back(arg->name());
|
||||
}
|
||||
verifiedArgs.push_back(arg);
|
||||
checkArguments(arg->secondaryArguments());
|
||||
}
|
||||
};
|
||||
checkArguments(m_mainArgs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief This method invokes verifySetup() before parsing. See its do documentation for more
|
||||
|
@ -459,7 +441,9 @@ void ArgumentParser::verifySetup() const
|
|||
void ArgumentParser::parseArgs(int argc, char *argv[])
|
||||
{
|
||||
// initiate parser
|
||||
#ifdef DEBUG_BUILD
|
||||
verifySetup();
|
||||
#endif
|
||||
m_actualArgc = 0; // reset actual agument count
|
||||
unsigned int actualArgc = 0;
|
||||
int valuesToRead = 0;
|
||||
|
@ -511,7 +495,7 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
|||
// 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 specified more than one time.");
|
||||
throw Failure("The argument \"" + string(currentArg->name()) + "\" has been specified more than one time.");
|
||||
} else {
|
||||
// set present flag of argument
|
||||
currentArg->m_present = true;
|
||||
|
@ -615,7 +599,7 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
|||
}
|
||||
// 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.");
|
||||
throw Failure("The argument \"" + string(arg->name()) + "\" is required but not given.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -623,9 +607,9 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
|||
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());
|
||||
throw Failure("The argument \"" + string(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() + "\".");
|
||||
throw Failure("The argument \"" + string(arg->name()) + "\" needs to be used together with the argument \"" + arg->parents().front()->name() + "\".");
|
||||
}
|
||||
}
|
||||
Argument *conflictingArgument = nullptr;
|
||||
|
@ -637,11 +621,11 @@ void ArgumentParser::parseArgs(int argc, char *argv[])
|
|||
conflictingArgument = arg->conflictsWithArgument();
|
||||
}
|
||||
if(conflictingArgument) {
|
||||
throw Failure("The argument \"" + conflictingArgument->name() + "\" can not be combined with \"" + arg->name() + "\".");
|
||||
throw Failure("The argument \"" + string(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:";
|
||||
ss << "Not all required information for the given argument \"" << string(arg->name()) << "\" provided. You have to give the following information:";
|
||||
int valueNamesPrint = 0;
|
||||
for(const auto &name : arg->m_valueNames) {
|
||||
ss << "\n" << name;
|
||||
|
|
|
@ -41,19 +41,18 @@ class LIB_EXPORT Argument
|
|||
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 char *name, const char *abbreviation = nullptr, const char *description = nullptr, const char *example = nullptr);
|
||||
~Argument();
|
||||
|
||||
const std::string &name() const;
|
||||
void setName(const std::string &name);
|
||||
const std::string &abbreviation() const;
|
||||
void setAbbreviation(const std::string &abbreviation);
|
||||
const char *name() const;
|
||||
void setName(const char *name);
|
||||
const char *abbreviation() const;
|
||||
void setAbbreviation(const char *abbreviation);
|
||||
//unsigned char isAmbiguous(const ArgumentParser &parser) const;
|
||||
const std::string &description() const;
|
||||
void setDescription(const std::string &description);
|
||||
const std::string &example() const;
|
||||
void setExample(const std::string &example);
|
||||
const char *description() const;
|
||||
void setDescription(const char *description);
|
||||
const char *example() const;
|
||||
void setExample(const char *example);
|
||||
const StringVector &values() const;
|
||||
const std::string &value(StringVector::size_type index) const;
|
||||
StringVector::size_type valueCount() const;
|
||||
|
@ -90,10 +89,10 @@ public:
|
|||
Argument *conflictsWithArgument() const;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_abbreviation;
|
||||
std::string m_description;
|
||||
std::string m_example;
|
||||
const char *m_name;
|
||||
const char *m_abbreviation;
|
||||
const char *m_description;
|
||||
const char *m_example;
|
||||
bool m_required;
|
||||
bool m_combinable;
|
||||
bool m_implicit;
|
||||
|
@ -116,7 +115,7 @@ private:
|
|||
* The parser compares the name with the characters following a "--" prefix to
|
||||
* identify arguments.
|
||||
*/
|
||||
inline const std::string &Argument::name() const
|
||||
inline const char *Argument::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
@ -129,11 +128,20 @@ inline const std::string &Argument::name() const
|
|||
* The parser compares the name with the characters following a "--" prefix to
|
||||
* identify arguments.
|
||||
*/
|
||||
inline void Argument::setName(const std::string &name)
|
||||
inline void Argument::setName(const char *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");
|
||||
#ifdef DEBUG_BUILD
|
||||
if(name && *name) {
|
||||
for(const char *c = name; *c; ++c) {
|
||||
switch(*c) {
|
||||
case ' ': case '=':
|
||||
throw std::invalid_argument("name mustn't contain white spaces or equation chars");
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
|
@ -143,7 +151,7 @@ inline void Argument::setName(const std::string &name)
|
|||
* The parser compares the abbreviation with the characters following a "-" prefix to
|
||||
* identify arguments.
|
||||
*/
|
||||
inline const std::string &Argument::abbreviation() const
|
||||
inline const char *Argument::abbreviation() const
|
||||
{
|
||||
return m_abbreviation;
|
||||
}
|
||||
|
@ -157,11 +165,20 @@ inline const std::string &Argument::abbreviation() const
|
|||
* The parser compares the abbreviation with the characters following a "-" prefix to
|
||||
* identify arguments.
|
||||
*/
|
||||
inline void Argument::setAbbreviation(const std::string &abbreviation)
|
||||
inline void Argument::setAbbreviation(const char *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");
|
||||
#ifdef DEBUG_BUILD
|
||||
if(abbreviation && *abbreviation) {
|
||||
for(const char *c = abbreviation; *c; ++c) {
|
||||
switch(*c) {
|
||||
case ' ': case '=':
|
||||
throw std::invalid_argument("abbreviation mustn't contain white spaces or equation chars");
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
m_abbreviation = abbreviation;
|
||||
}
|
||||
|
||||
|
@ -170,7 +187,7 @@ inline void Argument::setAbbreviation(const std::string &abbreviation)
|
|||
*
|
||||
* The parser uses the description when printing help information.
|
||||
*/
|
||||
inline const std::string &Argument::description() const
|
||||
inline const char *Argument::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
@ -180,7 +197,7 @@ inline const std::string &Argument::description() const
|
|||
*
|
||||
* The parser uses the description when printing help information.
|
||||
*/
|
||||
inline void Argument::setDescription(const std::string &description)
|
||||
inline void Argument::setDescription(const char *description)
|
||||
{
|
||||
m_description = description;
|
||||
}
|
||||
|
@ -190,7 +207,7 @@ inline void Argument::setDescription(const std::string &description)
|
|||
*
|
||||
* The parser uses the description when printing help information.
|
||||
*/
|
||||
inline const std::string &Argument::example() const
|
||||
inline const char *Argument::example() const
|
||||
{
|
||||
return m_example;
|
||||
}
|
||||
|
@ -200,7 +217,7 @@ inline const std::string &Argument::example() const
|
|||
*
|
||||
* The parser uses the description when printing help information.
|
||||
*/
|
||||
inline void Argument::setExample(const std::string &example)
|
||||
inline void Argument::setExample(const char *example)
|
||||
{
|
||||
m_example = example;
|
||||
}
|
||||
|
@ -564,7 +581,9 @@ public:
|
|||
void printHelp(std::ostream &os) const;
|
||||
Argument *findArg(const ArgumentPredicate &predicate) const;
|
||||
static Argument *findArg(const ArgumentVector &arguments, const ArgumentPredicate &predicate);
|
||||
#ifdef DEBUG_BUILD
|
||||
void verifySetup() const;
|
||||
#endif
|
||||
void parseArgs(int argc, char *argv[]);
|
||||
unsigned int actualArgumentCount() const;
|
||||
const std::string ¤tDirectory() const;
|
||||
|
|
Loading…
Reference in New Issue