diff --git a/src/util/argparser.cpp b/src/util/argparser.cpp index 1358025..1b333ce 100644 --- a/src/util/argparser.cpp +++ b/src/util/argparser.cpp @@ -1,5 +1,7 @@ -#include // std::find_if +#include // find_if #include // printf +#include // numeric_limits +#include // stod, stoi, stoul #include #include "util/argparser.h" @@ -276,6 +278,23 @@ void ArgParser::addOption(bool& value, char shortName, const char* longName, con addOption(std::move(option)); } +void ArgParser::addOption(const char*& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) +{ + Option option { + shortName, + longName, + argumentName, + usageString, + manString, + requiresArgument, + [&value](const char* a) -> bool { + value = a; + return true; + } + }; + addOption(std::move(option)); +} + void ArgParser::addOption(std::string& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) { Option option { @@ -293,6 +312,97 @@ void ArgParser::addOption(std::string& value, char shortName, const char* longNa addOption(std::move(option)); } +void ArgParser::addOption(std::string_view& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) +{ + Option option { + shortName, + longName, + argumentName, + usageString, + manString, + requiresArgument, + [&value](const char* a) -> bool { + value = a; + return true; + } + }; + addOption(std::move(option)); +} + +void ArgParser::addOption(int& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) +{ + Option option { + shortName, + longName, + argumentName, + usageString, + manString, + requiresArgument, + [&value](const char* a) -> bool { + try { + value = std::stoi(a); + return true; + } + catch (...) { + return false; + } + } + }; + addOption(std::move(option)); +} + +void ArgParser::addOption(unsigned int& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) +{ + Option option { + shortName, + longName, + argumentName, + usageString, + manString, + requiresArgument, + [&value](const char* a) -> bool { + unsigned long convert = 0; + try { + convert = std::stoul(a); + } + catch (...) { + return false; + } + + if (convert <= std::numeric_limits::max()) + { + value = static_cast(convert); + return true; + } + + return false; + } + }; + addOption(std::move(option)); +} + +void ArgParser::addOption(double& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) +{ + Option option { + shortName, + longName, + argumentName, + usageString, + manString, + requiresArgument, + [&value](const char* a) -> bool { + try { + value = std::stod(a); + return true; + } + catch (...) { + return false; + } + } + }; + addOption(std::move(option)); +} + void ArgParser::addOption(std::vector& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName, Required requiresArgument) { Option option { diff --git a/src/util/argparser.h b/src/util/argparser.h index 34613d6..3ffd655 100644 --- a/src/util/argparser.h +++ b/src/util/argparser.h @@ -1,7 +1,7 @@ #ifndef ARG_PARSER_H #define ARG_PARSER_H -#include +#include // function #include #include #include @@ -46,7 +46,12 @@ public: void addOption(Option&& option); void addOption(bool& value, char shortName, const char* longName, const char* usageString, const char* manString); + void addOption(const char*& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); void addOption(std::string& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); + void addOption(std::string_view& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); + void addOption(int& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); + void addOption(unsigned int& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); + void addOption(double& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); void addOption(std::vector& value, char shortName, const char* longName, const char* usageString, const char* manString, const char* argumentName = "", Required requiresArgument = Required::No); void setOptionIndex(int index) { m_optionIndex = index; } diff --git a/test/testutilargparser.cpp b/test/testutilargparser.cpp index 60241b4..5afc1f7 100644 --- a/test/testutilargparser.cpp +++ b/test/testutilargparser.cpp @@ -300,6 +300,75 @@ TEST_CASE(SingleNonRequiredStringOptions) // ----------------------------------------- +TEST_CASE(NumberOptions) +{ + // Required int short option + int intOpt1 = 0; + auto result = runParser({ "-i", "2147483647" }, [&](auto& parser) { + parser.addOption(intOpt1, 'i', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(intOpt1, 2147483647); + + // Required int short option, overflown value given + intOpt1 = 0; + result = runParser({ "-i", "2147483648" }, [&](auto& parser) { + parser.addOption(intOpt1, 'i', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(intOpt1, 0); + + // Required int short option, empty given + intOpt1 = 0; + result = runParser({ "-i" }, [&](auto& parser) { + parser.addOption(intOpt1, 'i', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(intOpt1, 0); + + // Required unsigned int short option + unsigned int unsignedIntOpt1 = 0; + result = runParser({ "-u", "4294967295" }, [&](auto& parser) { + parser.addOption(unsignedIntOpt1, 'u', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(unsignedIntOpt1, 4294967295); + + // Required unsigned int short option, overflown value given + unsignedIntOpt1 = 0; + result = runParser({ "-u", "4294967296" }, [&](auto& parser) { + parser.addOption(unsignedIntOpt1, 'u', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(unsignedIntOpt1, 0); + + // Required unsigned int short option, empty given + unsignedIntOpt1 = 0; + result = runParser({ "-u" }, [&](auto& parser) { + parser.addOption(unsignedIntOpt1, 'u', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(unsignedIntOpt1, 0); + + // Required double short option + double doubleOpt1 = 0; + result = runParser({ "-d", "999.999" }, [&](auto& parser) { + parser.addOption(doubleOpt1, 'd', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, true); + EXPECT_EQ(doubleOpt1, 999.999); + + // Required double short option, empty given + doubleOpt1 = 0; + result = runParser({ "-d" }, [&](auto& parser) { + parser.addOption(doubleOpt1, 'd', nullptr, nullptr, nullptr, nullptr, Util::ArgParser::Required::Yes); + }); + EXPECT_EQ(result, false); + EXPECT_EQ(doubleOpt1, 0); +} + +// ----------------------------------------- + TEST_CASE(VectorStringOptions) { // Required vector string short option, not given