diff --git a/common/StringUtil.cpp b/common/StringUtil.cpp index ad9cfc1e25..5afdab8a5b 100644 --- a/common/StringUtil.cpp +++ b/common/StringUtil.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2021 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -14,7 +14,10 @@ */ #include "PrecompiledHeader.h" + +#include "Assertions.h" #include "StringUtil.h" + #include #include #include @@ -452,6 +455,47 @@ namespace StringUtil return DecodeUTF8(str.data() + offset, str.length() - offset, ch); } + std::string 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)); + pxAssert(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 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)); + pxAssert(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); + } + } + #ifdef _WIN32 std::wstring UTF8StringToWideString(const std::string_view& str) { diff --git a/common/StringUtil.h b/common/StringUtil.h index 1b1138cd2d..48f0a77e3a 100644 --- a/common/StringUtil.h +++ b/common/StringUtil.h @@ -283,6 +283,10 @@ namespace StringUtil 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. static inline 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) diff --git a/tests/ctest/common/string_util_tests.cpp b/tests/ctest/common/string_util_tests.cpp index 6bc40a535f..bcb6486c2c 100644 --- a/tests/ctest/common/string_util_tests.cpp +++ b/tests/ctest/common/string_util_tests.cpp @@ -113,3 +113,32 @@ TEST(StringUtil, FromCharsIsLocaleIndependent) } #endif + +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"); +}