diff --git a/src/java/String.cxx b/src/java/String.cxx index d072b818f..71a99f177 100644 --- a/src/java/String.cxx +++ b/src/java/String.cxx @@ -35,13 +35,8 @@ char * Java::String::CopyTo(JNIEnv *env, jstring value, char *buffer, size_t max_size) noexcept { - const char *p = env->GetStringUTFChars(value, nullptr); - if (p == nullptr) - return nullptr; - - char *result = CopyTruncateString(buffer, p, max_size); - env->ReleaseStringUTFChars(value, p); - return result; + return CopyTruncateString(buffer, GetUTFChars(env, value).c_str(), + max_size); } std::string @@ -50,13 +45,5 @@ Java::String::ToString(JNIEnv *env, jstring s) noexcept assert(env != nullptr); assert(s != nullptr); - const char *p = env->GetStringUTFChars(s, nullptr); - if (p == nullptr) - return std::string(); - - AtScopeExit(env, s, p) { - env->ReleaseStringUTFChars(s, p); - }; - - return std::string(p); + return std::string(GetUTFChars(env, s).c_str()); } diff --git a/src/java/String.hxx b/src/java/String.hxx index c73a32c7f..f60e7abc7 100644 --- a/src/java/String.hxx +++ b/src/java/String.hxx @@ -39,6 +39,46 @@ namespace Java { +class StringUTFChars { + JNIEnv *env; + jstring string; + const char *chars = nullptr; + +public: + StringUTFChars() noexcept = default; + StringUTFChars(std::nullptr_t) noexcept {} + + StringUTFChars(JNIEnv *_env, + const jstring _string, + const char *const _chars) noexcept + :env(_env), string(_string), chars(_chars) {} + + StringUTFChars(StringUTFChars &&src) noexcept + :env(src.env), string(src.string), + chars(std::exchange(src.chars, nullptr)) {} + + ~StringUTFChars() noexcept { + if (chars != nullptr) + env->ReleaseStringUTFChars(string, chars); + } + + StringUTFChars &operator=(StringUTFChars &&src) noexcept { + using std::swap; + swap(env, src.env); + swap(string, src.string); + swap(chars, src.chars); + return *this; + } + + const char *c_str() const noexcept { + return chars; + } + + operator bool() const noexcept { + return chars != nullptr; + } +}; + /** * Wrapper for a local "jstring" reference. */ @@ -49,6 +89,14 @@ public: String(JNIEnv *_env, const char *_value) noexcept :LocalRef(_env, _env->NewStringUTF(_value)) {} + static StringUTFChars GetUTFChars(JNIEnv *env, jstring s) noexcept { + return {env, s, env->GetStringUTFChars(s, nullptr)}; + } + + StringUTFChars GetUTFChars() const noexcept { + return GetUTFChars(GetEnv(), Get()); + } + /** * Copy the value to the specified buffer. Truncates * the value if it does not fit into the buffer.