Commit f3b6b315 authored by Aleksey Konovalov's avatar Aleksey Konovalov

undefined behaviour fixed in the wstring encoding functions

parent 209e2f2e
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <cstring> #include <cstring>
static_assert(sizeof(jlong) >= sizeof(void*), "must be able to fit a void* into a jlong"); static_assert(sizeof(jlong) >= sizeof(void*), "must be able to fit a void* into a jlong");
static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "wchar_t must be represented by UTF-16 or UTF-32 encoding");
namespace djinni { namespace djinni {
...@@ -371,11 +372,37 @@ jstring jniStringFromUTF8(JNIEnv * env, const std::string & str) { ...@@ -371,11 +372,37 @@ jstring jniStringFromUTF8(JNIEnv * env, const std::string & str) {
return res; return res;
} }
jstring jniStringFromWString(JNIEnv * env, const std::wstring & str) { template<int wcharTypeSize>
static std::u16string implWStringToUTF16(const std::wstring & str);
template<>
inline std::u16string implWStringToUTF16<2>(const std::wstring & str) {
// case when wchar_t is represented by utf-16 encoding
return std::u16string(str.begin(), str.end());
}
template<>
inline std::u16string implWStringToUTF16<4>(const std::wstring & str) {
// case when wchar_t is represented by utf-32 encoding
std::u16string utf16;
utf16.reserve(str.size());
for(size_t i = 0; i < str.size(); ++i)
utf16_encode(static_cast<char32_t>(str[i]), utf16);
return utf16;
}
inline std::u16string wstringToUTF16(const std::wstring & str) {
// hide "defined but not used" warnings
(void)implWStringToUTF16<2>;
(void)implWStringToUTF16<4>;
return implWStringToUTF16<sizeof(wchar_t)>(str);
}
std::u16string utf16(str.begin(), str.end());; jstring jniStringFromWString(JNIEnv * env, const std::wstring & str) {
std::u16string utf16 = wstringToUTF16(str);
const size_t len = utf16.size();
jstring res = env->NewString( jstring res = env->NewString(
reinterpret_cast<const jchar *>(utf16.data()), utf16.length()); reinterpret_cast<const jchar *>(utf16.data()), len);
DJINNI_ASSERT(res, env); DJINNI_ASSERT(res, env);
return res; return res;
} }
...@@ -450,6 +477,32 @@ std::string jniUTF8FromString(JNIEnv * env, const jstring jstr) { ...@@ -450,6 +477,32 @@ std::string jniUTF8FromString(JNIEnv * env, const jstring jstr) {
return out; return out;
} }
template<int wcharTypeSize>
static std::wstring implUTF16ToWString(const char16_t * data, size_t length);
template<>
inline std::wstring implUTF16ToWString<2>(const char16_t * data, size_t length) {
// case when wchar_t is represented by utf-16 encoding
return std::wstring(data, data + length);
}
template<>
inline std::wstring implUTF16ToWString<4>(const char16_t * data, size_t length) {
// case when wchar_t is represented by utf-32 encoding
std::wstring result;
result.reserve(length);
for (size_t i = 0; i < length; )
result += static_cast<wchar_t>(utf16_decode(data, i));
return result;
}
inline std::wstring UTF16ToWString(const char16_t * data, size_t length) {
// hide "defined but not used" warnings
(void)implUTF16ToWString<2>;
(void)implUTF16ToWString<4>;
return implUTF16ToWString<sizeof(wchar_t)>(data, length);
}
std::wstring jniWStringFromString(JNIEnv * env, const jstring jstr) { std::wstring jniWStringFromString(JNIEnv * env, const jstring jstr) {
DJINNI_ASSERT(jstr, env); DJINNI_ASSERT(jstr, env);
const jsize length = env->GetStringLength(jstr); const jsize length = env->GetStringLength(jstr);
...@@ -458,10 +511,8 @@ std::wstring jniWStringFromString(JNIEnv * env, const jstring jstr) { ...@@ -458,10 +511,8 @@ std::wstring jniWStringFromString(JNIEnv * env, const jstring jstr) {
const auto deleter = [env, jstr] (const jchar * c) { env->ReleaseStringChars(jstr, c); }; const auto deleter = [env, jstr] (const jchar * c) { env->ReleaseStringChars(jstr, c); };
std::unique_ptr<const jchar, decltype(deleter)> ptr(env->GetStringChars(jstr, nullptr), std::unique_ptr<const jchar, decltype(deleter)> ptr(env->GetStringChars(jstr, nullptr),
deleter); deleter);
const char16_t* data = reinterpret_cast<const char16_t *>(ptr.get());
const char16_t* begin = reinterpret_cast<const char16_t *>(ptr.get()); return UTF16ToWString(data, length);
const char16_t* end = begin + length;
return std::wstring(begin, end);
} }
DJINNI_WEAK_DEFINITION DJINNI_WEAK_DEFINITION
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment