From ce07ef182134283178d220901e14d3de30e053b8 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 3 Aug 2022 15:44:51 +0200 Subject: [PATCH] android: Use correct encoding when converting strings The JNI functions that have "UTF" their name use "modified UTF-8" rather than the standard UTF-8 that Citra 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/android_common/android_common.cpp | 22 +++++++++++++------ .../main/jni/android_common/android_common.h | 2 +- src/common/string_util.cpp | 10 +++++---- src/common/string_util.h | 5 +++-- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp index 0fa028944..dedd33151 100644 --- a/src/android/app/src/main/jni/android_common/android_common.cpp +++ b/src/android/app/src/main/jni/android_common/android_common.cpp @@ -5,20 +5,28 @@ #include "jni/android_common/android_common.h" #include +#include #include -std::string GetJString(JNIEnv *env, jstring jstr) { +#include "common/string_util.h" + +std::string GetJString(JNIEnv* env, jstring jstr) { if (!jstr) { return {}; } - const char *s = env->GetStringUTFChars(jstr, nullptr); - std::string 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 = Common::UTF16ToUTF8(string_view); + env->ReleaseStringChars(jstr, jchars); + + return converted_string; } -jstring ToJString(JNIEnv* env, const std::string& str) { - return env->NewStringUTF(str.c_str()); +jstring ToJString(JNIEnv* env, std::string_view str) { + const std::u16string converted_string = Common::UTF8ToUTF16(str); + return env->NewString(reinterpret_cast(converted_string.data()), + static_cast(converted_string.size())); } diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h index ff55bee75..a09f7bc45 100644 --- a/src/android/app/src/main/jni/android_common/android_common.h +++ b/src/android/app/src/main/jni/android_common/android_common.h @@ -9,4 +9,4 @@ #include std::string GetJString(JNIEnv* env, jstring jstr); -jstring ToJString(JNIEnv* env, const std::string& str); +jstring ToJString(JNIEnv* env, std::string_view str); diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 395cf1d38..47aaddddb 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "common/common_paths.h" #include "common/logging/log.h" #include "common/string_util.h" @@ -135,14 +137,14 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st return result; } -std::string UTF16ToUTF8(const std::u16string& input) { +std::string UTF16ToUTF8(std::u16string_view input) { std::wstring_convert, char16_t> convert; - return convert.to_bytes(input); + return convert.to_bytes(input.data(), input.data() + input.size()); } -std::u16string UTF8ToUTF16(const std::string& input) { +std::u16string UTF8ToUTF16(std::string_view input) { std::wstring_convert, char16_t> convert; - return convert.from_bytes(input); + return convert.from_bytes(input.data(), input.data() + input.size()); } #ifdef _WIN32 diff --git a/src/common/string_util.h b/src/common/string_util.h index 2c454bb7b..d9edbf803 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "common/common_types.h" #include "common/swap.h" @@ -37,8 +38,8 @@ void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _P [[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest); -[[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input); -[[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input); +[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); +[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); #ifdef _WIN32 [[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input);