Commit ad2d1a6b5fd3fbb7bb0e7bc11f28a427494aea45

Authored by Long Deng
Committed by GitHub
1 parent c74846a8

Add iterator (#126) and easily print-out (#223) to ParseResult (#313)

* Add iterator (#126) and easily print-out (#223) to ParseResult
include/cxxopts.hpp
@@ -1457,14 +1457,76 @@ namespace cxxopts @@ -1457,14 +1457,76 @@ namespace cxxopts
1457 class ParseResult 1457 class ParseResult
1458 { 1458 {
1459 public: 1459 public:
  1460 + class Iterator
  1461 + {
  1462 + public:
  1463 + using iterator_category = std::forward_iterator_tag;
  1464 + using value_type = KeyValue;
  1465 + using difference_type = void;
  1466 + using pointer = const KeyValue*;
  1467 + using reference = const KeyValue&;
  1468 +
  1469 + Iterator() = default;
  1470 + Iterator(const Iterator&) = default;
  1471 +
  1472 + Iterator(const ParseResult *pr, bool end=false)
  1473 + : m_pr(pr)
  1474 + , m_iter(end? pr->m_defaults.end(): pr->m_sequential.begin())
  1475 + {
  1476 + }
  1477 +
  1478 + Iterator& operator++()
  1479 + {
  1480 + ++m_iter;
  1481 + if(m_iter == m_pr->m_sequential.end())
  1482 + {
  1483 + m_iter = m_pr->m_defaults.begin();
  1484 + return *this;
  1485 + }
  1486 + return *this;
  1487 + }
  1488 +
  1489 + Iterator operator++(int)
  1490 + {
  1491 + Iterator retval = *this;
  1492 + ++(*this);
  1493 + return retval;
  1494 + }
  1495 +
  1496 + bool operator==(const Iterator& other) const
  1497 + {
  1498 + return m_iter == other.m_iter;
  1499 + }
  1500 +
  1501 + bool operator!=(const Iterator& other) const
  1502 + {
  1503 + return !(*this == other);
  1504 + }
  1505 +
  1506 + const KeyValue& operator*()
  1507 + {
  1508 + return *m_iter;
  1509 + }
  1510 +
  1511 + const KeyValue* operator->()
  1512 + {
  1513 + return m_iter.operator->();
  1514 + }
  1515 +
  1516 + private:
  1517 + const ParseResult* m_pr;
  1518 + std::vector<KeyValue>::const_iterator m_iter;
  1519 + };
1460 1520
1461 ParseResult() = default; 1521 ParseResult() = default;
1462 ParseResult(const ParseResult&) = default; 1522 ParseResult(const ParseResult&) = default;
1463 1523
1464 - ParseResult(NameHashMap&& keys, ParsedHashMap&& values, std::vector<KeyValue> sequential, std::vector<std::string>&& unmatched_args) 1524 + ParseResult(NameHashMap&& keys, ParsedHashMap&& values, std::vector<KeyValue> sequential,
  1525 + std::vector<KeyValue> default_opts, std::vector<std::string>&& unmatched_args)
1465 : m_keys(std::move(keys)) 1526 : m_keys(std::move(keys))
1466 , m_values(std::move(values)) 1527 , m_values(std::move(values))
1467 , m_sequential(std::move(sequential)) 1528 , m_sequential(std::move(sequential))
  1529 + , m_defaults(std::move(default_opts))
1468 , m_unmatched(std::move(unmatched_args)) 1530 , m_unmatched(std::move(unmatched_args))
1469 { 1531 {
1470 } 1532 }
@@ -1472,6 +1534,18 @@ namespace cxxopts @@ -1472,6 +1534,18 @@ namespace cxxopts
1472 ParseResult& operator=(ParseResult&&) = default; 1534 ParseResult& operator=(ParseResult&&) = default;
1473 ParseResult& operator=(const ParseResult&) = default; 1535 ParseResult& operator=(const ParseResult&) = default;
1474 1536
  1537 + Iterator
  1538 + begin() const
  1539 + {
  1540 + return Iterator(this);
  1541 + }
  1542 +
  1543 + Iterator
  1544 + end() const
  1545 + {
  1546 + return Iterator(this, true);
  1547 + }
  1548 +
1475 size_t 1549 size_t
1476 count(const std::string& o) const 1550 count(const std::string& o) const
1477 { 1551 {
@@ -1523,10 +1597,32 @@ namespace cxxopts @@ -1523,10 +1597,32 @@ namespace cxxopts
1523 return m_unmatched; 1597 return m_unmatched;
1524 } 1598 }
1525 1599
  1600 + const std::vector<KeyValue>&
  1601 + defaults() const
  1602 + {
  1603 + return m_defaults;
  1604 + }
  1605 +
  1606 + const std::string
  1607 + arguments_string() const
  1608 + {
  1609 + std::string result;
  1610 + for(const auto& kv: m_sequential)
  1611 + {
  1612 + result += kv.key() + " = " + kv.value() + "\n";
  1613 + }
  1614 + for(const auto& kv: m_defaults)
  1615 + {
  1616 + result += kv.key() + " = " + kv.value() + " " + "(default)" + "\n";
  1617 + }
  1618 + return result;
  1619 + }
  1620 +
1526 private: 1621 private:
1527 NameHashMap m_keys{}; 1622 NameHashMap m_keys{};
1528 ParsedHashMap m_values{}; 1623 ParsedHashMap m_values{};
1529 std::vector<KeyValue> m_sequential{}; 1624 std::vector<KeyValue> m_sequential{};
  1625 + std::vector<KeyValue> m_defaults{};
1530 std::vector<std::string> m_unmatched{}; 1626 std::vector<std::string> m_unmatched{};
1531 }; 1627 };
1532 1628
@@ -1607,6 +1703,7 @@ namespace cxxopts @@ -1607,6 +1703,7 @@ namespace cxxopts
1607 const PositionalList& m_positional; 1703 const PositionalList& m_positional;
1608 1704
1609 std::vector<KeyValue> m_sequential{}; 1705 std::vector<KeyValue> m_sequential{};
  1706 + std::vector<KeyValue> m_defaults{};
1610 bool m_allow_unrecognised; 1707 bool m_allow_unrecognised;
1611 1708
1612 ParsedHashMap m_parsed{}; 1709 ParsedHashMap m_parsed{};
@@ -2053,6 +2150,7 @@ OptionParser::parse_default(const std::shared_ptr&lt;OptionDetails&gt;&amp; details) @@ -2053,6 +2150,7 @@ OptionParser::parse_default(const std::shared_ptr&lt;OptionDetails&gt;&amp; details)
2053 // TODO: remove the duplicate code here 2150 // TODO: remove the duplicate code here
2054 auto& store = m_parsed[details->hash()]; 2151 auto& store = m_parsed[details->hash()];
2055 store.parse_default(details); 2152 store.parse_default(details);
  2153 + m_defaults.emplace_back(details->long_name(), details->value().get_default_value());
2056 } 2154 }
2057 2155
2058 inline 2156 inline
@@ -2350,7 +2448,7 @@ OptionParser::parse(int argc, const char* const* argv) @@ -2350,7 +2448,7 @@ OptionParser::parse(int argc, const char* const* argv)
2350 2448
2351 finalise_aliases(); 2449 finalise_aliases();
2352 2450
2353 - ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(unmatched)); 2451 + ParseResult parsed(std::move(m_keys), std::move(m_parsed), std::move(m_sequential), std::move(m_defaults), std::move(unmatched));
2354 return parsed; 2452 return parsed;
2355 } 2453 }
2356 2454
src/example.cpp
@@ -63,6 +63,8 @@ parse(int argc, const char* argv[]) @@ -63,6 +63,8 @@ parse(int argc, const char* argv[])
63 ("float", "A floating point number", cxxopts::value<float>()) 63 ("float", "A floating point number", cxxopts::value<float>())
64 ("vector", "A list of doubles", cxxopts::value<std::vector<double>>()) 64 ("vector", "A list of doubles", cxxopts::value<std::vector<double>>())
65 ("option_that_is_too_long_for_the_help", "A very long option") 65 ("option_that_is_too_long_for_the_help", "A very long option")
  66 + ("l,list", "List all parsed arguments (including default values)")
  67 + ("range", "Use range-for to list arguments")
66 #ifdef CXXOPTS_USE_UNICODE 68 #ifdef CXXOPTS_USE_UNICODE
67 ("unicode", u8"A help option with non-ascii: à. Here the size of the" 69 ("unicode", u8"A help option with non-ascii: à. Here the size of the"
68 " string should be correct") 70 " string should be correct")
@@ -83,6 +85,22 @@ parse(int argc, const char* argv[]) @@ -83,6 +85,22 @@ parse(int argc, const char* argv[])
83 exit(0); 85 exit(0);
84 } 86 }
85 87
  88 + if(result.count("list"))
  89 + {
  90 + if(result.count("range"))
  91 + {
  92 + for(const auto &kv: result)
  93 + {
  94 + std::cout << kv.key() << " = " << kv.value() << std::endl;
  95 + }
  96 + }
  97 + else
  98 + {
  99 + std::cout << result.arguments_string() << std::endl;
  100 + }
  101 + exit(0);
  102 + }
  103 +
86 if (apple) 104 if (apple)
87 { 105 {
88 std::cout << "Saw option ‘a’ " << result.count("a") << " times " << 106 std::cout << "Saw option ‘a’ " << result.count("a") << " times " <<