From 4b24bf74f4decc4c9233ff0f12c567f8252e7112 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 18 Sep 2023 22:29:34 +1000 Subject: [PATCH] StringUtil: Add Ellipsise() --- src/common-tests/CMakeLists.txt | 1 + src/common-tests/common-tests.vcxproj | 1 + src/common-tests/common-tests.vcxproj.filters | 1 + src/common-tests/string_tests.cpp | 34 ++++++++++++++ src/common/string_util.cpp | 45 ++++++++++++++++++- src/common/string_util.h | 4 ++ 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/common-tests/string_tests.cpp diff --git a/src/common-tests/CMakeLists.txt b/src/common-tests/CMakeLists.txt index 86bec30d6..3aadc3002 100644 --- a/src/common-tests/CMakeLists.txt +++ b/src/common-tests/CMakeLists.txt @@ -3,6 +3,7 @@ add_executable(common-tests file_system_tests.cpp path_tests.cpp rectangle_tests.cpp + string_tests.cpp ) target_link_libraries(common-tests PRIVATE common gtest gtest_main) diff --git a/src/common-tests/common-tests.vcxproj b/src/common-tests/common-tests.vcxproj index 25bc2bccb..7df80bf06 100644 --- a/src/common-tests/common-tests.vcxproj +++ b/src/common-tests/common-tests.vcxproj @@ -7,6 +7,7 @@ + diff --git a/src/common-tests/common-tests.vcxproj.filters b/src/common-tests/common-tests.vcxproj.filters index d9efc532d..b7b2e270d 100644 --- a/src/common-tests/common-tests.vcxproj.filters +++ b/src/common-tests/common-tests.vcxproj.filters @@ -6,5 +6,6 @@ + \ No newline at end of file diff --git a/src/common-tests/string_tests.cpp b/src/common-tests/string_tests.cpp new file mode 100644 index 000000000..518d21c33 --- /dev/null +++ b/src/common-tests/string_tests.cpp @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin +// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) + +#include "common/string_util.h" +#include + +TEST(StringUtil, Ellipsise) +{ + ASSERT_EQ(StringUtil::Ellipsise("HelloWorld", 6, "..."), "Hel..."); + ASSERT_EQ(StringUtil::Ellipsise("HelloWorld", 7, ".."), "Hello.."); + ASSERT_EQ(StringUtil::Ellipsise("HelloWorld", 20, ".."), "HelloWorld"); + ASSERT_EQ(StringUtil::Ellipsise("", 20, "..."), ""); + ASSERT_EQ(StringUtil::Ellipsise("Hello", 10, "..."), "Hello"); +} + +TEST(StringUtil, EllipsiseInPlace) +{ + std::string s; + s = "HelloWorld"; + StringUtil::EllipsiseInPlace(s, 6, "..."); + ASSERT_EQ(s, "Hel..."); + s = "HelloWorld"; + StringUtil::EllipsiseInPlace(s, 7, ".."); + ASSERT_EQ(s, "Hello.."); + s = "HelloWorld"; + StringUtil::EllipsiseInPlace(s, 20, ".."); + ASSERT_EQ(s, "HelloWorld"); + s = ""; + StringUtil::EllipsiseInPlace(s, 20, "..."); + ASSERT_EQ(s, ""); + s = "Hello"; + StringUtil::EllipsiseInPlace(s, 10, "..."); + ASSERT_EQ(s, "Hello"); +} diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 25964092a..140d94606 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -1,7 +1,9 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) +#include "assert.h" #include "string_util.h" + #include #include #include @@ -395,6 +397,47 @@ invalid: return 1; } +std::string StringUtil::Ellipsise(const std::string_view& str, u32 max_length, const char* ellipsis /*= "..."*/) +{ + std::string ret; + ret.reserve(max_length); + + const u32 str_length = static_cast(str.length()); + const u32 ellipsis_len = static_cast(std::strlen(ellipsis)); + DebugAssert(ellipsis_len > 0 && ellipsis_len <= max_length); + + if (str_length > max_length) + { + const u32 copy_size = std::min(str_length, max_length - ellipsis_len); + if (copy_size > 0) + ret.append(str.data(), copy_size); + if (copy_size != str_length) + ret.append(ellipsis); + } + else + { + ret.append(str); + } + + return ret; +} + +void StringUtil::EllipsiseInPlace(std::string& str, u32 max_length, const char* ellipsis /*= "..."*/) +{ + const u32 str_length = static_cast(str.length()); + const u32 ellipsis_len = static_cast(std::strlen(ellipsis)); + DebugAssert(ellipsis_len > 0 && ellipsis_len <= max_length); + + if (str_length > max_length) + { + const u32 keep_size = std::min(static_cast(str.length()), max_length - ellipsis_len); + if (keep_size != str_length) + str.erase(keep_size); + + str.append(ellipsis); + } +} + size_t StringUtil::DecodeUTF8(const std::string_view& str, size_t offset, char32_t* ch) { return DecodeUTF8(str.data() + offset, str.length() - offset, ch); diff --git a/src/common/string_util.h b/src/common/string_util.h index 78432a83b..c14822eb6 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -271,6 +271,10 @@ size_t DecodeUTF8(const void* bytes, size_t length, char32_t* ch); size_t DecodeUTF8(const std::string_view& str, size_t offset, char32_t* ch); size_t DecodeUTF8(const std::string& str, size_t offset, char32_t* ch); +// Replaces the end of a string with ellipsis if it exceeds the specified length. +std::string Ellipsise(const std::string_view& str, u32 max_length, const char* ellipsis = "..."); +void EllipsiseInPlace(std::string& str, u32 max_length, const char* ellipsis = "..."); + /// Strided memcpy/memcmp. ALWAYS_INLINE static void StrideMemCpy(void* dst, std::size_t dst_stride, const void* src, std::size_t src_stride, std::size_t copy_size, std::size_t count)