| /* |
| * |
| * Copyright (c) 2021-2024 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <cstdint> |
| #include <jni.h> |
| #include <lib/support/CHIPJNIError.h> |
| #include <lib/support/JniReferences.h> |
| #include <lib/support/Span.h> |
| #include <string> |
| |
| namespace chip { |
| /// Exposes the underlying UTF string from a jni string |
| class JniUtfString |
| { |
| public: |
| JniUtfString(JNIEnv * env, jstring string) : mEnv(env), mString(string) |
| { |
| if (string == nullptr) |
| { |
| return; |
| } |
| mChars = env->GetStringUTFChars(string, 0); |
| mDataLength = env->GetStringUTFLength(string); |
| } |
| ~JniUtfString() |
| { |
| if (mString != nullptr) |
| { |
| mEnv->ReleaseStringUTFChars(mString, mChars); |
| } |
| } |
| |
| const char * c_str() const { return mChars; } |
| |
| chip::CharSpan charSpan() const { return chip::CharSpan(c_str(), static_cast<size_t>(size())); } |
| |
| jsize size() const { return mDataLength; } |
| |
| private: |
| JNIEnv * mEnv; |
| jstring mString; |
| const char * mChars; |
| jsize mDataLength; |
| }; |
| |
| /// Exposes the underlying binary data from a jni byte array |
| class JniByteArray |
| { |
| public: |
| JniByteArray(JNIEnv * env, jbyteArray array) : |
| mEnv(env), mArray(array), mData(env->GetByteArrayElements(array, nullptr)), mDataLength(env->GetArrayLength(array)) |
| {} |
| ~JniByteArray() { mEnv->ReleaseByteArrayElements(mArray, mData, 0); } |
| |
| const jbyte * data() const { return mData; } |
| |
| chip::ByteSpan byteSpan() const |
| { |
| return chip::ByteSpan(reinterpret_cast<const uint8_t *>(data()), static_cast<size_t>(size())); |
| } |
| |
| jsize size() const { return mDataLength; } |
| |
| private: |
| JNIEnv * mEnv; |
| jbyteArray mArray; |
| jbyte * mData; |
| jsize mDataLength; |
| }; |
| |
| /// wrap a c-string as a jni string |
| class UtfString |
| { |
| public: |
| UtfString(JNIEnv * env, const char * data) : mEnv(env) |
| { |
| jstring localRef = data != nullptr ? mEnv->NewStringUTF(data) : nullptr; |
| if (localRef == nullptr) |
| { |
| return; |
| } |
| mData = static_cast<jstring>(env->NewGlobalRef(localRef)); |
| } |
| |
| UtfString(JNIEnv * env, chip::CharSpan data) : mEnv(env) |
| { |
| std::string str(data.data(), data.size()); |
| jstring localRef = env->NewStringUTF(str.c_str()); |
| if (localRef == nullptr) |
| { |
| return; |
| } |
| mData = static_cast<jstring>(env->NewGlobalRef(localRef)); |
| } |
| |
| ~UtfString() |
| { |
| if (mEnv != nullptr && mData != nullptr) |
| { |
| mEnv->DeleteGlobalRef(mData); |
| mData = nullptr; |
| } |
| } |
| |
| jstring jniValue() { return mData; } |
| |
| private: |
| JNIEnv * mEnv = nullptr; |
| jstring mData = nullptr; |
| }; |
| |
| /// wrap a byte array as a JNI byte array |
| class ByteArray |
| { |
| public: |
| ByteArray(JNIEnv * env, const jbyte * data, jsize dataLen) : mEnv(env) |
| { |
| jbyteArray localRef = data != nullptr ? mEnv->NewByteArray(dataLen) : nullptr; |
| if (localRef == nullptr) |
| { |
| return; |
| } |
| env->SetByteArrayRegion(localRef, 0, dataLen, data); |
| mArray = static_cast<jbyteArray>(env->NewGlobalRef(localRef)); |
| } |
| |
| ByteArray(JNIEnv * env, chip::ByteSpan data) : mEnv(env) |
| { |
| jbyteArray localRef = mEnv->NewByteArray(static_cast<jsize>(data.size())); |
| if (localRef == nullptr) |
| { |
| return; |
| } |
| env->SetByteArrayRegion(localRef, 0, static_cast<jsize>(data.size()), reinterpret_cast<const jbyte *>(data.data())); |
| mArray = static_cast<jbyteArray>(env->NewGlobalRef(localRef)); |
| } |
| |
| ~ByteArray() |
| { |
| if (mEnv != nullptr && mArray != nullptr) |
| { |
| mEnv->DeleteGlobalRef(mArray); |
| } |
| } |
| |
| jbyteArray jniValue() { return mArray; } |
| |
| private: |
| JNIEnv * mEnv = nullptr; |
| jbyteArray mArray = nullptr; |
| }; |
| |
| // Manages an pre-existing global reference to a jobject. |
| class JniGlobalRefWrapper |
| { |
| public: |
| explicit JniGlobalRefWrapper(jobject mGlobalRef) : mGlobalRef(mGlobalRef) {} |
| ~JniGlobalRefWrapper() |
| { |
| chip::JniReferences::GetInstance().GetEnvForCurrentThread()->DeleteGlobalRef(mGlobalRef); |
| mGlobalRef = nullptr; |
| } |
| jobject classRef() { return mGlobalRef; } |
| |
| private: |
| jobject mGlobalRef = nullptr; |
| }; |
| } // namespace chip |