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 | 1457 | class ParseResult |
| 1458 | 1458 | { |
| 1459 | 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 | 1521 | ParseResult() = default; |
| 1462 | 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 | 1526 | : m_keys(std::move(keys)) |
| 1466 | 1527 | , m_values(std::move(values)) |
| 1467 | 1528 | , m_sequential(std::move(sequential)) |
| 1529 | + , m_defaults(std::move(default_opts)) | |
| 1468 | 1530 | , m_unmatched(std::move(unmatched_args)) |
| 1469 | 1531 | { |
| 1470 | 1532 | } |
| ... | ... | @@ -1472,6 +1534,18 @@ namespace cxxopts |
| 1472 | 1534 | ParseResult& operator=(ParseResult&&) = default; |
| 1473 | 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 | 1549 | size_t |
| 1476 | 1550 | count(const std::string& o) const |
| 1477 | 1551 | { |
| ... | ... | @@ -1523,10 +1597,32 @@ namespace cxxopts |
| 1523 | 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 | 1621 | private: |
| 1527 | 1622 | NameHashMap m_keys{}; |
| 1528 | 1623 | ParsedHashMap m_values{}; |
| 1529 | 1624 | std::vector<KeyValue> m_sequential{}; |
| 1625 | + std::vector<KeyValue> m_defaults{}; | |
| 1530 | 1626 | std::vector<std::string> m_unmatched{}; |
| 1531 | 1627 | }; |
| 1532 | 1628 | |
| ... | ... | @@ -1607,6 +1703,7 @@ namespace cxxopts |
| 1607 | 1703 | const PositionalList& m_positional; |
| 1608 | 1704 | |
| 1609 | 1705 | std::vector<KeyValue> m_sequential{}; |
| 1706 | + std::vector<KeyValue> m_defaults{}; | |
| 1610 | 1707 | bool m_allow_unrecognised; |
| 1611 | 1708 | |
| 1612 | 1709 | ParsedHashMap m_parsed{}; |
| ... | ... | @@ -2053,6 +2150,7 @@ OptionParser::parse_default(const std::shared_ptr<OptionDetails>& details) |
| 2053 | 2150 | // TODO: remove the duplicate code here |
| 2054 | 2151 | auto& store = m_parsed[details->hash()]; |
| 2055 | 2152 | store.parse_default(details); |
| 2153 | + m_defaults.emplace_back(details->long_name(), details->value().get_default_value()); | |
| 2056 | 2154 | } |
| 2057 | 2155 | |
| 2058 | 2156 | inline |
| ... | ... | @@ -2350,7 +2448,7 @@ OptionParser::parse(int argc, const char* const* argv) |
| 2350 | 2448 | |
| 2351 | 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 | 2452 | return parsed; |
| 2355 | 2453 | } |
| 2356 | 2454 | ... | ... |
src/example.cpp
| ... | ... | @@ -63,6 +63,8 @@ parse(int argc, const char* argv[]) |
| 63 | 63 | ("float", "A floating point number", cxxopts::value<float>()) |
| 64 | 64 | ("vector", "A list of doubles", cxxopts::value<std::vector<double>>()) |
| 65 | 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 | 68 | #ifdef CXXOPTS_USE_UNICODE |
| 67 | 69 | ("unicode", u8"A help option with non-ascii: à. Here the size of the" |
| 68 | 70 | " string should be correct") |
| ... | ... | @@ -83,6 +85,22 @@ parse(int argc, const char* argv[]) |
| 83 | 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 | 104 | if (apple) |
| 87 | 105 | { |
| 88 | 106 | std::cout << "Saw option ‘a’ " << result.count("a") << " times " << | ... | ... |