From f5da6e07d7405d89cc550b8c02f39a432f7888a3 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 28 Jun 2020 19:16:23 +0200 Subject: [PATCH] Android: Use correct encoding when converting strings The functions with "UTF" in the name use "modified UTF-8" rather than the standard UTF-8 which Dolphin uses, at least according to Oracle's documentation, so it is incorrect for us to use them. This change fixes the problem by converting between UTF-8 and UTF-16 manually instead of letting JNI do it for us. --- .../jni/AndroidCommon/AndroidCommon.cpp | 21 +++++++++++-------- Source/Core/Common/StringUtil.cpp | 14 ++++++++++++- Source/Core/Common/StringUtil.h | 2 ++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Source/Android/jni/AndroidCommon/AndroidCommon.cpp b/Source/Android/jni/AndroidCommon/AndroidCommon.cpp index cb7b9ff073..1f9973d451 100644 --- a/Source/Android/jni/AndroidCommon/AndroidCommon.cpp +++ b/Source/Android/jni/AndroidCommon/AndroidCommon.cpp @@ -5,25 +5,28 @@ #include "jni/AndroidCommon/AndroidCommon.h" #include +#include #include #include +#include "Common/StringUtil.h" + std::string GetJString(JNIEnv* env, jstring jstr) { - std::string result = ""; - if (!jstr) - return result; - - const char* s = env->GetStringUTFChars(jstr, nullptr); - result = s; - env->ReleaseStringUTFChars(jstr, s); - return result; + const jchar* jchars = env->GetStringChars(jstr, nullptr); + const jsize length = env->GetStringLength(jstr); + const std::u16string_view string_view(reinterpret_cast(jchars), length); + const std::string converted_string = UTF16ToUTF8(string_view); + env->ReleaseStringChars(jstr, jchars); + return converted_string; } jstring ToJString(JNIEnv* env, const std::string& str) { - return env->NewStringUTF(str.c_str()); + const std::u16string converted_string = UTF8ToUTF16(str); + return env->NewString(reinterpret_cast(converted_string.data()), + converted_string.size()); } std::vector JStringArrayToVector(JNIEnv* env, jobjectArray array) diff --git a/Source/Core/Common/StringUtil.cpp b/Source/Core/Common/StringUtil.cpp index e3c6f692f6..6c236de587 100644 --- a/Source/Core/Common/StringUtil.cpp +++ b/Source/Core/Common/StringUtil.cpp @@ -5,6 +5,7 @@ #include "Common/StringUtil.h" #include +#include #include #include #include @@ -33,7 +34,6 @@ constexpr u32 CODEPAGE_SHIFT_JIS = 932; constexpr u32 CODEPAGE_WINDOWS_1252 = 1252; #else -#include #include #include #include @@ -590,6 +590,18 @@ std::string UTF16BEToUTF8(const char16_t* str, size_t max_size) #endif +std::string UTF16ToUTF8(std::u16string_view input) +{ + std::wstring_convert, char16_t> converter; + return converter.to_bytes(input.data(), input.data() + input.size()); +} + +std::u16string UTF8ToUTF16(std::string_view input) +{ + std::wstring_convert, char16_t> converter; + return converter.from_bytes(input.data(), input.data() + input.size()); +} + #ifdef HAS_STD_FILESYSTEM // This is a replacement for path::u8path, which is deprecated starting with C++20. std::filesystem::path StringToPath(std::string_view path) diff --git a/Source/Core/Common/StringUtil.h b/Source/Core/Common/StringUtil.h index 70d240dbf9..d4fc19d683 100644 --- a/Source/Core/Common/StringUtil.h +++ b/Source/Core/Common/StringUtil.h @@ -173,6 +173,8 @@ std::string SHIFTJISToUTF8(std::string_view str); std::string UTF8ToSHIFTJIS(std::string_view str); std::string WStringToUTF8(std::wstring_view str); std::string UTF16BEToUTF8(const char16_t* str, size_t max_size); // Stops at \0 +std::string UTF16ToUTF8(std::u16string_view str); +std::u16string UTF8ToUTF16(std::string_view str); #ifdef _WIN32