diff options
-rw-r--r-- | Source/cmArgumentParser.h | 11 | ||||
-rw-r--r-- | Tests/CMakeLib/testArgumentParser.cxx | 49 |
2 files changed, 49 insertions, 11 deletions
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h index 2120a27..8be5a9c 100644 --- a/Source/cmArgumentParser.h +++ b/Source/cmArgumentParser.h @@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include <cm/optional> #include <cm/string_view> #include <cmext/string_view> @@ -39,6 +40,16 @@ public: void Bind(std::vector<std::string>& val); void Bind(std::vector<std::vector<std::string>>& val); + // cm::optional<> records the presence the keyword to which it binds. + template <typename T> + void Bind(cm::optional<T>& optVal) + { + if (!optVal) { + optVal.emplace(); + } + this->Bind(*optVal); + } + void Consume(cm::string_view arg, void* result, std::vector<std::string>* unparsedArguments, std::vector<cm::string_view>* keywordsMissingValue, diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx index 954c96f..52c5861 100644 --- a/Tests/CMakeLib/testArgumentParser.cxx +++ b/Tests/CMakeLib/testArgumentParser.cxx @@ -6,6 +6,7 @@ #include <string> #include <vector> +#include <cm/optional> #include <cm/string_view> #include <cmext/string_view> @@ -19,29 +20,38 @@ struct Result bool Option2 = false; std::string String1; - std::string String2; + cm::optional<std::string> String2; + cm::optional<std::string> String3; std::vector<std::string> List1; std::vector<std::string> List2; - std::vector<std::string> List3; + cm::optional<std::vector<std::string>> List3; + cm::optional<std::vector<std::string>> List4; + cm::optional<std::vector<std::string>> List5; std::vector<std::vector<std::string>> Multi1; std::vector<std::vector<std::string>> Multi2; - std::vector<std::vector<std::string>> Multi3; + cm::optional<std::vector<std::vector<std::string>>> Multi3; + cm::optional<std::vector<std::vector<std::string>>> Multi4; }; std::initializer_list<cm::string_view> const args = { /* clang-format off */ "OPTION_1", // option + // "OPTION_2", // option that is not present "STRING_1", // string arg missing value - "STRING_2", "foo", "bar", // string arg + unparsed value + "STRING_2", "foo", "bar", // string arg + unparsed value, presence captured + // "STRING_3", // string arg that is not present "LIST_1", // list arg missing values "LIST_2", "foo", "bar", // list arg with 2 elems "LIST_3", "bar", // list arg ... "LIST_3", "foo", // ... with continuation + "LIST_4", // list arg missing values, presence captured + // "LIST_5", // list arg that is not present "MULTI_2", // multi list with 0 lists "MULTI_3", "foo", "bar", // multi list with first list with two elems "MULTI_3", "bar", "foo", // multi list with second list with two elems + // "MULTI_4", // multi list arg that is not present /* clang-format on */ }; @@ -52,7 +62,8 @@ bool verifyResult(Result const& result, static std::vector<std::string> const foobar = { "foo", "bar" }; static std::vector<std::string> const barfoo = { "bar", "foo" }; static std::vector<cm::string_view> const missing = { "STRING_1"_s, - "LIST_1"_s }; + "LIST_1"_s, + "LIST_4"_s }; #define ASSERT_TRUE(x) \ do { \ @@ -66,18 +77,26 @@ bool verifyResult(Result const& result, ASSERT_TRUE(!result.Option2); ASSERT_TRUE(result.String1.empty()); - ASSERT_TRUE(result.String2 == "foo"); + ASSERT_TRUE(result.String2); + ASSERT_TRUE(*result.String2 == "foo"); + ASSERT_TRUE(!result.String3); ASSERT_TRUE(result.List1.empty()); ASSERT_TRUE(result.List2 == foobar); - ASSERT_TRUE(result.List3 == barfoo); + ASSERT_TRUE(result.List3); + ASSERT_TRUE(*result.List3 == barfoo); + ASSERT_TRUE(result.List4); + ASSERT_TRUE(result.List4->empty()); + ASSERT_TRUE(!result.List5); ASSERT_TRUE(result.Multi1.empty()); ASSERT_TRUE(result.Multi2.size() == 1); ASSERT_TRUE(result.Multi2[0].empty()); - ASSERT_TRUE(result.Multi3.size() == 2); - ASSERT_TRUE(result.Multi3[0] == foobar); - ASSERT_TRUE(result.Multi3[1] == barfoo); + ASSERT_TRUE(result.Multi3); + ASSERT_TRUE((*result.Multi3).size() == 2); + ASSERT_TRUE((*result.Multi3)[0] == foobar); + ASSERT_TRUE((*result.Multi3)[1] == barfoo); + ASSERT_TRUE(!result.Multi4); ASSERT_TRUE(unparsedArguments.size() == 1); ASSERT_TRUE(unparsedArguments[0] == "bar"); @@ -97,12 +116,16 @@ bool testArgumentParserDynamic() .Bind("OPTION_2"_s, result.Option2) .Bind("STRING_1"_s, result.String1) .Bind("STRING_2"_s, result.String2) + .Bind("STRING_3"_s, result.String3) .Bind("LIST_1"_s, result.List1) .Bind("LIST_2"_s, result.List2) .Bind("LIST_3"_s, result.List3) + .Bind("LIST_4"_s, result.List4) + .Bind("LIST_5"_s, result.List5) .Bind("MULTI_1"_s, result.Multi1) .Bind("MULTI_2"_s, result.Multi2) .Bind("MULTI_3"_s, result.Multi3) + .Bind("MULTI_4"_s, result.Multi4) .Parse(args, &unparsedArguments, &keywordsMissingValue); return verifyResult(result, unparsedArguments, keywordsMissingValue); @@ -116,12 +139,16 @@ bool testArgumentParserStatic() .Bind("OPTION_2"_s, &Result::Option2) .Bind("STRING_1"_s, &Result::String1) .Bind("STRING_2"_s, &Result::String2) + .Bind("STRING_3"_s, &Result::String3) .Bind("LIST_1"_s, &Result::List1) .Bind("LIST_2"_s, &Result::List2) .Bind("LIST_3"_s, &Result::List3) + .Bind("LIST_4"_s, &Result::List4) + .Bind("LIST_5"_s, &Result::List5) .Bind("MULTI_1"_s, &Result::Multi1) .Bind("MULTI_2"_s, &Result::Multi2) - .Bind("MULTI_3"_s, &Result::Multi3); + .Bind("MULTI_3"_s, &Result::Multi3) + .Bind("MULTI_4"_s, &Result::Multi4); std::vector<std::string> unparsedArguments; std::vector<cm::string_view> keywordsMissingValue; |