Commit c04f8a5bb9cabc552e690d8277d4939544813304
Committed by
GitHub
1 parent
17451028
Fully compatible with GCC4.8 compilation system. (#285)
* -Wsuggest-override is not supported by gcc before 5.0 * GCC prior to 5.0 should ignore not only -Wnon-virtual-dtor but also -Weffc++, otherwise non-virtual destructor problems will still be reported. * The `#pragma GCC diagnostic push' should be used before setting up the temporary environment. * When using GCC4.8, use manual lexical analysis instead of regular expressions. * Add gcc4.8 stuff to travis file.
Showing
2 changed files
with
318 additions
and
71 deletions
.travis.yml
| @@ -51,6 +51,20 @@ matrix: | @@ -51,6 +51,20 @@ matrix: | ||
| 51 | - g++-5 | 51 | - g++-5 |
| 52 | sources: *sources | 52 | sources: *sources |
| 53 | - os: linux | 53 | - os: linux |
| 54 | + env: COMPILER=g++-4.8 | ||
| 55 | + addons: | ||
| 56 | + apt: | ||
| 57 | + packages: | ||
| 58 | + - g++-4.8 | ||
| 59 | + sources: *sources | ||
| 60 | + - os: linux | ||
| 61 | + env: COMPILER=g++-4.8 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes | ||
| 62 | + addons: | ||
| 63 | + apt: | ||
| 64 | + packages: | ||
| 65 | + - g++-4.8 | ||
| 66 | + sources: *sources | ||
| 67 | + - os: linux | ||
| 54 | env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++ | 68 | env: COMPILER=clang++-3.8 CXXFLAGS=-stdlib=libc++ |
| 55 | addons: | 69 | addons: |
| 56 | apt: | 70 | apt: |
include/cxxopts.hpp
| @@ -33,13 +33,23 @@ THE SOFTWARE. | @@ -33,13 +33,23 @@ THE SOFTWARE. | ||
| 33 | #include <list> | 33 | #include <list> |
| 34 | #include <map> | 34 | #include <map> |
| 35 | #include <memory> | 35 | #include <memory> |
| 36 | -#include <regex> | ||
| 37 | #include <sstream> | 36 | #include <sstream> |
| 38 | #include <string> | 37 | #include <string> |
| 39 | #include <unordered_map> | 38 | #include <unordered_map> |
| 40 | #include <unordered_set> | 39 | #include <unordered_set> |
| 41 | #include <utility> | 40 | #include <utility> |
| 42 | #include <vector> | 41 | #include <vector> |
| 42 | +#include <algorithm> | ||
| 43 | + | ||
| 44 | +#if defined(__GNUC__) && !defined(__clang__) | ||
| 45 | +# if (__GNUC__ * 10 + __GNUC_MINOR__) < 49 | ||
| 46 | +# define CXXOPTS_NO_REGEX true | ||
| 47 | +# endif | ||
| 48 | +#endif | ||
| 49 | + | ||
| 50 | +#ifndef CXXOPTS_NO_REGEX | ||
| 51 | +# include <regex> | ||
| 52 | +#endif // CXXOPTS_NO_REGEX | ||
| 43 | 53 | ||
| 44 | #ifdef __cpp_lib_optional | 54 | #ifdef __cpp_lib_optional |
| 45 | #include <optional> | 55 | #include <optional> |
| @@ -91,6 +101,14 @@ namespace cxxopts | @@ -91,6 +101,14 @@ namespace cxxopts | ||
| 91 | return icu::UnicodeString::fromUTF8(std::move(s)); | 101 | return icu::UnicodeString::fromUTF8(std::move(s)); |
| 92 | } | 102 | } |
| 93 | 103 | ||
| 104 | +#if defined(__GNUC__) | ||
| 105 | +// GNU GCC with -Weffc++ will issue a warning regarding the upcoming class, we want to silence it: | ||
| 106 | +// warning: base class 'class std::enable_shared_from_this<cxxopts::Value>' has accessible non-virtual destructor | ||
| 107 | +#pragma GCC diagnostic push | ||
| 108 | +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" | ||
| 109 | +#pragma GCC diagnostic ignored "-Weffc++" | ||
| 110 | +// This will be ignored under other compilers like LLVM clang. | ||
| 111 | +#endif | ||
| 94 | class UnicodeStringIterator : public | 112 | class UnicodeStringIterator : public |
| 95 | std::iterator<std::forward_iterator_tag, int32_t> | 113 | std::iterator<std::forward_iterator_tag, int32_t> |
| 96 | { | 114 | { |
| @@ -137,6 +155,9 @@ namespace cxxopts | @@ -137,6 +155,9 @@ namespace cxxopts | ||
| 137 | const icu::UnicodeString* s; | 155 | const icu::UnicodeString* s; |
| 138 | int32_t i; | 156 | int32_t i; |
| 139 | }; | 157 | }; |
| 158 | +#if defined(__GNUC__) | ||
| 159 | +#pragma GCC diagnostic pop | ||
| 160 | +#endif | ||
| 140 | 161 | ||
| 141 | inline | 162 | inline |
| 142 | String& | 163 | String& |
| @@ -519,15 +540,257 @@ namespace cxxopts | @@ -519,15 +540,257 @@ namespace cxxopts | ||
| 519 | 540 | ||
| 520 | namespace values | 541 | namespace values |
| 521 | { | 542 | { |
| 522 | - namespace | 543 | + namespace parser_tool |
| 523 | { | 544 | { |
| 524 | - std::basic_regex<char> integer_pattern | ||
| 525 | - ("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)"); | ||
| 526 | - std::basic_regex<char> truthy_pattern | ||
| 527 | - ("(t|T)(rue)?|1"); | ||
| 528 | - std::basic_regex<char> falsy_pattern | ||
| 529 | - ("(f|F)(alse)?|0"); | ||
| 530 | - } // namespace | 545 | + struct IntegerDesc |
| 546 | + { | ||
| 547 | + std::string negative = ""; | ||
| 548 | + std::string base = ""; | ||
| 549 | + std::string value = ""; | ||
| 550 | + }; | ||
| 551 | + struct ArguDesc { | ||
| 552 | + std::string arg_name = ""; | ||
| 553 | + bool grouping = false; | ||
| 554 | + bool set_value = false; | ||
| 555 | + std::string value = ""; | ||
| 556 | + }; | ||
| 557 | +#ifdef CXXOPTS_NO_REGEX | ||
| 558 | + inline IntegerDesc SplitInteger(const std::string &text) | ||
| 559 | + { | ||
| 560 | + if (text.empty()) | ||
| 561 | + { | ||
| 562 | + throw_or_mimic<argument_incorrect_type>(text); | ||
| 563 | + } | ||
| 564 | + IntegerDesc desc; | ||
| 565 | + const char *pdata = text.c_str(); | ||
| 566 | + if (*pdata == '-') | ||
| 567 | + { | ||
| 568 | + pdata += 1; | ||
| 569 | + desc.negative = "-"; | ||
| 570 | + } | ||
| 571 | + if (strncmp(pdata, "0x", 2) == 0) | ||
| 572 | + { | ||
| 573 | + pdata += 2; | ||
| 574 | + desc.base = "0x"; | ||
| 575 | + } | ||
| 576 | + if (*pdata != '\0') | ||
| 577 | + { | ||
| 578 | + desc.value = std::string(pdata); | ||
| 579 | + } | ||
| 580 | + else | ||
| 581 | + { | ||
| 582 | + throw_or_mimic<argument_incorrect_type>(text); | ||
| 583 | + } | ||
| 584 | + return desc; | ||
| 585 | + } | ||
| 586 | + | ||
| 587 | + inline bool IsTrueText(const std::string &text) | ||
| 588 | + { | ||
| 589 | + const char *pdata = text.c_str(); | ||
| 590 | + if (*pdata == 't' || *pdata == 'T') | ||
| 591 | + { | ||
| 592 | + pdata += 1; | ||
| 593 | + if (strncmp(pdata, "rue\0", 4) == 0) | ||
| 594 | + { | ||
| 595 | + return true; | ||
| 596 | + } | ||
| 597 | + } | ||
| 598 | + else if (strncmp(pdata, "1\0", 2) == 0) | ||
| 599 | + { | ||
| 600 | + return true; | ||
| 601 | + } | ||
| 602 | + return false; | ||
| 603 | + } | ||
| 604 | + | ||
| 605 | + inline bool IsFalseText(const std::string &text) | ||
| 606 | + { | ||
| 607 | + const char *pdata = text.c_str(); | ||
| 608 | + if (*pdata == 'f' || *pdata == 'F') | ||
| 609 | + { | ||
| 610 | + pdata += 1; | ||
| 611 | + if (strncmp(pdata, "alse\0", 5) == 0) | ||
| 612 | + { | ||
| 613 | + return true; | ||
| 614 | + } | ||
| 615 | + } | ||
| 616 | + else if (strncmp(pdata, "0\0", 2) == 0) | ||
| 617 | + { | ||
| 618 | + return true; | ||
| 619 | + } | ||
| 620 | + return false; | ||
| 621 | + } | ||
| 622 | + | ||
| 623 | + inline std::pair<std::string, std::string> SplitSwitchDef(const std::string &text) | ||
| 624 | + { | ||
| 625 | + std::string short_sw, long_sw; | ||
| 626 | + const char *pdata = text.c_str(); | ||
| 627 | + if (isalnum(*pdata) && *(pdata + 1) == ',') { | ||
| 628 | + short_sw = std::string(1, *pdata); | ||
| 629 | + pdata += 2; | ||
| 630 | + } | ||
| 631 | + while (*pdata == ' ') { pdata += 1; } | ||
| 632 | + if (isalnum(*pdata)) { | ||
| 633 | + const char *store = pdata; | ||
| 634 | + pdata += 1; | ||
| 635 | + while (isalnum(*pdata) || *pdata == '-' || *pdata == '_') { | ||
| 636 | + pdata += 1; | ||
| 637 | + } | ||
| 638 | + if (*pdata == '\0') { | ||
| 639 | + long_sw = std::string(store, pdata - store); | ||
| 640 | + } else { | ||
| 641 | + throw_or_mimic<invalid_option_format_error>(text); | ||
| 642 | + } | ||
| 643 | + } | ||
| 644 | + return std::pair<std::string, std::string>(short_sw, long_sw); | ||
| 645 | + } | ||
| 646 | + | ||
| 647 | + inline ArguDesc ParseArgument(const char *arg, bool &matched) | ||
| 648 | + { | ||
| 649 | + ArguDesc argu_desc; | ||
| 650 | + const char *pdata = arg; | ||
| 651 | + matched = false; | ||
| 652 | + if (strncmp(pdata, "--", 2) == 0) | ||
| 653 | + { | ||
| 654 | + pdata += 2; | ||
| 655 | + if (isalnum(*pdata)) | ||
| 656 | + { | ||
| 657 | + argu_desc.arg_name.push_back(*pdata); | ||
| 658 | + pdata += 1; | ||
| 659 | + while (isalnum(*pdata) || *pdata == '-' || *pdata == '_') | ||
| 660 | + { | ||
| 661 | + argu_desc.arg_name.push_back(*pdata); | ||
| 662 | + pdata += 1; | ||
| 663 | + } | ||
| 664 | + if (argu_desc.arg_name.length() > 1) | ||
| 665 | + { | ||
| 666 | + if (*pdata == '=') | ||
| 667 | + { | ||
| 668 | + argu_desc.set_value = true; | ||
| 669 | + pdata += 1; | ||
| 670 | + if (*pdata != '\0') | ||
| 671 | + { | ||
| 672 | + argu_desc.value = std::string(pdata); | ||
| 673 | + } | ||
| 674 | + matched = true; | ||
| 675 | + } | ||
| 676 | + else if (*pdata == '\0') | ||
| 677 | + { | ||
| 678 | + matched = true; | ||
| 679 | + } | ||
| 680 | + } | ||
| 681 | + } | ||
| 682 | + } | ||
| 683 | + else if (strncmp(pdata, "-", 1) == 0) | ||
| 684 | + { | ||
| 685 | + pdata += 1; | ||
| 686 | + argu_desc.grouping = true; | ||
| 687 | + while (isalnum(*pdata)) | ||
| 688 | + { | ||
| 689 | + argu_desc.arg_name.push_back(*pdata); | ||
| 690 | + pdata += 1; | ||
| 691 | + } | ||
| 692 | + matched = !argu_desc.arg_name.empty() && *pdata == '\0'; | ||
| 693 | + } | ||
| 694 | + return argu_desc; | ||
| 695 | + } | ||
| 696 | + | ||
| 697 | +#else // CXXOPTS_NO_REGEX | ||
| 698 | + | ||
| 699 | + namespace | ||
| 700 | + { | ||
| 701 | + | ||
| 702 | + std::basic_regex<char> integer_pattern | ||
| 703 | + ("(-)?(0x)?([0-9a-zA-Z]+)|((0x)?0)"); | ||
| 704 | + std::basic_regex<char> truthy_pattern | ||
| 705 | + ("(t|T)(rue)?|1"); | ||
| 706 | + std::basic_regex<char> falsy_pattern | ||
| 707 | + ("(f|F)(alse)?|0"); | ||
| 708 | + | ||
| 709 | + std::basic_regex<char> option_matcher | ||
| 710 | + ("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]+)"); | ||
| 711 | + std::basic_regex<char> option_specifier | ||
| 712 | + ("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?"); | ||
| 713 | + | ||
| 714 | + } // namespace | ||
| 715 | + | ||
| 716 | + inline IntegerDesc SplitInteger(const std::string &text) | ||
| 717 | + { | ||
| 718 | + std::smatch match; | ||
| 719 | + std::regex_match(text, match, integer_pattern); | ||
| 720 | + | ||
| 721 | + if (match.length() == 0) | ||
| 722 | + { | ||
| 723 | + throw_or_mimic<argument_incorrect_type>(text); | ||
| 724 | + } | ||
| 725 | + | ||
| 726 | + IntegerDesc desc; | ||
| 727 | + desc.negative = match[1]; | ||
| 728 | + desc.base = match[2]; | ||
| 729 | + desc.value = match[3]; | ||
| 730 | + | ||
| 731 | + if (match.length(4) > 0) | ||
| 732 | + { | ||
| 733 | + desc.base = match[5]; | ||
| 734 | + desc.value = "0"; | ||
| 735 | + return desc; | ||
| 736 | + } | ||
| 737 | + | ||
| 738 | + return desc; | ||
| 739 | + } | ||
| 740 | + | ||
| 741 | + inline bool IsTrueText(const std::string &text) | ||
| 742 | + { | ||
| 743 | + std::smatch result; | ||
| 744 | + std::regex_match(text, result, truthy_pattern); | ||
| 745 | + return !result.empty(); | ||
| 746 | + } | ||
| 747 | + | ||
| 748 | + inline bool IsFalseText(const std::string &text) | ||
| 749 | + { | ||
| 750 | + std::smatch result; | ||
| 751 | + std::regex_match(text, result, falsy_pattern); | ||
| 752 | + return !result.empty(); | ||
| 753 | + } | ||
| 754 | + | ||
| 755 | + inline std::pair<std::string, std::string> SplitSwitchDef(const std::string &text) | ||
| 756 | + { | ||
| 757 | + std::match_results<const char*> result; | ||
| 758 | + std::regex_match(text.c_str(), result, option_specifier); | ||
| 759 | + if (result.empty()) | ||
| 760 | + { | ||
| 761 | + throw_or_mimic<invalid_option_format_error>(text); | ||
| 762 | + } | ||
| 763 | + | ||
| 764 | + const std::string& short_sw = result[2]; | ||
| 765 | + const std::string& long_sw = result[3]; | ||
| 766 | + | ||
| 767 | + return std::pair<std::string, std::string>(short_sw, long_sw); | ||
| 768 | + } | ||
| 769 | + | ||
| 770 | + inline ArguDesc ParseArgument(const char *arg, bool &matched) | ||
| 771 | + { | ||
| 772 | + std::match_results<const char*> result; | ||
| 773 | + std::regex_match(arg, result, option_matcher); | ||
| 774 | + matched = !result.empty(); | ||
| 775 | + | ||
| 776 | + ArguDesc argu_desc; | ||
| 777 | + if (matched) { | ||
| 778 | + argu_desc.arg_name = result[1].str(); | ||
| 779 | + argu_desc.set_value = result[2].length() > 0; | ||
| 780 | + argu_desc.value = result[3].str(); | ||
| 781 | + if (result[4].length() > 0) | ||
| 782 | + { | ||
| 783 | + argu_desc.grouping = true; | ||
| 784 | + argu_desc.arg_name = result[4].str(); | ||
| 785 | + } | ||
| 786 | + } | ||
| 787 | + | ||
| 788 | + return argu_desc; | ||
| 789 | + } | ||
| 790 | + | ||
| 791 | +#endif // CXXOPTS_NO_REGEX | ||
| 792 | +#undef CXXOPTS_NO_REGEX | ||
| 793 | + } | ||
| 531 | 794 | ||
| 532 | namespace detail | 795 | namespace detail |
| 533 | { | 796 | { |
| @@ -595,45 +858,32 @@ namespace cxxopts | @@ -595,45 +858,32 @@ namespace cxxopts | ||
| 595 | void | 858 | void |
| 596 | integer_parser(const std::string& text, T& value) | 859 | integer_parser(const std::string& text, T& value) |
| 597 | { | 860 | { |
| 598 | - std::smatch match; | ||
| 599 | - std::regex_match(text, match, integer_pattern); | ||
| 600 | - | ||
| 601 | - if (match.length() == 0) | ||
| 602 | - { | ||
| 603 | - throw_or_mimic<argument_incorrect_type>(text); | ||
| 604 | - } | ||
| 605 | - | ||
| 606 | - if (match.length(4) > 0) | ||
| 607 | - { | ||
| 608 | - value = 0; | ||
| 609 | - return; | ||
| 610 | - } | 861 | + parser_tool::IntegerDesc int_desc = parser_tool::SplitInteger(text); |
| 611 | 862 | ||
| 612 | using US = typename std::make_unsigned<T>::type; | 863 | using US = typename std::make_unsigned<T>::type; |
| 613 | - | ||
| 614 | constexpr bool is_signed = std::numeric_limits<T>::is_signed; | 864 | constexpr bool is_signed = std::numeric_limits<T>::is_signed; |
| 615 | - const bool negative = match.length(1) > 0; | ||
| 616 | - const uint8_t base = match.length(2) > 0 ? 16 : 10; | ||
| 617 | 865 | ||
| 618 | - auto value_match = match[3]; | 866 | + const bool negative = int_desc.negative.length() > 0; |
| 867 | + const uint8_t base = int_desc.base.length() > 0 ? 16 : 10; | ||
| 868 | + const std::string & value_match = int_desc.value; | ||
| 619 | 869 | ||
| 620 | US result = 0; | 870 | US result = 0; |
| 621 | 871 | ||
| 622 | - for (auto iter = value_match.first; iter != value_match.second; ++iter) | 872 | + for (char ch : value_match) |
| 623 | { | 873 | { |
| 624 | US digit = 0; | 874 | US digit = 0; |
| 625 | 875 | ||
| 626 | - if (*iter >= '0' && *iter <= '9') | 876 | + if (ch >= '0' && ch <= '9') |
| 627 | { | 877 | { |
| 628 | - digit = static_cast<US>(*iter - '0'); | 878 | + digit = static_cast<US>(ch - '0'); |
| 629 | } | 879 | } |
| 630 | - else if (base == 16 && *iter >= 'a' && *iter <= 'f') | 880 | + else if (base == 16 && ch >= 'a' && ch <= 'f') |
| 631 | { | 881 | { |
| 632 | - digit = static_cast<US>(*iter - 'a' + 10); | 882 | + digit = static_cast<US>(ch - 'a' + 10); |
| 633 | } | 883 | } |
| 634 | - else if (base == 16 && *iter >= 'A' && *iter <= 'F') | 884 | + else if (base == 16 && ch >= 'A' && ch <= 'F') |
| 635 | { | 885 | { |
| 636 | - digit = static_cast<US>(*iter - 'A' + 10); | 886 | + digit = static_cast<US>(ch - 'A' + 10); |
| 637 | } | 887 | } |
| 638 | else | 888 | else |
| 639 | { | 889 | { |
| @@ -731,17 +981,13 @@ namespace cxxopts | @@ -731,17 +981,13 @@ namespace cxxopts | ||
| 731 | void | 981 | void |
| 732 | parse_value(const std::string& text, bool& value) | 982 | parse_value(const std::string& text, bool& value) |
| 733 | { | 983 | { |
| 734 | - std::smatch result; | ||
| 735 | - std::regex_match(text, result, truthy_pattern); | ||
| 736 | - | ||
| 737 | - if (!result.empty()) | 984 | + if (parser_tool::IsTrueText(text)) |
| 738 | { | 985 | { |
| 739 | value = true; | 986 | value = true; |
| 740 | return; | 987 | return; |
| 741 | } | 988 | } |
| 742 | 989 | ||
| 743 | - std::regex_match(text, result, falsy_pattern); | ||
| 744 | - if (!result.empty()) | 990 | + if (parser_tool::IsFalseText(text)) |
| 745 | { | 991 | { |
| 746 | value = false; | 992 | value = false; |
| 747 | return; | 993 | return; |
| @@ -1579,12 +1825,6 @@ namespace cxxopts | @@ -1579,12 +1825,6 @@ namespace cxxopts | ||
| 1579 | constexpr size_t OPTION_LONGEST = 30; | 1825 | constexpr size_t OPTION_LONGEST = 30; |
| 1580 | constexpr size_t OPTION_DESC_GAP = 2; | 1826 | constexpr size_t OPTION_DESC_GAP = 2; |
| 1581 | 1827 | ||
| 1582 | - std::basic_regex<char> option_matcher | ||
| 1583 | - ("--([[:alnum:]][-_[:alnum:]]+)(=(.*))?|-([[:alnum:]]+)"); | ||
| 1584 | - | ||
| 1585 | - std::basic_regex<char> option_specifier | ||
| 1586 | - ("(([[:alnum:]]),)?[ ]*([[:alnum:]][-_[:alnum:]]*)?"); | ||
| 1587 | - | ||
| 1588 | String | 1828 | String |
| 1589 | format_option | 1829 | format_option |
| 1590 | ( | 1830 | ( |
| @@ -1794,37 +2034,30 @@ OptionAdder::operator() | @@ -1794,37 +2034,30 @@ OptionAdder::operator() | ||
| 1794 | std::string arg_help | 2034 | std::string arg_help |
| 1795 | ) | 2035 | ) |
| 1796 | { | 2036 | { |
| 1797 | - std::match_results<const char*> result; | ||
| 1798 | - std::regex_match(opts.c_str(), result, option_specifier); | 2037 | + std::string short_sw, long_sw; |
| 2038 | + std::tie(short_sw, long_sw) = values::parser_tool::SplitSwitchDef(opts); | ||
| 1799 | 2039 | ||
| 1800 | - if (result.empty()) | 2040 | + if (!short_sw.length() && !long_sw.length()) |
| 1801 | { | 2041 | { |
| 1802 | throw_or_mimic<invalid_option_format_error>(opts); | 2042 | throw_or_mimic<invalid_option_format_error>(opts); |
| 1803 | } | 2043 | } |
| 1804 | - | ||
| 1805 | - const auto& short_match = result[2]; | ||
| 1806 | - const auto& long_match = result[3]; | ||
| 1807 | - | ||
| 1808 | - if (!short_match.length() && !long_match.length()) | ||
| 1809 | - { | ||
| 1810 | - throw_or_mimic<invalid_option_format_error>(opts); | ||
| 1811 | - } else if (long_match.length() == 1 && short_match.length()) | 2044 | + else if (long_sw.length() == 1 && short_sw.length()) |
| 1812 | { | 2045 | { |
| 1813 | throw_or_mimic<invalid_option_format_error>(opts); | 2046 | throw_or_mimic<invalid_option_format_error>(opts); |
| 1814 | } | 2047 | } |
| 1815 | 2048 | ||
| 1816 | auto option_names = [] | 2049 | auto option_names = [] |
| 1817 | ( | 2050 | ( |
| 1818 | - const std::sub_match<const char*>& short_, | ||
| 1819 | - const std::sub_match<const char*>& long_ | 2051 | + const std::string &short_, |
| 2052 | + const std::string &long_ | ||
| 1820 | ) | 2053 | ) |
| 1821 | { | 2054 | { |
| 1822 | if (long_.length() == 1) | 2055 | if (long_.length() == 1) |
| 1823 | { | 2056 | { |
| 1824 | - return std::make_tuple(long_.str(), short_.str()); | 2057 | + return std::make_tuple(long_, short_); |
| 1825 | } | 2058 | } |
| 1826 | - return std::make_tuple(short_.str(), long_.str()); | ||
| 1827 | - }(short_match, long_match); | 2059 | + return std::make_tuple(short_, long_); |
| 2060 | + }(short_sw, long_sw); | ||
| 1828 | 2061 | ||
| 1829 | m_options.add_option | 2062 | m_options.add_option |
| 1830 | ( | 2063 | ( |
| @@ -1986,11 +2219,11 @@ OptionParser::parse(int argc, const char* const* argv) | @@ -1986,11 +2219,11 @@ OptionParser::parse(int argc, const char* const* argv) | ||
| 1986 | ++current; | 2219 | ++current; |
| 1987 | break; | 2220 | break; |
| 1988 | } | 2221 | } |
| 2222 | + bool matched = false; | ||
| 2223 | + values::parser_tool::ArguDesc argu_desc = | ||
| 2224 | + values::parser_tool::ParseArgument(argv[current], matched); | ||
| 1989 | 2225 | ||
| 1990 | - std::match_results<const char*> result; | ||
| 1991 | - std::regex_match(argv[current], result, option_matcher); | ||
| 1992 | - | ||
| 1993 | - if (result.empty()) | 2226 | + if (!matched) |
| 1994 | { | 2227 | { |
| 1995 | //not a flag | 2228 | //not a flag |
| 1996 | 2229 | ||
| @@ -2015,9 +2248,9 @@ OptionParser::parse(int argc, const char* const* argv) | @@ -2015,9 +2248,9 @@ OptionParser::parse(int argc, const char* const* argv) | ||
| 2015 | else | 2248 | else |
| 2016 | { | 2249 | { |
| 2017 | //short or long option? | 2250 | //short or long option? |
| 2018 | - if (result[4].length() != 0) | 2251 | + if (argu_desc.grouping) |
| 2019 | { | 2252 | { |
| 2020 | - const std::string& s = result[4]; | 2253 | + const std::string& s = argu_desc.arg_name; |
| 2021 | 2254 | ||
| 2022 | for (std::size_t i = 0; i != s.size(); ++i) | 2255 | for (std::size_t i = 0; i != s.size(); ++i) |
| 2023 | { | 2256 | { |
| @@ -2052,9 +2285,9 @@ OptionParser::parse(int argc, const char* const* argv) | @@ -2052,9 +2285,9 @@ OptionParser::parse(int argc, const char* const* argv) | ||
| 2052 | } | 2285 | } |
| 2053 | } | 2286 | } |
| 2054 | } | 2287 | } |
| 2055 | - else if (result[1].length() != 0) | 2288 | + else if (argu_desc.arg_name.length() != 0) |
| 2056 | { | 2289 | { |
| 2057 | - const std::string& name = result[1]; | 2290 | + const std::string& name = argu_desc.arg_name; |
| 2058 | 2291 | ||
| 2059 | auto iter = m_options.find(name); | 2292 | auto iter = m_options.find(name); |
| 2060 | 2293 | ||
| @@ -2074,11 +2307,11 @@ OptionParser::parse(int argc, const char* const* argv) | @@ -2074,11 +2307,11 @@ OptionParser::parse(int argc, const char* const* argv) | ||
| 2074 | auto opt = iter->second; | 2307 | auto opt = iter->second; |
| 2075 | 2308 | ||
| 2076 | //equals provided for long option? | 2309 | //equals provided for long option? |
| 2077 | - if (result[2].length() != 0) | 2310 | + if (argu_desc.set_value) |
| 2078 | { | 2311 | { |
| 2079 | //parse the option given | 2312 | //parse the option given |
| 2080 | 2313 | ||
| 2081 | - parse_option(opt, name, result[3]); | 2314 | + parse_option(opt, name, argu_desc.value); |
| 2082 | } | 2315 | } |
| 2083 | else | 2316 | else |
| 2084 | { | 2317 | { |