Merge pull request #6089 from JosJuice/android-convert-str

android: Improve string conversion
This commit is contained in:
SachinVin 2022-08-04 13:47:49 +05:30 committed by GitHub
commit a51b1cd3cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 70 additions and 39 deletions

View File

@ -1,4 +1,6 @@
add_library(citra-android SHARED add_library(citra-android SHARED
android_common/android_common.cpp
android_common/android_common.h
applets/mii_selector.cpp applets/mii_selector.cpp
applets/mii_selector.h applets/mii_selector.h
applets/swkbd.cpp applets/swkbd.cpp

View File

@ -0,0 +1,32 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "jni/android_common/android_common.h"
#include <string>
#include <string_view>
#include <jni.h>
#include "common/string_util.h"
std::string GetJString(JNIEnv* env, jstring jstr) {
if (!jstr) {
return {};
}
const jchar* jchars = env->GetStringChars(jstr, nullptr);
const jsize length = env->GetStringLength(jstr);
const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length);
const std::string converted_string = Common::UTF16ToUTF8(string_view);
env->ReleaseStringChars(jstr, jchars);
return converted_string;
}
jstring ToJString(JNIEnv* env, std::string_view str) {
const std::u16string converted_string = Common::UTF8ToUTF16(str);
return env->NewString(reinterpret_cast<const jchar*>(converted_string.data()),
static_cast<jint>(converted_string.size()));
}

View File

@ -0,0 +1,12 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <jni.h>
std::string GetJString(JNIEnv* env, jstring jstr);
jstring ToJString(JNIEnv* env, std::string_view str);

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/string_util.h" #include "common/string_util.h"
#include "jni/android_common/android_common.h"
#include "jni/applets/mii_selector.h" #include "jni/applets/mii_selector.h"
#include "jni/id_cache.h" #include "jni/id_cache.h"
@ -26,7 +27,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
static_cast<jboolean>(config.enable_cancel_button)); static_cast<jboolean>(config.enable_cancel_button));
env->SetObjectField(java_config, env->SetObjectField(java_config,
env->GetFieldID(s_mii_selector_config_class, "title", "Ljava/lang/String;"), env->GetFieldID(s_mii_selector_config_class, "title", "Ljava/lang/String;"),
env->NewStringUTF(config.title.c_str())); ToJString(env, config.title));
env->SetLongField( env->SetLongField(
java_config, java_config,
env->GetFieldID(s_mii_selector_config_class, "initially_selected_mii_index", "J"), env->GetFieldID(s_mii_selector_config_class, "initially_selected_mii_index", "J"),
@ -39,7 +40,7 @@ void AndroidMiiSelector::Setup(const Frontend::MiiSelectorConfig& config) {
env->NewObjectArray(static_cast<jsize>(miis.size()), string_class, nullptr); env->NewObjectArray(static_cast<jsize>(miis.size()), string_class, nullptr);
for (std::size_t i = 0; i < miis.size(); ++i) { for (std::size_t i = 0; i < miis.size(); ++i) {
const auto name = Common::UTF16BufferToUTF8(miis[i].mii_name); const auto name = Common::UTF16BufferToUTF8(miis[i].mii_name);
env->SetObjectArrayElement(array, static_cast<jsize>(i), env->NewStringUTF(name.c_str())); env->SetObjectArrayElement(array, static_cast<jsize>(i), ToJString(env, name));
} }
env->SetObjectField( env->SetObjectField(
java_config, java_config,

View File

@ -3,22 +3,14 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <map> #include <map>
#include <jni.h> #include <jni.h>
#include "core/core.h" #include "core/core.h"
#include "jni/android_common/android_common.h"
#include "jni/applets/swkbd.h" #include "jni/applets/swkbd.h"
#include "jni/id_cache.h" #include "jni/id_cache.h"
static 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;
}
static jclass s_software_keyboard_class; static jclass s_software_keyboard_class;
static jclass s_keyboard_config_class; static jclass s_keyboard_config_class;
static jclass s_keyboard_data_class; static jclass s_keyboard_data_class;
@ -39,15 +31,15 @@ static jobject ToJavaKeyboardConfig(const Frontend::KeyboardConfig& config) {
static_cast<jboolean>(config.multiline_mode)); static_cast<jboolean>(config.multiline_mode));
env->SetObjectField(object, env->SetObjectField(object,
env->GetFieldID(s_keyboard_config_class, "hint_text", "Ljava/lang/String;"), env->GetFieldID(s_keyboard_config_class, "hint_text", "Ljava/lang/String;"),
env->NewStringUTF(config.hint_text.c_str())); ToJString(env, config.hint_text));
const jclass string_class = reinterpret_cast<jclass>(env->FindClass("java/lang/String")); const jclass string_class = reinterpret_cast<jclass>(env->FindClass("java/lang/String"));
const jobjectArray array = const jobjectArray array =
env->NewObjectArray(static_cast<jsize>(config.button_text.size()), string_class, env->NewObjectArray(static_cast<jsize>(config.button_text.size()), string_class,
env->NewStringUTF(config.button_text[0].c_str())); ToJString(env, config.button_text[0]));
for (std::size_t i = 1; i < config.button_text.size(); ++i) { for (std::size_t i = 1; i < config.button_text.size(); ++i) {
env->SetObjectArrayElement(array, static_cast<jsize>(i), env->SetObjectArrayElement(array, static_cast<jsize>(i),
env->NewStringUTF(config.button_text[i].c_str())); ToJString(env, config.button_text[i]));
} }
env->SetObjectField( env->SetObjectField(
object, env->GetFieldID(s_keyboard_config_class, "button_text", "[Ljava/lang/String;"), object, env->GetFieldID(s_keyboard_config_class, "button_text", "[Ljava/lang/String;"),
@ -78,8 +70,7 @@ void AndroidKeyboard::Execute(const Frontend::KeyboardConfig& config) {
void AndroidKeyboard::ShowError(const std::string& error) { void AndroidKeyboard::ShowError(const std::string& error) {
JNIEnv* env = IDCache::GetEnvForThread(); JNIEnv* env = IDCache::GetEnvForThread();
env->CallStaticVoidMethod(s_software_keyboard_class, s_swkbd_show_error, env->CallStaticVoidMethod(s_software_keyboard_class, s_swkbd_show_error, ToJString(env, error));
env->NewStringUTF(error.c_str()));
} }
void InitJNI(JNIEnv* env) { void InitJNI(JNIEnv* env) {

View File

@ -27,6 +27,7 @@
#include "core/hle/service/nfc/nfc.h" #include "core/hle/service/nfc/nfc.h"
#include "core/savestate.h" #include "core/savestate.h"
#include "core/settings.h" #include "core/settings.h"
#include "jni/android_common/android_common.h"
#include "jni/applets/mii_selector.h" #include "jni/applets/mii_selector.h"
#include "jni/applets/swkbd.h" #include "jni/applets/swkbd.h"
#include "jni/camera/ndk_camera.h" #include "jni/camera/ndk_camera.h"
@ -58,24 +59,13 @@ std::condition_variable running_cv;
} // Anonymous namespace } // Anonymous namespace
static 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;
}
static bool DisplayAlertMessage(const char* caption, const char* text, bool yes_no) { static bool DisplayAlertMessage(const char* caption, const char* text, bool yes_no) {
JNIEnv* env = IDCache::GetEnvForThread(); JNIEnv* env = IDCache::GetEnvForThread();
// Execute the Java method. // Execute the Java method.
jboolean result = env->CallStaticBooleanMethod( jboolean result = env->CallStaticBooleanMethod(
IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), env->NewStringUTF(caption), IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), ToJString(env, caption),
env->NewStringUTF(text), yes_no ? JNI_TRUE : JNI_FALSE); ToJString(env, text), yes_no ? JNI_TRUE : JNI_FALSE);
return result != JNI_FALSE; return result != JNI_FALSE;
} }
@ -84,8 +74,8 @@ static std::string DisplayAlertPrompt(const char* caption, const char* text, int
JNIEnv* env = IDCache::GetEnvForThread(); JNIEnv* env = IDCache::GetEnvForThread();
jstring value = reinterpret_cast<jstring>(env->CallStaticObjectMethod( jstring value = reinterpret_cast<jstring>(env->CallStaticObjectMethod(
IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertPrompt(), IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertPrompt(), ToJString(env, caption),
env->NewStringUTF(caption), env->NewStringUTF(text), buttonConfig)); ToJString(env, text), buttonConfig));
return GetJString(env, value); return GetJString(env, value);
} }

View File

@ -8,6 +8,8 @@
#include <cstdlib> #include <cstdlib>
#include <locale> #include <locale>
#include <sstream> #include <sstream>
#include <string>
#include <string_view>
#include "common/common_paths.h" #include "common/common_paths.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/string_util.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; return result;
} }
std::string UTF16ToUTF8(const std::u16string& input) { std::string UTF16ToUTF8(std::u16string_view input) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, 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<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
return convert.from_bytes(input); return convert.from_bytes(input.data(), input.data() + input.size());
} }
#ifdef _WIN32 #ifdef _WIN32

View File

@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/swap.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, [[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src,
const std::string& dest); const std::string& dest);
[[nodiscard]] std::string UTF16ToUTF8(const std::u16string& input); [[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input);
[[nodiscard]] std::u16string UTF8ToUTF16(const std::string& input); [[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input);
#ifdef _WIN32 #ifdef _WIN32
[[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input); [[nodiscard]] std::string UTF16ToUTF8(const std::wstring& input);