From b836ad050d7037b26855e8f22ee4cc6d83828834 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Thu, 17 May 2018 21:05:00 +0200 Subject: [PATCH] Rewrite CodePageFromUTF8 as CodePageFromUnicode. --- src/openrct2/core/String.cpp | 50 ++++++++++++++++++++++-------------- test/tests/StringTest.cpp | 5 ---- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index 405f06b1cc..8c8ce255ff 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -612,14 +612,20 @@ namespace String case CODE_PAGE::CP_950: return "big5"; + case CODE_PAGE::CP_1252: + return "windows-1252"; + + case CODE_PAGE::CP_UTF8: + return "utf-8"; + default: throw std::runtime_error("Unsupported code page: " + std::to_string(codePage)); } } - static char* CodePageFromUTF8(const utf8* src, size_t srcMaxSize, sint32 dstCodePage) + static std::string CodePageFromUnicode(icu::UnicodeString src, sint32 dstCodePage) { - UConverter *conv; + UConverter* conv; UErrorCode status = U_ZERO_ERROR; const char* codepage = GetIcuCodePage(dstCodePage); @@ -631,25 +637,29 @@ namespace String return nullptr; } - const char *srcLimit = src + srcMaxSize; - auto sb = StringBuilder(64); + // Allocate buffer to convert to. + int8_t char_size = ucnv_getMaxCharSize(conv); + std::string buffer(char_size * src.length(), '\0'); - while ((src < srcLimit) && (*src != '\0')) + char* buffer_limit = &buffer[0] + (char_size * src.length()); + + // Ready the source string as well... + const char16_t* source = src.getTerminatedBuffer(); + const char16_t* source_limit = source + src.length(); + + // Convert the lot. + char* buffer_target = &buffer[0]; + ucnv_fromUnicode(conv, &buffer_target, buffer_limit, (const UChar**) &source, source_limit, nullptr, true, &status); + + if (U_FAILURE(status)) { - codepoint_t codepoint = ucnv_getNextUChar(conv, &src, srcLimit, &status); - - if (U_FAILURE(status)) - { - log_error("ICU error: %s", u_errorName(status)); - return nullptr; - } - - sb.Append(codepoint); + log_error("ICU error: %s", u_errorName(status)); + return nullptr; } ucnv_close(conv); - return (char*) sb.StealString(); + return buffer; } #endif @@ -680,11 +690,13 @@ namespace String icu::UnicodeString convertString(src.data(), codepage); std::string result; - convertString.toUTF8String(result); - - if (dstCodePage != CODE_PAGE::CP_UTF8) + if (dstCodePage == CODE_PAGE::CP_UTF8) { - result = CodePageFromUTF8(result.c_str(), result.length(), dstCodePage); + convertString.toUTF8String(result); + } + else + { + result = CodePageFromUnicode(convertString, dstCodePage); } return result; diff --git a/test/tests/StringTest.cpp b/test/tests/StringTest.cpp index 794327d3ea..da815d54dc 100644 --- a/test/tests/StringTest.cpp +++ b/test/tests/StringTest.cpp @@ -78,9 +78,6 @@ TEST_F(StringTest, Split_ByEmpty) // Tests for String::Convert /////////////////////////////////////////////////////////////////////////////// -// TODO Remove when String::Convert is implemented for non-Windows platforms -#ifdef _WIN32 - TEST_F(StringTest, Convert_950_to_UTF8) { auto input = StringFromHex("a7d6b374aabab4c4a6e2aab0af57"); @@ -113,8 +110,6 @@ TEST_F(StringTest, Convert_Empty) ASSERT_EQ(expected, actual); } -#endif - /////////////////////////////////////////////////////////////////////////////// // Tests for String::ToUpper ///////////////////////////////////////////////////////////////////////////////