diff --git a/src/common/stringutils.cpp b/src/common/stringutils.cpp index f52c3d04..02624d19 100644 --- a/src/common/stringutils.cpp +++ b/src/common/stringutils.cpp @@ -236,3 +236,71 @@ bool StrUtils::isUtf8ContinuationByte(char c) { return (c & 0b1100'0000) == 0b1000'0000; } + +std::string StrUtils::ToLower(const std::string& text) +{ + std::string result; + + for (size_t i = 0; i < text.size();) + { + std::mbstate_t state = {}; + wchar_t ch; + + int len = std::mbrtowc(&ch, text.data() + i, text.size() - i, &state); + + if (len == -1) throw std::invalid_argument("Invalid character"); + + if (len == 0) len = 1; + + ch = std::towlower(ch); + + char buffer[8]; + + state = {}; + size_t count = std::wcrtomb(buffer, ch, &state); + + if (count == -1) throw std::invalid_argument("Invalid character"); + + if (count == 0) count = 1; + + result.append(buffer, count); + + i += len; + } + + return result; +} + +std::string StrUtils::ToUpper(const std::string& text) +{ + std::string result; + + for (size_t i = 0; i < text.size();) + { + std::mbstate_t state = {}; + wchar_t ch; + + size_t len = std::mbrtowc(&ch, text.data() + i, text.size() - i, &state); + + if (len == -1) throw std::invalid_argument("Invalid character"); + + if (len == 0) len = 1; + + ch = std::towupper(ch); + + char buffer[8]; + + state = {}; + size_t count = std::wcrtomb(buffer, ch, &state); + + if (count == -1) throw std::invalid_argument("Invalid character"); + + if (count == 0) count = 1; + + result.append(buffer, count); + + i += len; + } + + return result; +} diff --git a/src/common/stringutils.h b/src/common/stringutils.h index 63e10698..fc19cd26 100644 --- a/src/common/stringutils.h +++ b/src/common/stringutils.h @@ -98,5 +98,10 @@ std::size_t Utf8StringLength(const std::string &str); //! Returns true if char is continuation UTF-8 byte bool isUtf8ContinuationByte(char c); -} // namespace StrUtil +//! Returns the string with characters converted to lower case when possible +std::string ToLower(const std::string& text); +//! Returns the string with characters converted to upper case when possible +std::string ToUpper(const std::string& text); + +} // namespace StrUtil diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 8b7792c2..2ddbd3a5 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -31,10 +31,16 @@ target_include_directories(colobot_ut PRIVATE ${COLOBOT_LOCAL_INCLUDES} ) +if(MSVC) + target_compile_options(colobot_ut PRIVATE /utf-8) +endif() + target_link_libraries(colobot_ut PRIVATE GTest::GTest hippomocks colobotbase) gtest_discover_tests(colobot_ut - WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + DISCOVERY_MODE PRE_TEST +) # GoogleTest isn't compatible with -Wsuggest-override -Werror: # see https://github.com/google/googletest/issues/1063 diff --git a/test/unit/common/stringutils_test.cpp b/test/unit/common/stringutils_test.cpp index 9411bdb9..52dbcc86 100644 --- a/test/unit/common/stringutils_test.cpp +++ b/test/unit/common/stringutils_test.cpp @@ -32,7 +32,7 @@ TEST(StringUtilTests, ReplaceShortToLong) std::string expected = "Test [0987654], [0987654], [0987654][0987654] Test"; - EXPECT_TRUE(result == expected); + EXPECT_EQ(result, expected); } TEST(StringUtilTests, ReplaceLongToShort) @@ -43,7 +43,7 @@ TEST(StringUtilTests, ReplaceLongToShort) std::string expected = "Test [64], [64], [64][64] Test"; - EXPECT_TRUE(result == expected); + EXPECT_EQ(result, expected); } TEST(StringUtilTests, ReplaceSameLength) @@ -54,7 +54,29 @@ TEST(StringUtilTests, ReplaceSameLength) std::string expected = "Test [432], [432], [432][432] Test"; - EXPECT_TRUE(result == expected); + EXPECT_EQ(result, expected); +} + +TEST(StringUtilTests, ToLowerTest) +{ + std::string text = u8",./;AaBbĄąĘę"; + + auto result = StrUtils::ToLower(text); + + std::string expected = u8",./;aabbąąęę"; + + EXPECT_EQ(result, expected); +} + +TEST(StringUtilTests, ToUpperTest) +{ + std::string text = u8",./;AaBbĄąĘę"; + + auto result = StrUtils::ToUpper(text); + + std::string expected = u8",./;AABBĄĄĘĘ"; + + EXPECT_EQ(result, expected); } } // namespace StringUtils diff --git a/test/unit/main.cpp b/test/unit/main.cpp index bc171b16..7741d3eb 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -29,6 +29,8 @@ int main(int argc, char* argv[]) ::testing::InitGoogleTest(&argc, argv); + std::setlocale(LC_ALL, "en_US.UTF-8"); + // parse arguments not removed by InitGoogleTest for (int i = 1; i < argc; ++i) {