Merge "Nativehelper: Export header-only version of helpers"
am: 7678ec555b
Change-Id: I676c6db9a8843daf5d391ef0e448a4138a021df5
diff --git a/Android.bp b/Android.bp
index a76b782..99a8597 100644
--- a/Android.bp
+++ b/Android.bp
@@ -20,6 +20,12 @@
}
cc_library_headers {
+ name: "libnativehelper_header_only",
+ host_supported: true,
+ export_include_dirs: ["header_only_include"],
+}
+
+cc_library_headers {
name: "jni_platform_headers",
host_supported: true,
export_include_dirs: ["platform_include"],
@@ -41,8 +47,16 @@
},
},
- header_libs: ["jni_headers", "jni_platform_headers"],
- export_header_lib_headers: ["jni_headers"],
+ header_libs: [
+ "jni_headers",
+ "libnativehelper_header_only",
+ "jni_platform_headers"
+ ],
+ export_header_lib_headers: [
+ "jni_headers",
+ "libnativehelper_header_only",
+ "jni_platform_headers",
+ ],
shared_libs: [
"liblog",
@@ -52,7 +66,7 @@
"-fvisibility=protected",
],
- export_include_dirs: ["include", "platform_include"],
+ export_include_dirs: ["include"],
}
//
@@ -64,11 +78,15 @@
cc_library_shared {
name: "libnativehelper_compat_libc++",
export_include_dirs: [
+ "header_only_include",
"include",
"include/nativehelper", // TODO(b/63762847): remove
],
cflags: ["-Werror"],
- include_dirs: ["libnativehelper/platform_include"],
+ include_dirs: [
+ "libnativehelper/header_only_include",
+ "libnativehelper/platform_include",
+ ],
srcs: [
"JNIHelp.cpp",
"JniConstants.cpp",
diff --git a/header_only_include/nativehelper/nativehelper_utils.h b/header_only_include/nativehelper/nativehelper_utils.h
new file mode 100644
index 0000000..da0c647
--- /dev/null
+++ b/header_only_include/nativehelper/nativehelper_utils.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef NATIVEHELPER_MACROS_H_
+#define NATIVEHELPER_MACROS_H_
+
+#if defined(__cplusplus)
+
+#if !defined(DISALLOW_COPY_AND_ASSIGN)
+// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. It goes in the private:
+// declarations in a class.
+#if __cplusplus >= 201103L
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+#else
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+#endif // __has_feature(cxx_deleted_functions)
+#endif // !defined(DISALLOW_COPY_AND_ASSIGN)
+
+#ifndef NATIVEHELPER_JNIHELP_H_
+// This seems a header-only include. Provide NPE throwing.
+static inline int jniThrowNullPointerException(JNIEnv* env, const char* msg) {
+ if (env->ExceptionCheck()) {
+ // Drop any pending exception.
+ env->ExceptionClear();
+ }
+
+ jclass e_class = env->FindClass("java/lang/NullPointerException");
+ if (e_class == nullptr) {
+ return -1;
+ }
+
+ if (env->ThrowNew(e_class, msg) != JNI_OK) {
+ env->DeleteLocalRef(e_class);
+ return -1;
+ }
+
+ env->DeleteLocalRef(e_class);
+ return 0;
+}
+#endif // NATIVEHELPER_JNIHELP_H_
+
+#endif // defined(__cplusplus)
+
+#endif // NATIVEHELPER_MACROS_H_
diff --git a/header_only_include/nativehelper/scoped_bytes.h b/header_only_include/nativehelper/scoped_bytes.h
new file mode 100644
index 0000000..abeb395
--- /dev/null
+++ b/header_only_include/nativehelper/scoped_bytes.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SCOPED_BYTES_H_
+#define SCOPED_BYTES_H_
+
+#include "jni.h"
+#include "nativehelper_utils.h"
+
+/**
+ * ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and
+ * ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed
+ * by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s.
+ * (On Android, this last group only contains MappedByteBuffers.)
+ */
+template<bool readOnly>
+class ScopedBytes {
+public:
+ ScopedBytes(JNIEnv* env, jobject object)
+ : mEnv(env), mObject(object), mByteArray(NULL), mPtr(NULL)
+ {
+ if (mObject == NULL) {
+ jniThrowNullPointerException(mEnv, NULL);
+ } else if (mEnv->IsInstanceOf(mObject, JniConstants::byteArrayClass)) {
+ mByteArray = reinterpret_cast<jbyteArray>(mObject);
+ mPtr = mEnv->GetByteArrayElements(mByteArray, NULL);
+ } else {
+ mPtr = reinterpret_cast<jbyte*>(mEnv->GetDirectBufferAddress(mObject));
+ }
+ }
+
+ ~ScopedBytes() {
+ if (mByteArray != NULL) {
+ mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0);
+ }
+ }
+
+private:
+ JNIEnv* const mEnv;
+ const jobject mObject;
+ jbyteArray mByteArray;
+
+protected:
+ jbyte* mPtr;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedBytes);
+};
+
+class ScopedBytesRO : public ScopedBytes<true> {
+public:
+ ScopedBytesRO(JNIEnv* env, jobject object) : ScopedBytes<true>(env, object) {}
+ const jbyte* get() const {
+ return mPtr;
+ }
+};
+
+class ScopedBytesRW : public ScopedBytes<false> {
+public:
+ ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes<false>(env, object) {}
+ jbyte* get() {
+ return mPtr;
+ }
+};
+
+#endif // SCOPED_BYTES_H_
diff --git a/header_only_include/nativehelper/scoped_local_frame.h b/header_only_include/nativehelper/scoped_local_frame.h
new file mode 100644
index 0000000..70797f4
--- /dev/null
+++ b/header_only_include/nativehelper/scoped_local_frame.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SCOPED_LOCAL_FRAME_H_
+#define SCOPED_LOCAL_FRAME_H_
+
+#include "jni.h"
+
+class ScopedLocalFrame {
+public:
+ explicit ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
+ mEnv->PushLocalFrame(128);
+ }
+
+ ~ScopedLocalFrame() {
+ mEnv->PopLocalFrame(NULL);
+ }
+
+private:
+ JNIEnv* const mEnv;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedLocalFrame);
+};
+
+#endif // SCOPED_LOCAL_FRAME_H_
diff --git a/header_only_include/nativehelper/scoped_local_ref.h b/header_only_include/nativehelper/scoped_local_ref.h
new file mode 100644
index 0000000..458c87f
--- /dev/null
+++ b/header_only_include/nativehelper/scoped_local_ref.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SCOPED_LOCAL_REF_H_
+#define SCOPED_LOCAL_REF_H_
+
+#include <cstddef>
+
+#include "jni.h"
+#include "nativehelper_utils.h"
+
+// A smart pointer that deletes a JNI local reference when it goes out of scope.
+template<typename T>
+class ScopedLocalRef {
+public:
+ ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
+ }
+
+ ~ScopedLocalRef() {
+ reset();
+ }
+
+ void reset(T ptr = NULL) {
+ if (ptr != mLocalRef) {
+ if (mLocalRef != NULL) {
+ mEnv->DeleteLocalRef(mLocalRef);
+ }
+ mLocalRef = ptr;
+ }
+ }
+
+ T release() __attribute__((warn_unused_result)) {
+ T localRef = mLocalRef;
+ mLocalRef = NULL;
+ return localRef;
+ }
+
+ T get() const {
+ return mLocalRef;
+ }
+
+// Some better C++11 support.
+#if __cplusplus >= 201103L
+ // Move constructor.
+ ScopedLocalRef(ScopedLocalRef&& s) : mEnv(s.mEnv), mLocalRef(s.release()) {
+ }
+
+ explicit ScopedLocalRef(JNIEnv* env) : mEnv(env), mLocalRef(nullptr) {
+ }
+
+ // We do not expose an empty constructor as it can easily lead to errors
+ // using common idioms, e.g.:
+ // ScopedLocalRef<...> ref;
+ // ref.reset(...);
+
+ // Move assignment operator.
+ ScopedLocalRef& operator=(ScopedLocalRef&& s) {
+ reset(s.release());
+ mEnv = s.mEnv;
+ return *this;
+ }
+
+ // Allows "if (scoped_ref == nullptr)"
+ bool operator==(std::nullptr_t) const {
+ return mLocalRef == nullptr;
+ }
+
+ // Allows "if (scoped_ref != nullptr)"
+ bool operator!=(std::nullptr_t) const {
+ return mLocalRef != nullptr;
+ }
+#endif
+
+private:
+ JNIEnv* mEnv;
+ T mLocalRef;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef);
+};
+
+#endif // SCOPED_LOCAL_REF_H_
diff --git a/header_only_include/nativehelper/scoped_primitive_array.h b/header_only_include/nativehelper/scoped_primitive_array.h
new file mode 100644
index 0000000..d6840c2
--- /dev/null
+++ b/header_only_include/nativehelper/scoped_primitive_array.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SCOPED_PRIMITIVE_ARRAY_H_
+#define SCOPED_PRIMITIVE_ARRAY_H_
+
+#include "jni.h"
+#include "nativehelper_utils.h"
+
+#ifdef POINTER_TYPE
+#error POINTER_TYPE is defined.
+#else
+#define POINTER_TYPE(T) T* /* NOLINT */
+#endif
+
+#ifdef REFERENCE_TYPE
+#error REFERENCE_TYPE is defined.
+#else
+#define REFERENCE_TYPE(T) T& /* NOLINT */
+#endif
+
+// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
+// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
+// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
+// access and should be used by default.
+#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
+ class Scoped ## NAME ## ArrayRO { \
+ public: \
+ explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \
+ : mEnv(env), mJavaArray(NULL), mRawArray(NULL), mSize(0) {} \
+ Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
+ : mEnv(env) { \
+ if (javaArray == NULL) { \
+ mJavaArray = NULL; \
+ mSize = 0; \
+ mRawArray = NULL; \
+ jniThrowNullPointerException(mEnv, NULL); \
+ } else { \
+ reset(javaArray); \
+ } \
+ } \
+ ~Scoped ## NAME ## ArrayRO() { \
+ if (mRawArray != NULL && mRawArray != mBuffer) { \
+ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
+ } \
+ } \
+ void reset(PRIMITIVE_TYPE ## Array javaArray) { \
+ mJavaArray = javaArray; \
+ mSize = mEnv->GetArrayLength(mJavaArray); \
+ if (mSize <= buffer_size) { \
+ mEnv->Get ## NAME ## ArrayRegion(mJavaArray, 0, mSize, mBuffer); \
+ mRawArray = mBuffer; \
+ } else { \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ } \
+ const PRIMITIVE_TYPE* get() const { return mRawArray; } \
+ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
+ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
+ size_t size() const { return mSize; } \
+ private: \
+ static const jsize buffer_size = 1024; \
+ JNIEnv* const mEnv; \
+ PRIMITIVE_TYPE ## Array mJavaArray; \
+ POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
+ jsize mSize; \
+ PRIMITIVE_TYPE mBuffer[buffer_size]; \
+ DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRO); \
+ }
+
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
+
+#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
+
+// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
+// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
+// convenient read-write access to Java arrays from JNI code. These are more expensive,
+// since they entail a copy back onto the Java heap, and should only be used when necessary.
+#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
+ class Scoped ## NAME ## ArrayRW { \
+ public: \
+ explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \
+ : mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
+ Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
+ : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
+ if (mJavaArray == NULL) { \
+ jniThrowNullPointerException(mEnv, NULL); \
+ } else { \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ } \
+ ~Scoped ## NAME ## ArrayRW() { \
+ if (mRawArray) { \
+ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
+ } \
+ } \
+ void reset(PRIMITIVE_TYPE ## Array javaArray) { \
+ mJavaArray = javaArray; \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ const PRIMITIVE_TYPE* get() const { return mRawArray; } \
+ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
+ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
+ POINTER_TYPE(PRIMITIVE_TYPE) get() { return mRawArray; } \
+ REFERENCE_TYPE(PRIMITIVE_TYPE) operator[](size_t n) { return mRawArray[n]; } \
+ size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
+ private: \
+ JNIEnv* const mEnv; \
+ PRIMITIVE_TYPE ## Array mJavaArray; \
+ POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
+ DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRW); \
+ }
+
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
+
+#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
+#undef POINTER_TYPE
+#undef REFERENCE_TYPE
+
+#endif // SCOPED_PRIMITIVE_ARRAY_H_
diff --git a/header_only_include/nativehelper/scoped_string_chars.h b/header_only_include/nativehelper/scoped_string_chars.h
new file mode 100644
index 0000000..4debb2a
--- /dev/null
+++ b/header_only_include/nativehelper/scoped_string_chars.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SCOPED_STRING_CHARS_H_
+#define SCOPED_STRING_CHARS_H_
+
+#include "jni.h"
+#include "nativehelper_utils.h"
+
+// A smart pointer that provides access to a jchar* given a JNI jstring.
+// Unlike GetStringChars, we throw NullPointerException rather than abort if
+// passed a null jstring, and get will return NULL.
+// This makes the correct idiom very simple:
+//
+// ScopedStringChars name(env, java_name);
+// if (name.get() == NULL) {
+// return NULL;
+// }
+class ScopedStringChars {
+ public:
+ ScopedStringChars(JNIEnv* env, jstring s) : env_(env), string_(s), size_(0) {
+ if (s == NULL) {
+ chars_ = NULL;
+ jniThrowNullPointerException(env, NULL);
+ } else {
+ chars_ = env->GetStringChars(string_, NULL);
+ if (chars_ != NULL) {
+ size_ = env->GetStringLength(string_);
+ }
+ }
+ }
+
+ ~ScopedStringChars() {
+ if (chars_ != NULL) {
+ env_->ReleaseStringChars(string_, chars_);
+ }
+ }
+
+ const jchar* get() const {
+ return chars_;
+ }
+
+ size_t size() const {
+ return size_;
+ }
+
+ const jchar& operator[](size_t n) const {
+ return chars_[n];
+ }
+
+ private:
+ JNIEnv* const env_;
+ const jstring string_;
+ const jchar* chars_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedStringChars);
+};
+
+#endif // SCOPED_STRING_CHARS_H_
diff --git a/header_only_include/nativehelper/scoped_utf_chars.h b/header_only_include/nativehelper/scoped_utf_chars.h
new file mode 100644
index 0000000..75cbe50
--- /dev/null
+++ b/header_only_include/nativehelper/scoped_utf_chars.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SCOPED_UTF_CHARS_H_
+#define SCOPED_UTF_CHARS_H_
+
+#include <string.h>
+
+#include "jni.h"
+#include "nativehelper_utils.h"
+
+// A smart pointer that provides read-only access to a Java string's UTF chars.
+// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
+// passed a null jstring, and c_str will return nullptr.
+// This makes the correct idiom very simple:
+//
+// ScopedUtfChars name(env, java_name);
+// if (name.c_str() == nullptr) {
+// return nullptr;
+// }
+class ScopedUtfChars {
+ public:
+ ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
+ if (s == nullptr) {
+ utf_chars_ = nullptr;
+ jniThrowNullPointerException(env, nullptr);
+ } else {
+ utf_chars_ = env->GetStringUTFChars(s, nullptr);
+ }
+ }
+
+ ScopedUtfChars(ScopedUtfChars&& rhs) :
+ env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
+ rhs.env_ = nullptr;
+ rhs.string_ = nullptr;
+ rhs.utf_chars_ = nullptr;
+ }
+
+ ~ScopedUtfChars() {
+ if (utf_chars_) {
+ env_->ReleaseStringUTFChars(string_, utf_chars_);
+ }
+ }
+
+ ScopedUtfChars& operator=(ScopedUtfChars&& rhs) {
+ if (this != &rhs) {
+ // Delete the currently owned UTF chars.
+ this->~ScopedUtfChars();
+
+ // Move the rhs ScopedUtfChars and zero it out.
+ env_ = rhs.env_;
+ string_ = rhs.string_;
+ utf_chars_ = rhs.utf_chars_;
+ rhs.env_ = nullptr;
+ rhs.string_ = nullptr;
+ rhs.utf_chars_ = nullptr;
+ }
+ return *this;
+ }
+
+ const char* c_str() const {
+ return utf_chars_;
+ }
+
+ size_t size() const {
+ return strlen(utf_chars_);
+ }
+
+ const char& operator[](size_t n) const {
+ return utf_chars_[n];
+ }
+
+ private:
+ JNIEnv* env_;
+ jstring string_;
+ const char* utf_chars_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
+};
+
+#endif // SCOPED_UTF_CHARS_H_
diff --git a/include/nativehelper/ScopedBytes.h b/include/nativehelper/ScopedBytes.h
index fec46e8..7cb2ad0 100644
--- a/include/nativehelper/ScopedBytes.h
+++ b/include/nativehelper/ScopedBytes.h
@@ -18,61 +18,6 @@
#define SCOPED_BYTES_H_included
#include "JNIHelp.h"
-
-/**
- * ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and
- * ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed
- * by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s.
- * (On Android, this last group only contains MappedByteBuffers.)
- */
-template<bool readOnly>
-class ScopedBytes {
-public:
- ScopedBytes(JNIEnv* env, jobject object)
- : mEnv(env), mObject(object), mByteArray(NULL), mPtr(NULL)
- {
- if (mObject == NULL) {
- jniThrowNullPointerException(mEnv, NULL);
- } else if (mEnv->IsInstanceOf(mObject, JniConstants::byteArrayClass)) {
- mByteArray = reinterpret_cast<jbyteArray>(mObject);
- mPtr = mEnv->GetByteArrayElements(mByteArray, NULL);
- } else {
- mPtr = reinterpret_cast<jbyte*>(mEnv->GetDirectBufferAddress(mObject));
- }
- }
-
- ~ScopedBytes() {
- if (mByteArray != NULL) {
- mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0);
- }
- }
-
-private:
- JNIEnv* const mEnv;
- const jobject mObject;
- jbyteArray mByteArray;
-
-protected:
- jbyte* mPtr;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(ScopedBytes);
-};
-
-class ScopedBytesRO : public ScopedBytes<true> {
-public:
- ScopedBytesRO(JNIEnv* env, jobject object) : ScopedBytes<true>(env, object) {}
- const jbyte* get() const {
- return mPtr;
- }
-};
-
-class ScopedBytesRW : public ScopedBytes<false> {
-public:
- ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes<false>(env, object) {}
- jbyte* get() {
- return mPtr;
- }
-};
+#include <nativehelper/scoped_bytes.h>
#endif // SCOPED_BYTES_H_included
diff --git a/include/nativehelper/ScopedLocalFrame.h b/include/nativehelper/ScopedLocalFrame.h
index a74611f..57873f2 100644
--- a/include/nativehelper/ScopedLocalFrame.h
+++ b/include/nativehelper/ScopedLocalFrame.h
@@ -17,22 +17,6 @@
#ifndef SCOPED_LOCAL_FRAME_H_included
#define SCOPED_LOCAL_FRAME_H_included
-#include "JNIHelp.h"
-
-class ScopedLocalFrame {
-public:
- explicit ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
- mEnv->PushLocalFrame(128);
- }
-
- ~ScopedLocalFrame() {
- mEnv->PopLocalFrame(NULL);
- }
-
-private:
- JNIEnv* const mEnv;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedLocalFrame);
-};
+#include <nativehelper/scoped_local_frame.h>
#endif // SCOPED_LOCAL_FRAME_H_included
diff --git a/include/nativehelper/ScopedLocalRef.h b/include/nativehelper/ScopedLocalRef.h
index 4018f20..0fb03d7 100644
--- a/include/nativehelper/ScopedLocalRef.h
+++ b/include/nativehelper/ScopedLocalRef.h
@@ -17,78 +17,7 @@
#ifndef SCOPED_LOCAL_REF_H_included
#define SCOPED_LOCAL_REF_H_included
-#include <cstddef>
-
-#include "jni.h"
-#include "JNIHelp.h" // for DISALLOW_COPY_AND_ASSIGN.
-
-// A smart pointer that deletes a JNI local reference when it goes out of scope.
-template<typename T>
-class ScopedLocalRef {
-public:
- ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
- }
-
- ~ScopedLocalRef() {
- reset();
- }
-
- void reset(T ptr = NULL) {
- if (ptr != mLocalRef) {
- if (mLocalRef != NULL) {
- mEnv->DeleteLocalRef(mLocalRef);
- }
- mLocalRef = ptr;
- }
- }
-
- T release() __attribute__((warn_unused_result)) {
- T localRef = mLocalRef;
- mLocalRef = NULL;
- return localRef;
- }
-
- T get() const {
- return mLocalRef;
- }
-
-// Some better C++11 support.
-#if __cplusplus >= 201103L
- // Move constructor.
- ScopedLocalRef(ScopedLocalRef&& s) : mEnv(s.mEnv), mLocalRef(s.release()) {
- }
-
- explicit ScopedLocalRef(JNIEnv* env) : mEnv(env), mLocalRef(nullptr) {
- }
-
- // We do not expose an empty constructor as it can easily lead to errors
- // using common idioms, e.g.:
- // ScopedLocalRef<...> ref;
- // ref.reset(...);
-
- // Move assignment operator.
- ScopedLocalRef& operator=(ScopedLocalRef&& s) {
- reset(s.release());
- mEnv = s.mEnv;
- return *this;
- }
-
- // Allows "if (scoped_ref == nullptr)"
- bool operator==(std::nullptr_t) const {
- return mLocalRef == nullptr;
- }
-
- // Allows "if (scoped_ref != nullptr)"
- bool operator!=(std::nullptr_t) const {
- return mLocalRef != nullptr;
- }
-#endif
-
-private:
- JNIEnv* mEnv;
- T mLocalRef;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef);
-};
+#include "JNIHelp.h"
+#include <nativehelper/scoped_local_ref.h>
#endif // SCOPED_LOCAL_REF_H_included
diff --git a/include/nativehelper/ScopedPrimitiveArray.h b/include/nativehelper/ScopedPrimitiveArray.h
index 46f1786..626b64f 100644
--- a/include/nativehelper/ScopedPrimitiveArray.h
+++ b/include/nativehelper/ScopedPrimitiveArray.h
@@ -18,129 +18,6 @@
#define SCOPED_PRIMITIVE_ARRAY_H_included
#include "JNIHelp.h"
-
-#ifdef POINTER_TYPE
-#error POINTER_TYPE is defined.
-#else
-#define POINTER_TYPE(T) T* /* NOLINT */
-#endif
-
-#ifdef REFERENCE_TYPE
-#error REFERENCE_TYPE is defined.
-#else
-#define REFERENCE_TYPE(T) T& /* NOLINT */
-#endif
-
-// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
-// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
-// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
-// access and should be used by default.
-#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
- class Scoped ## NAME ## ArrayRO { \
- public: \
- explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \
- : mEnv(env), mJavaArray(NULL), mRawArray(NULL), mSize(0) {} \
- Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
- : mEnv(env) { \
- if (javaArray == NULL) { \
- mJavaArray = NULL; \
- mSize = 0; \
- mRawArray = NULL; \
- jniThrowNullPointerException(mEnv, NULL); \
- } else { \
- reset(javaArray); \
- } \
- } \
- ~Scoped ## NAME ## ArrayRO() { \
- if (mRawArray != NULL && mRawArray != mBuffer) { \
- mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
- } \
- } \
- void reset(PRIMITIVE_TYPE ## Array javaArray) { \
- mJavaArray = javaArray; \
- mSize = mEnv->GetArrayLength(mJavaArray); \
- if (mSize <= buffer_size) { \
- mEnv->Get ## NAME ## ArrayRegion(mJavaArray, 0, mSize, mBuffer); \
- mRawArray = mBuffer; \
- } else { \
- mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
- } \
- } \
- const PRIMITIVE_TYPE* get() const { return mRawArray; } \
- PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
- const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
- size_t size() const { return mSize; } \
- private: \
- static const jsize buffer_size = 1024; \
- JNIEnv* const mEnv; \
- PRIMITIVE_TYPE ## Array mJavaArray; \
- POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
- jsize mSize; \
- PRIMITIVE_TYPE mBuffer[buffer_size]; \
- DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRO); \
- }
-
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
-
-#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
-
-// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
-// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
-// convenient read-write access to Java arrays from JNI code. These are more expensive,
-// since they entail a copy back onto the Java heap, and should only be used when necessary.
-#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
- class Scoped ## NAME ## ArrayRW { \
- public: \
- explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \
- : mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
- Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
- : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
- if (mJavaArray == NULL) { \
- jniThrowNullPointerException(mEnv, NULL); \
- } else { \
- mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
- } \
- } \
- ~Scoped ## NAME ## ArrayRW() { \
- if (mRawArray) { \
- mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
- } \
- } \
- void reset(PRIMITIVE_TYPE ## Array javaArray) { \
- mJavaArray = javaArray; \
- mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
- } \
- const PRIMITIVE_TYPE* get() const { return mRawArray; } \
- PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
- const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
- POINTER_TYPE(PRIMITIVE_TYPE) get() { return mRawArray; } \
- REFERENCE_TYPE(PRIMITIVE_TYPE) operator[](size_t n) { return mRawArray[n]; } \
- size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
- private: \
- JNIEnv* const mEnv; \
- PRIMITIVE_TYPE ## Array mJavaArray; \
- POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
- DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRW); \
- }
-
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
-
-#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
-#undef POINTER_TYPE
-#undef REFERENCE_TYPE
+#include <nativehelper/scoped_primitive_array.h>
#endif // SCOPED_PRIMITIVE_ARRAY_H_included
diff --git a/include/nativehelper/ScopedStringChars.h b/include/nativehelper/ScopedStringChars.h
index 688291d..59c405c 100644
--- a/include/nativehelper/ScopedStringChars.h
+++ b/include/nativehelper/ScopedStringChars.h
@@ -18,55 +18,6 @@
#define SCOPED_STRING_CHARS_H_included
#include "JNIHelp.h"
-
-// A smart pointer that provides access to a jchar* given a JNI jstring.
-// Unlike GetStringChars, we throw NullPointerException rather than abort if
-// passed a null jstring, and get will return NULL.
-// This makes the correct idiom very simple:
-//
-// ScopedStringChars name(env, java_name);
-// if (name.get() == NULL) {
-// return NULL;
-// }
-class ScopedStringChars {
- public:
- ScopedStringChars(JNIEnv* env, jstring s) : env_(env), string_(s), size_(0) {
- if (s == NULL) {
- chars_ = NULL;
- jniThrowNullPointerException(env, NULL);
- } else {
- chars_ = env->GetStringChars(string_, NULL);
- if (chars_ != NULL) {
- size_ = env->GetStringLength(string_);
- }
- }
- }
-
- ~ScopedStringChars() {
- if (chars_ != NULL) {
- env_->ReleaseStringChars(string_, chars_);
- }
- }
-
- const jchar* get() const {
- return chars_;
- }
-
- size_t size() const {
- return size_;
- }
-
- const jchar& operator[](size_t n) const {
- return chars_[n];
- }
-
- private:
- JNIEnv* const env_;
- const jstring string_;
- const jchar* chars_;
- size_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedStringChars);
-};
+#include <nativehelper/scoped_string_chars.h>
#endif // SCOPED_STRING_CHARS_H_included
diff --git a/include/nativehelper/ScopedUtfChars.h b/include/nativehelper/ScopedUtfChars.h
index aa8489d..f123115 100644
--- a/include/nativehelper/ScopedUtfChars.h
+++ b/include/nativehelper/ScopedUtfChars.h
@@ -18,75 +18,6 @@
#define SCOPED_UTF_CHARS_H_included
#include "JNIHelp.h"
-#include <string.h>
-
-// A smart pointer that provides read-only access to a Java string's UTF chars.
-// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
-// passed a null jstring, and c_str will return nullptr.
-// This makes the correct idiom very simple:
-//
-// ScopedUtfChars name(env, java_name);
-// if (name.c_str() == nullptr) {
-// return nullptr;
-// }
-class ScopedUtfChars {
- public:
- ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
- if (s == nullptr) {
- utf_chars_ = nullptr;
- jniThrowNullPointerException(env, nullptr);
- } else {
- utf_chars_ = env->GetStringUTFChars(s, nullptr);
- }
- }
-
- ScopedUtfChars(ScopedUtfChars&& rhs) :
- env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
- rhs.env_ = nullptr;
- rhs.string_ = nullptr;
- rhs.utf_chars_ = nullptr;
- }
-
- ~ScopedUtfChars() {
- if (utf_chars_) {
- env_->ReleaseStringUTFChars(string_, utf_chars_);
- }
- }
-
- ScopedUtfChars& operator=(ScopedUtfChars&& rhs) {
- if (this != &rhs) {
- // Delete the currently owned UTF chars.
- this->~ScopedUtfChars();
-
- // Move the rhs ScopedUtfChars and zero it out.
- env_ = rhs.env_;
- string_ = rhs.string_;
- utf_chars_ = rhs.utf_chars_;
- rhs.env_ = nullptr;
- rhs.string_ = nullptr;
- rhs.utf_chars_ = nullptr;
- }
- return *this;
- }
-
- const char* c_str() const {
- return utf_chars_;
- }
-
- size_t size() const {
- return strlen(utf_chars_);
- }
-
- const char& operator[](size_t n) const {
- return utf_chars_[n];
- }
-
- private:
- JNIEnv* env_;
- jstring string_;
- const char* utf_chars_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
-};
+#include <nativehelper/scoped_utf_chars.h>
#endif // SCOPED_UTF_CHARS_H_included