1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SCOPED_NULLABLE_PRIMITIVE_ARRAY_H 18 #define SCOPED_NULLABLE_PRIMITIVE_ARRAY_H 19 20 #include <jni.h> 21 22 namespace android { 23 24 #define ARRAY_TRAITS(ARRAY_TYPE, POINTER_TYPE, NAME) \ 25 class NAME ## ArrayTraits { \ 26 public: \ 27 static constexpr void getArrayRegion(JNIEnv* env, ARRAY_TYPE array, size_t start, \ 28 size_t len, POINTER_TYPE out) { \ 29 env->Get ## NAME ## ArrayRegion(array, start, len, out); \ 30 } \ 31 \ 32 static constexpr POINTER_TYPE getArrayElements(JNIEnv* env, ARRAY_TYPE array) { \ 33 return env->Get ## NAME ## ArrayElements(array, nullptr); \ 34 } \ 35 \ 36 static constexpr void releaseArrayElements(JNIEnv* env, ARRAY_TYPE array, \ 37 POINTER_TYPE buffer, jint mode) { \ 38 env->Release ## NAME ## ArrayElements(array, buffer, mode); \ 39 } \ 40 }; \ 41 42 ARRAY_TRAITS(jbooleanArray, jboolean*, Boolean) 43 ARRAY_TRAITS(jbyteArray, jbyte*, Byte) 44 ARRAY_TRAITS(jcharArray, jchar*, Char) 45 ARRAY_TRAITS(jdoubleArray, jdouble*, Double) 46 ARRAY_TRAITS(jfloatArray, jfloat*, Float) 47 ARRAY_TRAITS(jintArray, jint*, Int) 48 ARRAY_TRAITS(jlongArray, jlong*, Long) 49 ARRAY_TRAITS(jshortArray, jshort*, Short) 50 51 #undef ARRAY_TRAITS 52 53 template<typename JavaArrayType, typename PrimitiveType, class Traits, size_t preallocSize = 10> 54 class ScopedArrayRO { 55 public: 56 ScopedArrayRO(JNIEnv* env, JavaArrayType javaArray) : mEnv(env), mJavaArray(javaArray) { 57 if (mJavaArray == nullptr) { 58 mSize = 0; 59 mRawArray = nullptr; 60 } else { 61 mSize = mEnv->GetArrayLength(mJavaArray); 62 if (mSize <= preallocSize) { 63 Traits::getArrayRegion(mEnv, mJavaArray, 0, mSize, mBuffer); 64 mRawArray = mBuffer; 65 } else { 66 mRawArray = Traits::getArrayElements(mEnv, mJavaArray); 67 } 68 } 69 } 70 71 ~ScopedArrayRO() { 72 if (mRawArray != nullptr && mRawArray != mBuffer) { 73 Traits::releaseArrayElements(mEnv, mJavaArray, mRawArray, JNI_ABORT); 74 } 75 } 76 77 const PrimitiveType* get() const { return mRawArray; } 78 const PrimitiveType& operator[](size_t n) const { return mRawArray[n]; } 79 size_t size() const { return mSize; } 80 81 private: 82 JNIEnv* const mEnv; 83 JavaArrayType mJavaArray; 84 PrimitiveType* mRawArray; 85 size_t mSize; 86 PrimitiveType mBuffer[preallocSize]; 87 DISALLOW_COPY_AND_ASSIGN(ScopedArrayRO); 88 }; 89 90 // ScopedNullable***ArrayRO provide convenient read-only access to Java array from JNI code. 91 // These accept nullptr. In that case, get() returns nullptr and size() returns 0. 92 using ScopedNullableBooleanArrayRO = ScopedArrayRO<jbooleanArray, jboolean, BooleanArrayTraits>; 93 using ScopedNullableByteArrayRO = ScopedArrayRO<jbyteArray, jbyte, ByteArrayTraits>; 94 using ScopedNullableCharArrayRO = ScopedArrayRO<jcharArray, jchar, CharArrayTraits>; 95 using ScopedNullableDoubleArrayRO = ScopedArrayRO<jdoubleArray, jdouble, DoubleArrayTraits>; 96 using ScopedNullableFloatArrayRO = ScopedArrayRO<jfloatArray, jfloat, FloatArrayTraits>; 97 using ScopedNullableIntArrayRO = ScopedArrayRO<jintArray, jint, IntArrayTraits>; 98 using ScopedNullableLongArrayRO = ScopedArrayRO<jlongArray, jlong, LongArrayTraits>; 99 using ScopedNullableShortArrayRO = ScopedArrayRO<jshortArray, jshort, ShortArrayTraits>; 100 101 } // namespace android 102 103 #endif // SCOPED_NULLABLE_PRIMITIVE_ARRAY_H 104