Nativehelper: Export header-only version of helpers
Export a version of the nativehelper helpers that doesn't have
a dependency on the libnativehelper library. Instead, provide an
inline function for null throw.
Test: m
Change-Id: Idfab8809873d54db824c8bc089f003265fe5a9b9
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_