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