1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
5 #include "cmConfigure.h" // IWYU pragma: keep
13 #include <cm/string_view>
14 #include <cmext/string_view>
16 namespace ArgumentParser {
18 using StringList = std::vector<std::string>;
19 using MultiStringList = std::vector<StringList>;
22 using Action = std::function<void(Instance&, void*)>;
24 // using ActionMap = cm::flat_map<cm::string_view, Action>;
25 class ActionMap : public std::vector<std::pair<cm::string_view, Action>>
28 std::pair<iterator, bool> Emplace(cm::string_view name, Action action);
29 const_iterator Find(cm::string_view name) const;
35 Instance(ActionMap const& bindings)
41 void Bind(std::string& val);
42 void Bind(StringList& val);
43 void Bind(MultiStringList& val);
45 void Consume(cm::string_view arg, void* result,
46 std::vector<std::string>* unparsedArguments,
47 std::vector<std::string>* keywordsMissingValue,
48 std::vector<std::string>* parsedKeywords);
51 ActionMap const& Bindings;
52 std::string* CurrentString = nullptr;
53 StringList* CurrentList = nullptr;
54 bool ExpectValue = false;
57 } // namespace ArgumentParser
59 template <typename Result>
60 class cmArgumentParser
63 // I *think* this function could be made `constexpr` when the code is
64 // compiled as C++20. This would allow building a parser at compile time.
66 cmArgumentParser& Bind(cm::static_string_view name, T Result::*member)
71 [member](ArgumentParser::Instance& instance, void* result) {
72 instance.Bind(static_cast<Result*>(result)->*member);
75 assert(inserted), (void)inserted;
79 template <typename Range>
80 void Parse(Result& result, Range const& args,
81 std::vector<std::string>* unparsedArguments = nullptr,
82 std::vector<std::string>* keywordsMissingValue = nullptr,
83 std::vector<std::string>* parsedKeywords = nullptr) const
85 ArgumentParser::Instance instance(this->Bindings);
86 for (cm::string_view arg : args) {
87 instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue,
92 template <typename Range>
93 Result Parse(Range const& args,
94 std::vector<std::string>* unparsedArguments = nullptr,
95 std::vector<std::string>* keywordsMissingValue = nullptr,
96 std::vector<std::string>* parsedKeywords = nullptr) const
99 this->Parse(result, args, unparsedArguments, keywordsMissingValue,
105 ArgumentParser::ActionMap Bindings;
109 class cmArgumentParser<void>
112 template <typename T>
113 cmArgumentParser& Bind(cm::static_string_view name, T& ref)
115 bool const inserted = this->Bind(cm::string_view(name), ref);
116 assert(inserted), (void)inserted;
120 template <typename Range>
121 void Parse(Range const& args,
122 std::vector<std::string>* unparsedArguments = nullptr,
123 std::vector<std::string>* keywordsMissingValue = nullptr,
124 std::vector<std::string>* parsedKeywords = nullptr) const
126 ArgumentParser::Instance instance(this->Bindings);
127 for (cm::string_view arg : args) {
128 instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue,
134 template <typename T>
135 bool Bind(cm::string_view name, T& ref)
137 return this->Bindings
139 [&ref](ArgumentParser::Instance& instance, void*) {
146 ArgumentParser::ActionMap Bindings;