1 /* 2 * Copyright (C) 2010 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 #pragma once 18 19 #include <stddef.h> 20 21 #include <jni.h> 22 23 #include "nativehelper_utils.h" 24 25 #ifdef POINTER_TYPE 26 #error POINTER_TYPE is defined. 27 #else 28 #define POINTER_TYPE(T) T* /* NOLINT */ 29 #endif 30 31 #ifdef REFERENCE_TYPE 32 #error REFERENCE_TYPE is defined. 33 #else 34 #define REFERENCE_TYPE(T) T& /* NOLINT */ 35 #endif 36 37 // ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO, 38 // ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide 39 // convenient read-only access to Java arrays from JNI code. This is cheaper than read-write 40 // access and should be used by default. 41 #define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \ 42 class Scoped ## NAME ## ArrayRO { \ 43 public: \ 44 explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \ 45 : mEnv(env), mJavaArray(nullptr), mRawArray(nullptr), mSize(0) {} \ 46 Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \ 47 : mEnv(env) { \ 48 if (javaArray == nullptr) { \ 49 mJavaArray = nullptr; \ 50 mSize = 0; \ 51 mRawArray = nullptr; \ 52 jniThrowNullPointerException(mEnv); \ 53 } else { \ 54 reset(javaArray); \ 55 } \ 56 } \ 57 ~Scoped ## NAME ## ArrayRO() { \ 58 if (mRawArray != nullptr && mRawArray != mBuffer) { \ 59 mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \ 60 } \ 61 } \ 62 void reset(PRIMITIVE_TYPE ## Array javaArray) { \ 63 mJavaArray = javaArray; \ 64 mSize = mEnv->GetArrayLength(mJavaArray); \ 65 if (mSize <= buffer_size) { \ 66 mEnv->Get ## NAME ## ArrayRegion(mJavaArray, 0, mSize, mBuffer); \ 67 mRawArray = mBuffer; \ 68 } else { \ 69 mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, nullptr); \ 70 } \ 71 } \ 72 const PRIMITIVE_TYPE* get() const { return mRawArray; } \ 73 PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \ 74 const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \ 75 size_t size() const { return mSize; } \ 76 private: \ 77 static const jsize buffer_size = 1024; \ 78 JNIEnv* const mEnv; \ 79 PRIMITIVE_TYPE ## Array mJavaArray; \ 80 POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \ 81 jsize mSize; \ 82 PRIMITIVE_TYPE mBuffer[buffer_size]; \ 83 DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRO); \ 84 } 85 86 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean); 87 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte); 88 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char); 89 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double); 90 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float); 91 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int); 92 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long); 93 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short); 94 95 #undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO 96 97 // ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW, 98 // ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide 99 // convenient read-write access to Java arrays from JNI code. These are more expensive, 100 // since they entail a copy back onto the Java heap, and should only be used when necessary. 101 #define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \ 102 class Scoped ## NAME ## ArrayRW { \ 103 public: \ 104 explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \ 105 : mEnv(env), mJavaArray(nullptr), mRawArray(nullptr) {} \ 106 Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \ 107 : mEnv(env), mJavaArray(javaArray), mRawArray(nullptr) { \ 108 if (mJavaArray == nullptr) { \ 109 jniThrowNullPointerException(mEnv); \ 110 } else { \ 111 mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, nullptr); \ 112 } \ 113 } \ 114 ~Scoped ## NAME ## ArrayRW() { \ 115 if (mRawArray) { \ 116 mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \ 117 } \ 118 } \ 119 void reset(PRIMITIVE_TYPE ## Array javaArray) { \ 120 mJavaArray = javaArray; \ 121 mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, nullptr); \ 122 } \ 123 const PRIMITIVE_TYPE* get() const { return mRawArray; } \ 124 PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \ 125 const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \ 126 POINTER_TYPE(PRIMITIVE_TYPE) get() { return mRawArray; } \ 127 REFERENCE_TYPE(PRIMITIVE_TYPE) operator[](size_t n) { return mRawArray[n]; } \ 128 size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \ 129 private: \ 130 JNIEnv* const mEnv; \ 131 PRIMITIVE_TYPE ## Array mJavaArray; \ 132 POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \ 133 DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRW); \ 134 } 135 136 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean); 137 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte); 138 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char); 139 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double); 140 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float); 141 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int); 142 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long); 143 INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short); 144 145 #undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW 146 #undef POINTER_TYPE 147 #undef REFERENCE_TYPE 148 149