local_ref<jstring> make_jstring(const char* utf8) { if (!utf8) { return {}; } const auto env = internal::getEnv(); size_t len; size_t modlen = detail::modifiedLength(reinterpret_cast<const uint8_t*>(utf8), &len); jstring result; if (modlen == len) { // The only difference between utf8 and modifiedUTF8 is in encoding 4-byte UTF8 chars // and '\0' that is encoded on 2 bytes. // // Since modifiedUTF8-encoded string can be no shorter than it's UTF8 conterpart we // know that if those two strings are of the same length we don't need to do any // conversion -> no 4-byte chars nor '\0'. result = env->NewStringUTF(utf8); } else { auto modified = std::vector<char>(modlen + 1); // allocate extra byte for \0 detail::utf8ToModifiedUTF8( reinterpret_cast<const uint8_t*>(utf8), len, reinterpret_cast<uint8_t*>(modified.data()), modified.size()); result = env->NewStringUTF(modified.data()); } FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); return adopt_local(result); }
size_t JByteBuffer::getDirectSize() const { if (!self()) { throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException"); } int size = Environment::current()->GetDirectBufferCapacity(self()); FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); if (size < 0) { throw std::runtime_error( isDirect() ? "Attempt to get direct size of non-direct byte buffer." : "Error getting direct size of byte buffer."); } return static_cast<size_t>(size); }
uint8_t* JByteBuffer::getDirectBytes() const { if (!self()) { throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException"); } void* bytes = Environment::current()->GetDirectBufferAddress(self()); FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); if (!bytes) { throw std::runtime_error( isDirect() ? "Attempt to get direct bytes of non-direct byte buffer." : "Error getting direct bytes of byte buffer."); } return static_cast<uint8_t*>(bytes); }
local_ref<JByteBuffer> JByteBuffer::wrapBytes(uint8_t* data, size_t size) { // env->NewDirectByteBuffer requires that size is positive. Android's // dalvik returns an invalid result and Android's art aborts if size == 0. // Workaround this by using a slow path through Java in that case. if (!size) { return createEmpty(); } auto res = adopt_local(static_cast<javaobject>(Environment::current()->NewDirectByteBuffer(data, size))); FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); if (!res) { throw std::runtime_error("Direct byte buffers are unsupported."); } return res; }