|
|
@ -143,72 +143,69 @@ bool ArgParser::parseShortOption(std::string_view option, std::string_view next) |
|
|
|
// Optional: directly after, separated by '='
|
|
|
|
// Optional: directly after, separated by '='
|
|
|
|
bool ArgParser::parseLongOption(std::string_view option, std::string_view next) |
|
|
|
bool ArgParser::parseLongOption(std::string_view option, std::string_view next) |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool result = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string name = std::string(option.substr(0, option.find_first_of('='))); |
|
|
|
std::string name = std::string(option.substr(0, option.find_first_of('='))); |
|
|
|
std::string_view value = option.substr(option.find_first_of('=') + 1); |
|
|
|
std::string_view value = option.substr(option.find_first_of('=') + 1); |
|
|
|
|
|
|
|
|
|
|
|
bool argumentProvided = true; |
|
|
|
|
|
|
|
if (name.compare(value) == 0 && option.find('=') == std::string_view::npos) { |
|
|
|
|
|
|
|
argumentProvided = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("Parsing long option: '%s' with value '%s'\n", name.data(), argumentProvided ? value.data() : ""); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto foundOption = std::find_if(m_options.begin(), m_options.end(), [&name](Option& it) -> bool { |
|
|
|
auto foundOption = std::find_if(m_options.begin(), m_options.end(), [&name](Option& it) -> bool { |
|
|
|
return it.longName && it.longName == name; |
|
|
|
return it.longName && it.longName == name; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (foundOption == m_options.cend()) { |
|
|
|
if (foundOption == m_options.cend()) { |
|
|
|
printError(name.data(), Error::OptionUnrecognized); |
|
|
|
printError(name.data(), Error::OptionUnrecognized); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum class ArgumentProvided { |
|
|
|
|
|
|
|
No, |
|
|
|
|
|
|
|
DirectlyAfter, |
|
|
|
|
|
|
|
Seperated, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
result = false; |
|
|
|
auto argument = ArgumentProvided::No; |
|
|
|
|
|
|
|
if (name != value || option.find('=') != std::string_view::npos) { |
|
|
|
|
|
|
|
argument = ArgumentProvided::DirectlyAfter; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (argumentProvided) { |
|
|
|
else if (!next.empty() && next[0] != '-') { |
|
|
|
if (foundOption->requiresArgument == Required::No) { |
|
|
|
argument = ArgumentProvided::Seperated; |
|
|
|
|
|
|
|
value = next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool result = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (foundOption->requiresArgument == Required::No) { |
|
|
|
|
|
|
|
if (argument == ArgumentProvided::DirectlyAfter) { |
|
|
|
foundOption->error = Error::OptionDoesntAllowArgument; |
|
|
|
foundOption->error = Error::OptionDoesntAllowArgument; |
|
|
|
printError(name.data(), Error::OptionDoesntAllowArgument); |
|
|
|
printError(name.data(), Error::OptionDoesntAllowArgument); |
|
|
|
|
|
|
|
return false; |
|
|
|
result = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (foundOption->requiresArgument == Required::Yes) { |
|
|
|
|
|
|
|
result = foundOption->acceptValue(value.data()); |
|
|
|
|
|
|
|
if (!result) { |
|
|
|
|
|
|
|
printError(name.data(), Error::OptionInvalidArgumentType); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (foundOption->requiresArgument == Required::Optional) { |
|
|
|
|
|
|
|
result = foundOption->acceptValue(value.data()); |
|
|
|
|
|
|
|
if (!result) { |
|
|
|
|
|
|
|
printError(name.data(), Error::OptionInvalidArgumentType); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME: Figure out why providing a nullptr breaks the lambda here.
|
|
|
|
|
|
|
|
result = foundOption->acceptValue(""); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (!next.empty() && foundOption->requiresArgument == Required::Yes) { |
|
|
|
else if (foundOption->requiresArgument == Required::Yes) { |
|
|
|
if (next[0] == '-') { |
|
|
|
if (argument == ArgumentProvided::No) { |
|
|
|
foundOption->error = Error::OptionRequiresArgument; |
|
|
|
foundOption->error = Error::OptionRequiresArgument; |
|
|
|
printError(name.data(), Error::OptionRequiresArgument); |
|
|
|
printError(name.data(), Error::OptionRequiresArgument); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
result = false; |
|
|
|
result = foundOption->acceptValue(value.data()); |
|
|
|
|
|
|
|
if (!result) { |
|
|
|
|
|
|
|
printError(name.data(), Error::OptionInvalidArgumentType); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
|
|
|
|
result = foundOption->acceptValue(next.data()); |
|
|
|
if (argument == ArgumentProvided::Seperated) { |
|
|
|
m_optionIndex++; |
|
|
|
m_optionIndex++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (foundOption->requiresArgument == Required::Optional) { |
|
|
|
|
|
|
|
if (argument == ArgumentProvided::DirectlyAfter) { |
|
|
|
|
|
|
|
result = foundOption->acceptValue(value.data()); |
|
|
|
if (!result) { |
|
|
|
if (!result) { |
|
|
|
printError(name.data(), Error::OptionInvalidArgumentType); |
|
|
|
printError(name.data(), Error::OptionInvalidArgumentType); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (foundOption->requiresArgument == Required::Yes) { |
|
|
|
|
|
|
|
foundOption->error = Error::OptionRequiresArgument; |
|
|
|
|
|
|
|
printError(name.data(), Error::OptionRequiresArgument); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
// FIXME: Figure out why providing a nullptr breaks the lambda here.
|
|
|
|
|
|
|
|
result = foundOption->acceptValue(""); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|