From 7a5f6ebd09c1164480d2bd35927e355ed8fadd40 Mon Sep 17 00:00:00 2001 From: kamchatka-volcano Date: Sun, 15 Jan 2023 00:13:53 +0300 Subject: [PATCH] -added string_utils overloads which are safe to use with temporary strings; -updated clang-format; --- .clang-format | 1 + include/sfun/string_utils.h | 74 +++++++++++++++++++++++++++++---- tests/test_string.cpp | 83 +++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 7 deletions(-) diff --git a/.clang-format b/.clang-format index 71848cc..f921912 100644 --- a/.clang-format +++ b/.clang-format @@ -18,6 +18,7 @@ BraceWrapping: BeforeElse: true BeforeLambdaBody: true BeforeWhile: true + BeforeCatch: true BreakBeforeBraces: Custom BreakBeforeBinaryOperators: None BreakInheritanceList: AfterComma diff --git a/include/sfun/string_utils.h b/include/sfun/string_utils.h index 27a067b..64095fe 100644 --- a/include/sfun/string_utils.h +++ b/include/sfun/string_utils.h @@ -78,8 +78,10 @@ inline char toupper(char ch) return static_cast(std::toupper(static_cast(ch))); } -inline std::string_view trimFront(std::string_view str) +template>* = nullptr> +inline std::string_view trimFront(const T& strVal) { + auto str = std::string_view{strVal}; auto it = std::find_if( str.begin(), str.end(), @@ -91,8 +93,15 @@ inline std::string_view trimFront(std::string_view str) return str.substr(static_cast(firstNotBlank)); } -inline std::string_view trimBack(std::string_view str) +inline std::string trimFront(std::string&& str) { + return std::string{trimFront(std::string_view{str})}; +} + +template>* = nullptr> +inline std::string_view trimBack(const T& strVal) +{ + auto str = std::string_view{strVal}; auto it = std::find_if( str.rbegin(), str.rend(), @@ -105,13 +114,27 @@ inline std::string_view trimBack(std::string_view str) return str.substr(0, static_cast(lastNotBlank)); } -inline std::string_view trim(std::string_view str) +inline std::string trimBack(std::string&& str) +{ + return std::string{trimBack(std::string_view{str})}; +} + +template>* = nullptr> +inline std::string_view trim(const T& strVal) { + auto str = std::string_view{strVal}; return trimBack(trimFront(str)); } -inline std::vector split(std::string_view str, std::string_view delim = " ", bool trimmed = true) +inline std::string trim(std::string&& str) { + return std::string{trim(std::string_view{str})}; +} + +template>* = nullptr> +inline std::vector split(const T& strVal, std::string_view delim = " ", bool trimmed = true) +{ + auto str = std::string_view{strVal}; if (delim.empty() || str.empty()) return std::vector{str}; @@ -133,6 +156,21 @@ inline std::vector split(std::string_view str, std::string_vie return result; } +inline std::vector split(std::string&& str, std::string_view delim = " ", bool trimmed = true) +{ + auto stringViewList = split(std::string_view{str}, delim, trimmed); + auto stringList = std::vector{}; + std::transform( + stringViewList.begin(), + stringViewList.end(), + std::back_inserter(stringList), + [](const std::string_view& view) + { + return std::string{view}; + }); + return stringList; +} + inline std::string replace(std::string str, std::string_view subStr, std::string_view val) { if (subStr.empty()) @@ -197,26 +235,48 @@ inline bool endsWith(std::string_view str, std::string_view val) return std::distance(res, str.end()) == static_cast(val.size()); } -inline std::string_view before(std::string_view str, std::string_view val) +template>* = nullptr> +inline std::string_view before(const T& strVal, std::string_view val) { + auto str = std::string_view{strVal}; auto res = str.find(val); if (res == std::string_view::npos) return str; return {str.data(), res}; } -inline std::string_view after(std::string_view str, std::string_view val) +inline std::string before(std::string&& str, std::string_view val) +{ + return std::string{before(std::string_view{str}, val)}; +} + +template>* = nullptr> +inline std::string_view after(const T& strVal, std::string_view val) { + auto str = std::string_view{strVal}; auto res = str.find(val); if (res == std::string_view::npos) return {}; return {std::next(str.data(), static_cast(res + val.size())), str.size() - (res + val.size())}; } -inline std::string_view between(std::string_view str, std::string_view afterStr, std::string_view beforeStr) +inline std::string after(std::string&& str, std::string_view val) +{ + return std::string{after(std::string_view{str}, val)}; +} + +template>* = nullptr> +inline std::string_view between(const T& strVal, std::string_view afterStr, std::string_view beforeStr) { + auto str = std::string_view{strVal}; return before(after(str, afterStr), beforeStr); } + +inline std::string between(std::string&& str, std::string_view afterStr, std::string_view beforeStr) +{ + return std::string{between(std::string_view{str}, afterStr, beforeStr)}; +} + } //namespace sfun #endif //SFUN_STRING_UTILS_H \ No newline at end of file diff --git a/tests/test_string.cpp b/tests/test_string.cpp index 8a8b19f..c8fd356 100644 --- a/tests/test_string.cpp +++ b/tests/test_string.cpp @@ -12,6 +12,18 @@ TEST(String, TrimFront) EXPECT_EQ(trimFront(" \n \t "), ""); EXPECT_EQ(trimFront("\n\t"), ""); EXPECT_EQ(trimFront(""), ""); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(trimFront(str(" Hello world")), "Hello world"); + EXPECT_EQ(trimFront(str(" Hello world ")), "Hello world "); + EXPECT_EQ(trimFront(str(" \n\t Hello world")), "Hello world"); + EXPECT_EQ(trimFront(str("Hello world ")), "Hello world "); + EXPECT_EQ(trimFront(str(" \n \t ")), ""); + EXPECT_EQ(trimFront(str("\n\t")), ""); + EXPECT_EQ(trimFront(str("")), ""); } TEST(String, TrimBack) @@ -22,6 +34,17 @@ TEST(String, TrimBack) EXPECT_EQ(trimBack(" \n \t "), ""); EXPECT_EQ(trimBack("\n\t"), ""); EXPECT_EQ(trimBack(""), ""); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(trimBack(str("Hello world ")), "Hello world"); + EXPECT_EQ(trimBack(str(" Hello world ")), " Hello world"); + EXPECT_EQ(trimBack(str("Hello world \n\t")), "Hello world"); + EXPECT_EQ(trimBack(str(" \n \t ")), ""); + EXPECT_EQ(trimBack(str("\n\t")), ""); + EXPECT_EQ(trimBack(str("")), ""); } TEST(String, Trim) @@ -33,6 +56,18 @@ TEST(String, Trim) EXPECT_EQ(trim(" \n\t "), ""); EXPECT_EQ(trim("\n\t"), ""); EXPECT_EQ(trim(""), ""); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(trim(str(" Hello world")), "Hello world"); + EXPECT_EQ(trim(str(" Hello world ")), "Hello world"); + EXPECT_EQ(trim(str("Hello world ")), "Hello world"); + EXPECT_EQ(trim(str(" \n\t Hello world")), "Hello world"); + EXPECT_EQ(trim(str(" \n\t ")), ""); + EXPECT_EQ(trim(str("\n\t")), ""); + EXPECT_EQ(trim(str("")), ""); } TEST(String, Split) @@ -46,6 +81,20 @@ TEST(String, Split) EXPECT_EQ(split(""), (std::vector{""})); EXPECT_EQ(split("hello world", ""), (std::vector{"hello world"})); EXPECT_EQ(split("", ""), (std::vector{""})); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(split(str("hello world")), (std::vector{"hello", "world"})); + EXPECT_EQ(split(str("hello world"), ","), (std::vector{"hello world"})); + EXPECT_EQ(split(str("hello world, nice weather"), ","), (std::vector{"hello world", "nice weather"})); + EXPECT_EQ( + split(str("hello world\n, nice weather"), ",", false), + (std::vector{"hello world\n", " nice weather"})); + EXPECT_EQ(split(str("")), (std::vector{""})); + EXPECT_EQ(split(str("hello world"), ""), (std::vector{"hello world"})); + EXPECT_EQ(split(str(""), ""), (std::vector{""})); } TEST(String, Replace) @@ -124,6 +173,16 @@ TEST(String, Before) EXPECT_EQ(before("hello world", ""), ""); EXPECT_EQ(before("", "moon"), ""); EXPECT_EQ(before("", ""), ""); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(before(str("hello world"), "world"), "hello "); + EXPECT_EQ(before(str("hello world"), "moon"), "hello world"); + EXPECT_EQ(before(str("hello world"), ""), ""); + EXPECT_EQ(before(str(""), "moon"), ""); + EXPECT_EQ(before(str(""), ""), ""); } TEST(String, After) @@ -133,6 +192,16 @@ TEST(String, After) EXPECT_EQ(after("hello world", ""), "hello world"); EXPECT_EQ(after("", "moon"), ""); EXPECT_EQ(after("", ""), ""); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(after(str("hello world"), "hello"), " world"); + EXPECT_EQ(after(str("hello world"), "moon"), ""); + EXPECT_EQ(after(str("hello world"), ""), "hello world"); + EXPECT_EQ(after(str(""), "moon"), ""); + EXPECT_EQ(after(str(""), ""), ""); } TEST(String, Between) @@ -146,6 +215,20 @@ TEST(String, Between) EXPECT_EQ(between("", "", "moon"), ""); EXPECT_EQ(between("", "moon", ""), ""); EXPECT_EQ(between("", "", ""), ""); + + auto str = [](auto strVal) + { + return std::string{strVal}; + }; + EXPECT_EQ(between(str("hello world!"), "hello", "!"), " world"); + EXPECT_EQ(between(str("hello world!"), "hello", "moon"), " world!"); + EXPECT_EQ(between(str("hello world!"), "moon", "!"), ""); + EXPECT_EQ(between(str("hello world!"), "", "!"), "hello world"); + EXPECT_EQ(between(str("hello world!"), "hello", ""), ""); + EXPECT_EQ(between(str(""), "hello", "moon"), ""); + EXPECT_EQ(between(str(""), "", "moon"), ""); + EXPECT_EQ(between(str(""), "moon", ""), ""); + EXPECT_EQ(between(str(""), "", ""), ""); } TEST(String, cctypeWrappers)