diff --git a/include/bx/string.h b/include/bx/string.h index 114f194..7b27cc3 100644 --- a/include/bx/string.h +++ b/include/bx/string.h @@ -251,9 +251,15 @@ namespace bx /// Returns string view with characters _chars trimmed from right. StringView strRTrim(const StringView& _str, const StringView& _chars); + /// Returns string view with whitespace characters trimmed from right. + StringView strRTrimSpace(const StringView& _str); + /// Returns string view with characters _chars trimmed from left and right. StringView strTrim(const StringView& _str, const StringView& _chars); + /// Returns string view with whitespace characters trimmed from left and right. + StringView strTrimSpace(const StringView& _str); + /// Find new line. Returns pointer after new line terminator. StringView strFindNl(const StringView& _str); diff --git a/src/string.cpp b/src/string.cpp index aaf4754..ed4e56c 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -530,11 +530,34 @@ namespace bx return _str; } + StringView strRTrimSpace(const StringView& _str) + { + if (!_str.isEmpty() ) + { + const char* ptr = _str.getPtr(); + + for (int32_t len = _str.getLength(), ii = len - 1; 0 <= ii; --ii) + { + if (!isSpace(ptr[ii]) ) + { + return StringView(ptr, ii + 1); + } + } + } + + return _str; + } + StringView strTrim(const StringView& _str, const StringView& _chars) { return strLTrim(strRTrim(_str, _chars), _chars); } + StringView strTrimSpace(const StringView& _str) + { + return strLTrimSpace(strRTrimSpace(_str) ); + } + constexpr uint32_t kFindStep = 1024; StringView strFindNl(const StringView& _str) diff --git a/tests/string_test.cpp b/tests/string_test.cpp index 4cf4b95..40f58cf 100644 --- a/tests/string_test.cpp +++ b/tests/string_test.cpp @@ -494,6 +494,33 @@ TEST_CASE("Trim", "") REQUIRE(0 == bx::strCmp(bx::strTrim(uri.getPath(), "/"), "555333/podmac") ); } +TEST_CASE("TrimSpace", "") +{ + REQUIRE(bx::strLTrimSpace("").isEmpty() ); + REQUIRE(bx::strRTrimSpace("").isEmpty() ); + REQUIRE(bx::strTrimSpace( "").isEmpty() ); + + const bx::StringView t0("1389"); + const bx::StringView t1(" 1389"); + const bx::StringView t2("1389 "); + const bx::StringView t3(" 1389 "); + + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t0), t0) ); + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t1), t0) ); + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t2), t2) ); + REQUIRE(0 == bx::strCmp(bx::strLTrimSpace(t3), "1389 ") ); + + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t0), t0) ); + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t1), t1) ); + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t2), t0) ); + REQUIRE(0 == bx::strCmp(bx::strRTrimSpace(t3), " 1389") ); + + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t0), t0) ); + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t1), t0) ); + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t2), t0) ); + REQUIRE(0 == bx::strCmp(bx::strTrimSpace(t3), t0) ); +} + TEST_CASE("strWord", "") { REQUIRE(bx::strWord(" abvgd-1389.0").isEmpty() );