From 74ce20b25652adefaf3a715703bb4bd92adcbc86 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 23 Feb 2021 12:52:34 -0500 Subject: [PATCH] Add string util search_deliminated_string (#1260) This function takes a string of deliminated an see if another string is one of those This function also verifies it's not finding a substring --- common/string_util.cpp | 13 +++++++++++++ common/string_util.h | 1 + tests/string_util_test.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/common/string_util.cpp b/common/string_util.cpp index 7cd19c829..d236f6532 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -125,6 +125,19 @@ std::vector SplitString(const std::string &str, char delim) { return ret; } +std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator) +{ + // this shouldn't go out of bounds, even without obvious bounds checks + auto pos = haystack.find(needle); + while (pos != std::string::npos) { + auto c = haystack[pos + needle.length()]; + if ((c == '\0' || c == deliminator) && (pos == 0 || haystack[pos - 1] == deliminator)) + return pos; + pos = haystack.find(needle, pos + needle.length()); + } + return std::string::npos; +} + std::string implode(std::string glue, std::vector src) { if (src.empty()) { diff --git a/common/string_util.h b/common/string_util.h index 226e21645..6ccaf7125 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -178,6 +178,7 @@ std::vector join_tuple(const std::string &glue, const std::pair SplitString(const std::string &s, char delim); +std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator = ','); std::string EscapeString(const char *src, size_t sz); std::string EscapeString(const std::string &s); bool StringIsNumber(const std::string &s); diff --git a/tests/string_util_test.h b/tests/string_util_test.h index facb0cc72..0333d0391 100644 --- a/tests/string_util_test.h +++ b/tests/string_util_test.h @@ -29,6 +29,7 @@ public: TEST_ADD(StringUtilTest::StringFormatTest); TEST_ADD(StringUtilTest::EscapeStringTest); TEST_ADD(StringUtilTest::EscapeStringMemoryTest); + TEST_ADD(StringUtilTest::SearchDeliminatedStringTest); } ~StringUtilTest() { @@ -80,6 +81,33 @@ public: auto s = EscapeString(t, 10); TEST_ASSERT(s.compare("abc\\x00\\n\\r\\\\\\'\\\"\\x1a") == 0); } + + void SearchDeliminatedStringTest() { + std::string h = + "befallen,charasis,dalnir,frontiermtns,gukbottom,iceclad,lakeofillomen,northkarana,qey2hh1,soldunga,southro,wakening,podisease,velketor,akheva,riwwi,bothunder,poair"; + TEST_ASSERT(search_deliminated_string(h, "befallen") == 0); + TEST_ASSERT(search_deliminated_string(h, "charasis") == 9); + TEST_ASSERT(search_deliminated_string(h, "dalnir") == 18); + TEST_ASSERT(search_deliminated_string(h, "frontiermtns") == 25); + TEST_ASSERT(search_deliminated_string(h, "gukbottom") == 38); + TEST_ASSERT(search_deliminated_string(h, "iceclad") == 48); + TEST_ASSERT(search_deliminated_string(h, "lakeofillomen") == 56); + TEST_ASSERT(search_deliminated_string(h, "northkarana") == 70); + TEST_ASSERT(search_deliminated_string(h, "qey2hh1") == 82); + TEST_ASSERT(search_deliminated_string(h, "soldunga") == 90); + TEST_ASSERT(search_deliminated_string(h, "southro") == 99); + TEST_ASSERT(search_deliminated_string(h, "wakening") == 107); + TEST_ASSERT(search_deliminated_string(h, "podisease") == 116); + TEST_ASSERT(search_deliminated_string(h, "velketor") == 126); + TEST_ASSERT(search_deliminated_string(h, "akheva") == 135); + TEST_ASSERT(search_deliminated_string(h, "riwwi") == 142); + TEST_ASSERT(search_deliminated_string(h, "bothunder") == 148); + TEST_ASSERT(search_deliminated_string(h, "poair") == 158); + TEST_ASSERT(search_deliminated_string(h, "pod") == std::string::npos); + TEST_ASSERT(search_deliminated_string(h, "air") == std::string::npos); + TEST_ASSERT(search_deliminated_string(h, "bef") == std::string::npos); + TEST_ASSERT(search_deliminated_string(h, "wwi") == std::string::npos); + } }; #endif