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