Make ArgumentParser::verifyArgs() more strict
This commit is contained in:
parent
bbb884da30
commit
9f3ca443e4
|
@ -412,7 +412,7 @@ void ArgumentParser::parseArgs(int argc, const char *const *argv)
|
||||||
*/
|
*/
|
||||||
void ArgumentParser::readArgs(int argc, const char * const *argv)
|
void ArgumentParser::readArgs(int argc, const char * const *argv)
|
||||||
{
|
{
|
||||||
IF_DEBUG_BUILD(verifyArgs(m_mainArgs);)
|
IF_DEBUG_BUILD(verifyArgs(m_mainArgs, std::vector<char>(), std::vector<const char *>());)
|
||||||
m_actualArgc = 0;
|
m_actualArgc = 0;
|
||||||
if(argc) {
|
if(argc) {
|
||||||
// the first argument is the executable name
|
// the first argument is the executable name
|
||||||
|
@ -491,14 +491,12 @@ bool ArgumentParser::isUncombinableMainArgPresent() const
|
||||||
* - Verifies the sub arguments, too.
|
* - Verifies the sub arguments, too.
|
||||||
* - For debugging purposes only; hence only available in debug builds.
|
* - For debugging purposes only; hence only available in debug builds.
|
||||||
*/
|
*/
|
||||||
void ApplicationUtilities::ArgumentParser::verifyArgs(const ArgumentVector &args)
|
void ApplicationUtilities::ArgumentParser::verifyArgs(const ArgumentVector &args, vector<char> abbreviations, vector<const char *> names)
|
||||||
{
|
{
|
||||||
vector<const Argument *> verifiedArgs;
|
vector<const Argument *> verifiedArgs;
|
||||||
verifiedArgs.reserve(args.size());
|
verifiedArgs.reserve(args.size());
|
||||||
vector<char> abbreviations;
|
abbreviations.reserve(abbreviations.size() + args.size());
|
||||||
abbreviations.reserve(args.size());
|
names.reserve(names.size() + args.size());
|
||||||
vector<string> names;
|
|
||||||
names.reserve(args.size());
|
|
||||||
bool hasImplicit = false;
|
bool hasImplicit = false;
|
||||||
for(const Argument *arg : args) {
|
for(const Argument *arg : args) {
|
||||||
assert(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) == verifiedArgs.cend());
|
assert(find(verifiedArgs.cbegin(), verifiedArgs.cend(), arg) == verifiedArgs.cend());
|
||||||
|
@ -508,10 +506,12 @@ void ApplicationUtilities::ArgumentParser::verifyArgs(const ArgumentVector &args
|
||||||
hasImplicit |= arg->isImplicit();
|
hasImplicit |= arg->isImplicit();
|
||||||
assert(!arg->abbreviation() || find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) == abbreviations.cend());
|
assert(!arg->abbreviation() || find(abbreviations.cbegin(), abbreviations.cend(), arg->abbreviation()) == abbreviations.cend());
|
||||||
abbreviations.push_back(arg->abbreviation());
|
abbreviations.push_back(arg->abbreviation());
|
||||||
assert(!arg->name() || find(names.cbegin(), names.cend(), arg->name()) == names.cend());
|
assert(!arg->name() || find_if(names.cbegin(), names.cend(), [arg] (const char *name) { return !strcmp(arg->name(), name); }) == names.cend());
|
||||||
assert(arg->requiredValueCount() == 0 || arg->subArguments().size() == 0);
|
assert(arg->requiredValueCount() == 0 || arg->subArguments().size() == 0);
|
||||||
names.emplace_back(arg->name());
|
names.emplace_back(arg->name());
|
||||||
verifyArgs(arg->subArguments());
|
}
|
||||||
|
for(const Argument *arg : args) {
|
||||||
|
verifyArgs(arg->subArguments(), abbreviations, names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -231,7 +231,7 @@ public:
|
||||||
bool isUncombinableMainArgPresent() const;
|
bool isUncombinableMainArgPresent() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args);)
|
IF_DEBUG_BUILD(void verifyArgs(const ArgumentVector &args, std::vector<char> abbreviations, std::vector<const char *> names);)
|
||||||
void readSpecifiedArgs(ArgumentVector &args, std::size_t &index, const char *const *&argv, const char *const *end, Argument *&lastArg, const char *&argDenotation, bool completionMode = false);
|
void readSpecifiedArgs(ArgumentVector &args, std::size_t &index, const char *const *&argv, const char *const *end, Argument *&lastArg, const char *&argDenotation, bool completionMode = false);
|
||||||
void printBashCompletion(int argc, const char * const *argv, unsigned int cursorPos, const Argument *lastDetectedArg);
|
void printBashCompletion(int argc, const char * const *argv, unsigned int cursorPos, const Argument *lastDetectedArg);
|
||||||
void checkConstraints(const ArgumentVector &args);
|
void checkConstraints(const ArgumentVector &args);
|
||||||
|
|
|
@ -101,17 +101,17 @@ void ArgumentParserTests::testParsing()
|
||||||
outputFileArg.setCombinable(true);
|
outputFileArg.setCombinable(true);
|
||||||
Argument printFieldNamesArg("print-field-names", '\0', "prints available field names");
|
Argument printFieldNamesArg("print-field-names", '\0', "prints available field names");
|
||||||
Argument displayFileInfoArg("display-file-info", 'i', "displays general file information");
|
Argument displayFileInfoArg("display-file-info", 'i', "displays general file information");
|
||||||
|
Argument notAlbumArg("album", 'a', "should not be confused with album value");
|
||||||
displayFileInfoArg.setDenotesOperation(true);
|
displayFileInfoArg.setDenotesOperation(true);
|
||||||
displayFileInfoArg.setSubArguments({&fileArg, &verboseArg});
|
displayFileInfoArg.setSubArguments({&fileArg, &verboseArg, ¬AlbumArg});
|
||||||
Argument fieldsArg("fields", '\0', "specifies the fields");
|
Argument fieldsArg("fields", '\0', "specifies the fields");
|
||||||
fieldsArg.setRequiredValueCount(-1);
|
fieldsArg.setRequiredValueCount(-1);
|
||||||
fieldsArg.setValueNames({"title", "album", "artist", "trackpos"});
|
fieldsArg.setValueNames({"title", "album", "artist", "trackpos"});
|
||||||
fieldsArg.setImplicit(true);
|
fieldsArg.setImplicit(true);
|
||||||
Argument notAlbumArg("album", 'a', "should not be confused with album value");
|
|
||||||
Argument displayTagInfoArg("get", 'p', "displays the values of all specified tag fields (displays all fields if none specified)");
|
Argument displayTagInfoArg("get", 'p', "displays the values of all specified tag fields (displays all fields if none specified)");
|
||||||
displayTagInfoArg.setDenotesOperation(true);
|
displayTagInfoArg.setDenotesOperation(true);
|
||||||
displayTagInfoArg.setSubArguments({&fieldsArg, &filesArg, &verboseArg, ¬AlbumArg});
|
displayTagInfoArg.setSubArguments({&fieldsArg, &filesArg, &verboseArg, ¬AlbumArg});
|
||||||
parser.setMainArguments({&qtConfigArgs.qtWidgetsGuiArg(), &printFieldNamesArg, &displayTagInfoArg, &displayFileInfoArg, &helpArg, ¬AlbumArg});
|
parser.setMainArguments({&qtConfigArgs.qtWidgetsGuiArg(), &printFieldNamesArg, &displayTagInfoArg, &displayFileInfoArg, &helpArg});
|
||||||
|
|
||||||
// define some argument values
|
// define some argument values
|
||||||
const char *argv[] = {"tageditor", "get", "album", "title", "diskpos", "-f", "somefile"};
|
const char *argv[] = {"tageditor", "get", "album", "title", "diskpos", "-f", "somefile"};
|
||||||
|
|
Loading…
Reference in New Issue