diff options
author | Long Deng <37360259+ldeng-ustc@users.noreply.github.com> | 2021-11-09 10:49:58 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-09 10:49:58 +0300 |
commit | ad2d1a6b5fd3fbb7bb0e7bc11f28a427494aea45 (patch) | |
tree | 17afc4a2a1d01f1de3e00be8bd23b464e4bd02c0 | |
parent | c74846a891b3cc3bfa992d588b1295f528d43039 (diff) |
Add iterator (#126) and easily print-out (#223) to ParseResult (#313)
* Add iterator (#126) and easily print-out (#223) to ParseResult
-rw-r--r-- | include/cxxopts.hpp | 102 | ||||
-rw-r--r-- | src/example.cpp | 18 |
2 files changed, 118 insertions, 2 deletions
diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index 12456a7..d247ba7 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -1457,14 +1457,76 @@ namespace cxxopts class ParseResult { public: + class Iterator + { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = KeyValue; + using difference_type = void; + using pointer = const KeyValue*; + using reference = const KeyValue&; + + Iterator() = default; + Iterator(const Iterator&) = default; + + Iterator(const ParseResult *pr, bool end=false) + : m_pr(pr) + , m_iter(end? pr->m_defaults.end(): pr->m_sequential.begin()) + { + } + + Iterator& operator++() + { + ++m_iter; + if(m_iter == m_pr->m_sequential.end()) + { + m_iter = m_pr->m_defaults.begin(); + return *this; + } + return *this; + } + + Iterator operator++(int) + { + Iterator retval = *this; + ++(*this); + return retval; + } + + bool operator==(const Iterator& other) const + { + return m_iter == other.m_iter; + } + + bool operator!=(const Iterator& other) const + { + return !(*this == other); + } + + const KeyValue& operator*() + { + return *m_iter; + } + + const KeyValue* operator->() + { + return m_iter.operator->(); + } + + private: + const ParseResult* m_pr; + std::vector<KeyValue>::const_iterator m_iter; + }; ParseResult() = default; ParseResult(const ParseResult&) = default; - ParseResult(NameHashMap&& keys, ParsedHashMap&& values, std::vector<KeyValue> sequential, std::vector<std::string>&& unmatched_args) + ParseResult(NameHashMap&& keys, ParsedHashMap&& values, std::vector<KeyValue> sequential, + std::vector<KeyValue> default_opts, std::vector<std::string>&& unmatched_args) : m_keys(std::move(keys)) , m_values(std::move(values)) , m_sequential(std::move(sequential)) + , m_defaults(std::move(default_opts)) , m_unmatched(std::move(unmatched_args)) { } @@ -1472,6 +1534,18 @@ namespace cxxopts ParseResult& operator=(ParseResult&&) = default; ParseResult& operator=(const ParseResult&) = default; + Iterator + begin() const + { + return Iterator(this); + } + + Iterator + end() const + { + return Iterator(this, true); + } + size_t count(const std::string& o) const { @@ -1523,10 +1597,32 @@ namespace cxxopts return m_unmatched; } + const std::vector<KeyValue>& + defaults() const + { + return m_defaults; + } + + const std::string + arguments_string() const + { + std::string result; + for(const auto& kv: m_sequential) + { + result += kv.key() + " = " + kv.value() + "\n"; + } + for(const auto& kv: m_defaults) + { + result += kv.key() + " = " + kv.value() + " " + "(default)" + "\n"; + } + return result; + } + private: NameHashMap m_keys{}; ParsedHashMap m_values{}; std::vector<KeyValue> m_sequential{}; + std::vector<KeyValue> m_defaults{}; std::vector<std::string> m_unmatched{}; }; @@ -1607,6 +1703,7 @@ namespace cxxopts const PositionalList& m_positional; std::vector<KeyValue> m_sequential{}; + std::vector<KeyValue> m_defaults{}; bool m_allow_unrecognised; ParsedHashMap m_parsed{}; @@ -2053,6 +2150,7 @@ OptionParser::parse_default(const std::shared_ptr<OptionDetails>& details) // TODO: remove the duplicate code here auto& store = m_parsed[details->hash()]; store.parse_default(details); + m_defaults.emplace_back(details->long_name(), details->value().get_default_value()); } inline @@ -2350,7 +2448,7 @@ OptionParser::parse(int argc, const char* const* argv) finalise_aliases(); - ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(unmatched)); + ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(m_defaults), std::move(unmatched)); return parsed; } diff --git a/src/example.cpp b/src/example.cpp index c21bad6..420220e 100644 --- a/src/example.cpp +++ b/src/example.cpp @@ -63,6 +63,8 @@ parse(int argc, const char* argv[]) ("float", "A floating point number", cxxopts::value<float>()) ("vector", "A list of doubles", cxxopts::value<std::vector<double>>()) ("option_that_is_too_long_for_the_help", "A very long option") + ("l,list", "List all parsed arguments (including default values)") + ("range", "Use range-for to list arguments") #ifdef CXXOPTS_USE_UNICODE ("unicode", u8"A help option with non-ascii: à. Here the size of the" " string should be correct") @@ -83,6 +85,22 @@ parse(int argc, const char* argv[]) exit(0); } + if(result.count("list")) + { + if(result.count("range")) + { + for(const auto &kv: result) + { + std::cout << kv.key() << " = " << kv.value() << std::endl; + } + } + else + { + std::cout << result.arguments_string() << std::endl; + } + exit(0); + } + if (apple) { std::cout << "Saw option ‘a’ " << result.count("a") << " times " << |