Commit ad2d1a6b5fd3fbb7bb0e7bc11f28a427494aea45
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
Showing
2 changed files
with
118 additions
and
2 deletions
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<OptionDetails>& details) | @@ -2053,6 +2150,7 @@ OptionParser::parse_default(const std::shared_ptr<OptionDetails>& 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 " << |