From 5a15b718a475f8c2809521ea3166de379bf85b36 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 10 Feb 2016 16:36:04 +0300 Subject: In parameters parsing function add support for multiply separators. --- src/utils/paramerers.cpp | 24 +++---- src/utils/paramerers.h | 2 +- src/utils/paramerers_unittest.cc | 141 +++++++++++++++++++++++++++++++------- src/utils/stringutils.cpp | 15 ++++ src/utils/stringutils.h | 4 ++ src/utils/stringutils_unittest.cc | 13 ++++ 6 files changed, 162 insertions(+), 37 deletions(-) (limited to 'src/utils') diff --git a/src/utils/paramerers.cpp b/src/utils/paramerers.cpp index 12c20a18e..418e15ab7 100644 --- a/src/utils/paramerers.cpp +++ b/src/utils/paramerers.cpp @@ -31,22 +31,20 @@ static inline void addToken(StringVect &tokens, std::string str) { - const size_t sz = str.size(); - std::string item; + std::string item = trim(str); + const size_t sz = item.size(); if (sz > 1) { if (str[0] == '\"' && str[sz - 1] == '\"' && str[sz - 2] != '\\') { - str = str.substr(1, sz - 2); - item = trim(str); + item = item.substr(1, sz - 2); replaceAll(item, "\\\"", "\""); tokens.push_back(item); return; } } - item = trim(str); replaceAll(item, "\\\"", "\""); if (!item.empty()) tokens.push_back(item); @@ -57,15 +55,17 @@ static inline size_t findNextQuote(const std::string &str, const size_t pos) { size_t idx = str.find(quote, pos); - if (idx == std::string::npos) - return idx; - while (idx > 0 && str[idx - 1] == '\\') + while (idx > 0 && + idx != std::string::npos && + str[idx - 1] == '\\') + { idx = str.find(quote, idx + 1); + } return idx; } -static inline size_t findNextSplit(std::string &str, - const char separator, +static inline size_t findNextSplit(const std::string &str, + const std::string &separator, const char quote) { size_t pos = 0; @@ -73,7 +73,7 @@ static inline size_t findNextSplit(std::string &str, while (true) { // search for next separator - idx1 = str.find(separator, pos); + idx1 = findAny(str, separator, pos); // search for next open quote, skipping escaped quotes size_t idx2 = findNextQuote(str, quote, pos); if (idx2 == std::string::npos) // not quotes, return next separator @@ -99,7 +99,7 @@ static inline size_t findNextSplit(std::string &str, bool splitParameters(StringVect &tokens, std::string text, - const char separator, + const std::string &separator, const char quote) { size_t idx = findNextSplit(text, separator, quote); diff --git a/src/utils/paramerers.h b/src/utils/paramerers.h index bdd91a9f2..d93f7a207 100644 --- a/src/utils/paramerers.h +++ b/src/utils/paramerers.h @@ -27,7 +27,7 @@ bool splitParameters(StringVect &tokens, std::string text, - const char separator, + const std::string &separator, const char quote); #endif // UTILS_PARAMETERS_H diff --git a/src/utils/paramerers_unittest.cc b/src/utils/paramerers_unittest.cc index 6303331e5..fbccef0e1 100644 --- a/src/utils/paramerers_unittest.cc +++ b/src/utils/paramerers_unittest.cc @@ -27,14 +27,14 @@ TEST_CASE("parameters basic 1") { StringVect pars; - REQUIRE(splitParameters(pars, "", ',', '\"') == true); + REQUIRE(splitParameters(pars, "", ",", '\"') == true); REQUIRE(pars.size() == 0); } TEST_CASE("parameters basic 2") { StringVect pars; - REQUIRE(splitParameters(pars, "one,two, tree", ',', '\"') == true); + REQUIRE(splitParameters(pars, "one,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "one"); REQUIRE(pars[1] == "two"); @@ -44,14 +44,14 @@ TEST_CASE("parameters basic 2") TEST_CASE("parameters basic 3") { StringVect pars; - REQUIRE(splitParameters(pars, ", ,,,", ',', '\"') == true); + REQUIRE(splitParameters(pars, ", ,,,", ",", '\"') == true); REQUIRE(pars.size() == 0); } TEST_CASE("parameters basic 4") { StringVect pars; - REQUIRE(splitParameters(pars, "one,,two, tree", ',', '\"') == true); + REQUIRE(splitParameters(pars, "one,,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "one"); REQUIRE(pars[1] == "two"); @@ -61,7 +61,7 @@ TEST_CASE("parameters basic 4") TEST_CASE("parameters escape 1") { StringVect pars; - REQUIRE(splitParameters(pars, "\\\"", ',', '\"') == true); + REQUIRE(splitParameters(pars, "\\\"", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\""); } @@ -69,7 +69,7 @@ TEST_CASE("parameters escape 1") TEST_CASE("parameters escape 2") { StringVect pars; - REQUIRE(splitParameters(pars, "\\\", test", ',', '\"') == true); + REQUIRE(splitParameters(pars, "\\\", test", ",", '\"') == true); REQUIRE(pars.size() == 2); REQUIRE(pars[0] == "\""); REQUIRE(pars[1] == "test"); @@ -78,7 +78,7 @@ TEST_CASE("parameters escape 2") TEST_CASE("parameters escape 3") { StringVect pars; - REQUIRE(splitParameters(pars, "test,\\\"", ',', '\"') == true); + REQUIRE(splitParameters(pars, "test,\\\"", ",", '\"') == true); REQUIRE(pars.size() == 2); REQUIRE(pars[0] == "test"); REQUIRE(pars[1] == "\""); @@ -87,7 +87,7 @@ TEST_CASE("parameters escape 3") TEST_CASE("parameters quote 1") { StringVect pars; - REQUIRE(splitParameters(pars, "\"one\",,two, tree", ',', '\"') == true); + REQUIRE(splitParameters(pars, "\"one\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "one"); REQUIRE(pars[1] == "two"); @@ -97,7 +97,7 @@ TEST_CASE("parameters quote 1") TEST_CASE("parameters quote 2") { StringVect pars; - REQUIRE(splitParameters(pars, "\"\",,two, tree", ',', '\"') == true); + REQUIRE(splitParameters(pars, "\"\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == ""); REQUIRE(pars[1] == "two"); @@ -107,7 +107,7 @@ TEST_CASE("parameters quote 2") TEST_CASE("parameters quote 3") { StringVect pars; - REQUIRE(splitParameters(pars, "\"one test\",,two, tree", ',', '\"') == + REQUIRE(splitParameters(pars, "\"one test\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "one test"); @@ -118,7 +118,7 @@ TEST_CASE("parameters quote 3") TEST_CASE("parameters quote 4") { StringVect pars; - REQUIRE(splitParameters(pars, "\"\\\"one test\\\"\",,two, tree", ',', '\"') + REQUIRE(splitParameters(pars, "\"\\\"one test\\\"\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "\"one test\""); @@ -129,8 +129,8 @@ TEST_CASE("parameters quote 4") TEST_CASE("parameters quote 5") { StringVect pars; - REQUIRE(splitParameters(pars, "\"\\\"one \\\"test\\\"\",,two, tree", ',', '\"') - == true); + REQUIRE(splitParameters(pars, "\"\\\"one \\\"test\\\"\",,two, tree", + ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "\"one \"test\""); REQUIRE(pars[1] == "two"); @@ -140,7 +140,7 @@ TEST_CASE("parameters quote 5") TEST_CASE("parameters quote 6") { StringVect pars; - REQUIRE(splitParameters(pars, "\"one, test\",,two, tree", ',', '\"') + REQUIRE(splitParameters(pars, "\"one, test\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "one, test"); @@ -151,8 +151,8 @@ TEST_CASE("parameters quote 6") TEST_CASE("parameters quote 7") { StringVect pars; - REQUIRE(splitParameters(pars, "\"\\\"one, test\\\"\",,two, tree", ',', '\"') - == true); + REQUIRE(splitParameters(pars, "\"\\\"one, test\\\"\",,two, tree", + ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "\"one, test\""); REQUIRE(pars[1] == "two"); @@ -162,7 +162,7 @@ TEST_CASE("parameters quote 7") TEST_CASE("parameters quote 8") { StringVect pars; - REQUIRE(splitParameters(pars, "\"\\\"\",,two, tree", ',', '\"') + REQUIRE(splitParameters(pars, "\"\\\"\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 3); REQUIRE(pars[0] == "\""); @@ -173,7 +173,7 @@ TEST_CASE("parameters quote 8") TEST_CASE("parameters quote 9") { StringVect pars; - REQUIRE(splitParameters(pars, "\"\\\",,two, tree", ',', '\"') + REQUIRE(splitParameters(pars, "\"\\\",,two, tree", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\"\",,two, tree"); @@ -182,7 +182,7 @@ TEST_CASE("parameters quote 9") TEST_CASE("parameters quote 10") { StringVect pars; - REQUIRE(splitParameters(pars, "\"", ',', '\"') + REQUIRE(splitParameters(pars, "\"", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\""); @@ -191,7 +191,7 @@ TEST_CASE("parameters quote 10") TEST_CASE("parameters quote 11") { StringVect pars; - REQUIRE(splitParameters(pars, "\\\"", ',', '\"') + REQUIRE(splitParameters(pars, "\\\"", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\""); @@ -200,7 +200,7 @@ TEST_CASE("parameters quote 11") TEST_CASE("parameters quote 12") { StringVect pars; - REQUIRE(splitParameters(pars, ",\"", ',', '\"') + REQUIRE(splitParameters(pars, ",\"", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\""); @@ -209,7 +209,7 @@ TEST_CASE("parameters quote 12") TEST_CASE("parameters quote 13") { StringVect pars; - REQUIRE(splitParameters(pars, "\",", ',', '\"') + REQUIRE(splitParameters(pars, "\",", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\","); @@ -218,7 +218,7 @@ TEST_CASE("parameters quote 13") TEST_CASE("parameters quote 14") { StringVect pars; - REQUIRE(splitParameters(pars, "\\\",", ',', '\"') + REQUIRE(splitParameters(pars, "\\\",", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\""); @@ -227,8 +227,101 @@ TEST_CASE("parameters quote 14") TEST_CASE("parameters quote 15") { StringVect pars; - REQUIRE(splitParameters(pars, ",\\\"", ',', '\"') + REQUIRE(splitParameters(pars, ",\\\"", ",", '\"') == true); REQUIRE(pars.size() == 1); REQUIRE(pars[0] == "\""); } + +TEST_CASE("parameters quote 16") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"one test\"", ",", '\"') == + true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "one test"); +} + +TEST_CASE("parameters quote 17") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"one, test\"", ",", '\"') == + true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "one, test"); +} + +TEST_CASE("parameters quote 18") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"one\\\" test\"", ",", '\"') == + true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "one\" test"); +} + +TEST_CASE("parameters quote 19") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"one\\\" ,test\"", ",", '\"') == + true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "one\" ,test"); +} + +TEST_CASE("parameters quote 20") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"one\\\" test,\"", ",", '\"') == + true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "one\" test,"); +} + +TEST_CASE("parameters complex 1") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"test\" \"line\"", ",", '\"') == true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "test\" \"line"); +} + +TEST_CASE("parameters complex 2") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"test\", \"line\"", ",", '\"') == true); + REQUIRE(pars.size() == 2); + REQUIRE(pars[0] == "test"); + REQUIRE(pars[1] == "line"); +} + +TEST_CASE("parameters complex 3") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"test,\" \"line\"", ",", '\"') == true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "test,\" \"line"); +} + +TEST_CASE("parameters broken 1") +{ + StringVect pars; + REQUIRE(splitParameters(pars, "\"", ",", '\"') == true); + REQUIRE(pars.size() == 1); + REQUIRE(pars[0] == "\""); +} + +TEST_CASE("parameters broken 2") +{ + StringVect pars; + REQUIRE(splitParameters(pars, ",", ",", '\"') == true); + REQUIRE(pars.size() == 0); +} + +TEST_CASE("parameters broken 3") +{ + StringVect pars; + REQUIRE(splitParameters(pars, + ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,", ",", '\"') == true); + REQUIRE(pars.size() == 0); +} diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index 9cc21f23a..e7887bc48 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -210,6 +210,21 @@ size_t findI(std::string text, const StringVect &list) return std::string::npos; } +size_t findAny(const std::string &restrict text, + const std::string &restrict chars, + const size_t pos) +{ + size_t idx = std::string::npos; + const size_t sz = chars.size(); + for (size_t f = 0; f < sz; f ++) + { + const size_t idx2 = text.find(chars[f], pos); + if (idx2 != std::string::npos && idx2 < idx) + idx = idx2; + } + return idx; +} + namespace { unsigned int base = 94; diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h index 67e91a464..ab9290378 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -142,6 +142,10 @@ size_t findI(std::string str, std::string subStr) A_WARN_UNUSED; size_t findI(std::string text, const StringVect &list) A_WARN_UNUSED; +size_t findAny(const std::string &restrict text, + const std::string &restrict chars, + const size_t pos) A_WARN_UNUSED; + const std::string encodeStr(unsigned int value, const unsigned int size = 0) A_WARN_UNUSED; diff --git a/src/utils/stringutils_unittest.cc b/src/utils/stringutils_unittest.cc index f6586558c..b921cf509 100644 --- a/src/utils/stringutils_unittest.cc +++ b/src/utils/stringutils_unittest.cc @@ -593,6 +593,19 @@ TEST_CASE("stringuntils isDigit") REQUIRE_FALSE(isDigit("12-34")); } +TEST_CASE("stringuntils findAny") +{ + std::string str; + + REQUIRE(findAny("test line", ",", 0) == std::string::npos); + REQUIRE(findAny("test line", " ", 0) == 4U); + REQUIRE(findAny("test, line", ", ", 0) == 4U); + REQUIRE(findAny("test ,line", ", ", 0) == 4U); + REQUIRE(findAny("test, line", " ,", 2) == 4U); + REQUIRE(findAny("test ,line", " ,", 3) == 4U); + REQUIRE(findAny("\"one\",,two, tree", ",", 5) == 5U); +} + TEST_CASE("stringuntils replaceItemLinks") { ItemDB::NamedItemInfos &infos = ItemDB::getNamedItemInfosTest(); -- cgit v1.2.3-70-g09d2