From 25d4cbaf044553cd16a2324b4b4fff409aec1af8 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Tue, 31 Jan 2017 16:22:50 -0500 Subject: [PATCH] Preparing for regex replacement --- include/CLI.hpp | 74 +++++++++++++++++++++++++++++++++++---------- tests/SmallTest.cpp | 58 +++++++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 18 deletions(-) diff --git a/include/CLI.hpp b/include/CLI.hpp index 21ec9ac8..54675ff4 100644 --- a/include/CLI.hpp +++ b/include/CLI.hpp @@ -4,7 +4,6 @@ // file LICENSE or https://github.com/henryiii/CLI11 for details. #include -#include #include #include #include @@ -24,6 +23,18 @@ #include #include +// GCC 4.7 and 4.8 have an non-working implementation of regex +#include +#if __cplusplus >= 201103L \ + && (!defined(__GLIBCXX__) \ + || (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE>4) \ + || (__cplusplus >= 201402L) \ + || (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || defined(_GLIBCXX_REGEX_STATE_LIMIT))) +#define HAVE_WORKING_REGEX 1 +#else +#define HAVE_WORKING_REGEX 0 +#endif + //#define CLI_LOG 1 namespace CLI { @@ -182,8 +193,30 @@ const std::regex reg_split{R"regex((?:([a-zA-Z_]?)(?:,|$)|^)([a-zA-Z0-9_][a-zA-Z const std::regex reg_short{R"regex(-([a-zA-Z_])(.*))regex"}; const std::regex reg_long{R"regex(--([^-^=][^=]*)=?(.*))regex"}; +// Returns false if not a short option. Otherwise, sets opt name and rest and returns true +inline bool split_short(const std::string ¤t, std::string &name, std::string &rest) { + std::smatch match; + if(std::regex_match(current, match, reg_short)) { + name = match[1]; + rest = match[2]; + return true; + } else + return false; +} -std::tuple split(std::string fullname) { +// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true +inline bool split_long(const std::string ¤t, std::string &name, std::string &value) { + std::smatch match; + if(std::regex_match(current, match, reg_long)) { + name = match[1]; + value = match[2]; + return true; + } else + return false; +} + +// Splits a string into long and short names +inline std::tuple split(std::string fullname) { std::smatch match; if (std::regex_match(fullname, match, reg_split)) { @@ -195,6 +228,19 @@ std::tuple split(std::string fullname) { } else throw BadNameString(fullname); } +// Splits a string into multiple long and short names (not implemented) +inline std::vector split_names(std::string current) { + std::vector output; + size_t val; + while((val = current.find(",")) != std::string::npos) { + output.push_back(current.substr(0,val)); + current = current.substr(val+1); + } + output.push_back(current); + return output; + +} + const Combiner NOTHING {0, false,false,false, {}}; const Combiner REQUIRED {1, false,true, false, {}}; const Combiner DEFAULT {1, false,false,true, {}}; @@ -843,14 +889,12 @@ public: void _parse_short(std::vector &args) { std::string current = args.back(); - std::smatch match; - if(!std::regex_match(current, match, reg_short)) + std::string name; + std::string rest; + if(!split_short(current, name, rest)) throw HorribleError("Short"); - args.pop_back(); - std::string name = match[1]; - std::string rest = match[2]; logit("Working on short: " + name + " (" + rest + ")"); @@ -895,31 +939,29 @@ public: } Classifer _recognize(std::string current) const { + std::string dummy1, dummy2; + if(current == "--") return Classifer::POSITIONAL_MARK; for(const std::unique_ptr &com : subcommands) { if(com->name == current) return Classifer::SUBCOMMAND; } - if(std::regex_match(current, reg_long)) + if(split_long(current, dummy1, dummy2)) return Classifer::LONG; - if(std::regex_match(current, reg_short)) + if(split_short(current, dummy1, dummy2)) return Classifer::SHORT; return Classifer::NONE; - - } void _parse_long(std::vector &args) { std::string current = args.back(); - std::smatch match; - if(!std::regex_match(current, match, reg_long)) + std::string name; + std::string value; + if(!split_long(current, name, value)) throw HorribleError("Long"); - args.pop_back(); - std::string name = match[1]; - std::string value = match[2]; logit("Working on long: " + name + " (" + value + ")"); diff --git a/tests/SmallTest.cpp b/tests/SmallTest.cpp index 924af48d..a36f332a 100644 --- a/tests/SmallTest.cpp +++ b/tests/SmallTest.cpp @@ -5,8 +5,6 @@ TEST(Split, GoodStrings) { - std::vector test_strings = {"a,boo", ",coo", "d,", "Q,this-is", "s", "single"}; - std::string s, l; std::tie(s, l) = CLI::split("a,boo"); @@ -65,3 +63,59 @@ TEST(Validators, FileNotExists) { std::remove(myfile.c_str()); EXPECT_TRUE(CLI::_NonexistentPath(myfile)); } + +TEST(Split, StringList) { + + std::vector results {"a", "long", "--lone", "-q"}; + EXPECT_EQ(results, CLI::split_names("a,long,--lone,-q")); + + EXPECT_EQ(std::vector({"one"}), CLI::split_names("one")); +} + +TEST(RegEx, Shorts) { + std::string name, value; + + EXPECT_TRUE(CLI::split_short("-a", name, value)); + EXPECT_EQ("a", name); + EXPECT_EQ("", value); + + EXPECT_TRUE(CLI::split_short("-B", name, value)); + EXPECT_EQ("B", name); + EXPECT_EQ("", value); + + EXPECT_TRUE(CLI::split_short("-cc", name, value)); + EXPECT_EQ("c", name); + EXPECT_EQ("c", value); + + EXPECT_TRUE(CLI::split_short("-simple", name, value)); + EXPECT_EQ("s", name); + EXPECT_EQ("imple", value); + + EXPECT_FALSE(CLI::split_short("--a", name, value)); + EXPECT_FALSE(CLI::split_short("--thing", name, value)); + EXPECT_FALSE(CLI::split_short("--", name, value)); + EXPECT_FALSE(CLI::split_short("something", name, value)); + EXPECT_FALSE(CLI::split_short("s", name, value)); +} + +TEST(RegEx, Longs) { + std::string name, value; + + EXPECT_TRUE(CLI::split_long("--a", name, value)); + EXPECT_EQ("a", name); + EXPECT_EQ("", value); + + EXPECT_TRUE(CLI::split_long("--thing", name, value)); + EXPECT_EQ("thing", name); + EXPECT_EQ("", value); + + EXPECT_TRUE(CLI::split_long("--some=thing", name, value)); + EXPECT_EQ("some", name); + EXPECT_EQ("thing", value); + + EXPECT_FALSE(CLI::split_long("-a", name, value)); + EXPECT_FALSE(CLI::split_long("-things", name, value)); + EXPECT_FALSE(CLI::split_long("Q", name, value)); + EXPECT_FALSE(CLI::split_long("--", name, value)); + +}