New upstream version 8.1.0+r23

parent f6449d99
// Copyright (C) 2009 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.
cc_library_headers {
name: "jni_headers",
host_supported: true,
export_include_dirs: ["include_jni"],
vendor_available: true,
}
cc_library {
name: "libnativehelper",
host_supported: true,
srcs: [
"JNIHelp.cpp",
"JniConstants.cpp",
"toStringArray.cpp",
"JniInvocation.cpp",
],
target: {
android: {
srcs: ["AsynchronousCloseMonitor.cpp"],
shared_libs: ["libdl"],
},
linux: {
srcs: ["AsynchronousCloseMonitor.cpp"],
host_ldlibs: ["-ldl"],
},
},
header_libs: ["jni_headers"],
export_header_lib_headers: ["jni_headers"],
shared_libs: [
"liblog",
],
clang: true,
cflags: [
"-Werror",
"-fvisibility=protected",
],
export_include_dirs: ["include", "platform_include"],
}
//
// NDK-only build for the target (device), using libc++.
// - Relies only on NDK exposed functionality.
// - This doesn't include JniInvocation.
//
cc_library_shared {
name: "libnativehelper_compat_libc++",
clang: true,
local_include_dirs: ["include/nativehelper"],
export_include_dirs: ["include/nativehelper"],
cflags: ["-Werror"],
srcs: [
"JNIHelp.cpp",
"JniConstants.cpp",
"toStringArray.cpp",
],
shared_libs: [
"liblog",
"libdl",
],
sdk_version: "19",
stl: "c++_static",
}
ndk_headers {
name: "ndk_jni.h",
from: "include_jni",
to: "",
srcs: ["include_jni/jni.h"],
license: "NOTICE",
}
//
// Tests.
//
subdirs = ["tests"]
# Copyright (C) 2009 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.
LOCAL_PATH := $(call my-dir)
local_src_files := \
JNIHelp.cpp \
JniConstants.cpp \
toStringArray.cpp
#
# Build for the target (device).
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(local_src_files) \
JniInvocation.cpp \
AsynchronousCloseMonitor.cpp
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libnativehelper
LOCAL_CLANG := true
LOCAL_CFLAGS := -Werror -fvisibility=protected
LOCAL_C_INCLUDES := libcore/include
LOCAL_SHARED_LIBRARIES += libdl
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_SHARED_LIBRARY)
#
# NDK-only build for the target (device), using libc++.
# - Relies only on NDK exposed functionality.
# - This doesn't include JniInvocation.
#
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libnativehelper_compat_libc++
LOCAL_CLANG := true
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include/nativehelper
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH)/include/nativehelper
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := $(local_src_files)
LOCAL_LDFLAGS := -llog -ldl
LOCAL_SDK_VERSION := 19
LOCAL_NDK_STL_VARIANT := c++_static
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_SHARED_LIBRARY)
#
# Build for the host.
#
include $(CLEAR_VARS)
LOCAL_MODULE := libnativehelper
LOCAL_MODULE_TAGS := optional
LOCAL_CLANG := true
LOCAL_SRC_FILES := \
$(local_src_files) \
JniInvocation.cpp
ifeq ($(HOST_OS),linux)
LOCAL_SRC_FILES += AsynchronousCloseMonitor.cpp
endif
LOCAL_CFLAGS := -Werror -fvisibility=protected
LOCAL_C_INCLUDES := libcore/include
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_LDFLAGS := -ldl
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MULTILIB := both
include $(BUILD_HOST_SHARED_LIBRARY)
#
# Build static for the host.
#
include $(CLEAR_VARS)
LOCAL_MODULE := libnativehelper
LOCAL_MODULE_TAGS := optional
LOCAL_CLANG := true
LOCAL_SRC_FILES := \
$(local_src_files) \
JniInvocation.cpp
ifeq ($(HOST_OS),linux)
LOCAL_SRC_FILES += AsynchronousCloseMonitor.cpp
endif
LOCAL_CFLAGS := -Werror -fvisibility=protected
LOCAL_C_INCLUDES := libcore/include
LOCAL_STATIC_LIBRARIES := liblog
LOCAL_LDFLAGS := -ldl
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MULTILIB := both
include $(BUILD_HOST_STATIC_LIBRARY)
#
# Tests.
#
include $(LOCAL_PATH)/tests/Android.mk
......@@ -23,6 +23,8 @@
#include <signal.h>
#include <string.h>
#include <mutex>
/**
* We use an intrusive doubly-linked list to keep track of blocked threads.
* This gives us O(1) insertion and removal, and means we don't need to do any allocation.
......@@ -31,7 +33,7 @@
* of blocked threads (not the number of threads actually blocked on the file descriptor in
* question). For now at least, this seems like a good compromise for Android.
*/
static pthread_mutex_t blockedThreadListMutex = PTHREAD_MUTEX_INITIALIZER;
static std::mutex blockedThreadListMutex;
static AsynchronousCloseMonitor* blockedThreadList = NULL;
/**
......@@ -59,7 +61,7 @@ void AsynchronousCloseMonitor::init() {
}
void AsynchronousCloseMonitor::signalBlockedThreads(int fd) {
ScopedPthreadMutexLock lock(&blockedThreadListMutex);
std::lock_guard<std::mutex> lock(blockedThreadListMutex);
for (AsynchronousCloseMonitor* it = blockedThreadList; it != NULL; it = it->mNext) {
if (it->mFd == fd) {
it->mSignaled = true;
......@@ -74,7 +76,7 @@ bool AsynchronousCloseMonitor::wasSignaled() const {
}
AsynchronousCloseMonitor::AsynchronousCloseMonitor(int fd) {
ScopedPthreadMutexLock lock(&blockedThreadListMutex);
std::lock_guard<std::mutex> lock(blockedThreadListMutex);
// Who are we, and what are we waiting for?
mThread = pthread_self();
mFd = fd;
......@@ -89,7 +91,7 @@ AsynchronousCloseMonitor::AsynchronousCloseMonitor(int fd) {
}
AsynchronousCloseMonitor::~AsynchronousCloseMonitor() {
ScopedPthreadMutexLock lock(&blockedThreadListMutex);
std::lock_guard<std::mutex> lock(blockedThreadListMutex);
// Unlink ourselves from the intrusive doubly-linked list...
if (mNext != NULL) {
mNext->mPrev = mPrev;
......
......@@ -17,6 +17,8 @@
#if defined(__ANDROID__)
/* libnativehelper is built by NDK 19 in one variant, which doesn't yet have the GNU strerror_r. */
#undef _GNU_SOURCE
/* ...but this code uses asprintf, which is a BSD/GNU extension. */
#define _BSD_SOURCE
#endif
#define LOG_TAG "JNIHelp"
......@@ -38,7 +40,7 @@
template<typename T>
class scoped_local_ref {
public:
scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
explicit scoped_local_ref(C_JNIEnv* env, T localRef = NULL)
: mEnv(env), mLocalRef(localRef)
{
}
......@@ -360,3 +362,7 @@ jobject jniGetReferent(C_JNIEnv* env, jobject ref) {
return (*env)->CallObjectMethod(e, ref, get);
}
jstring jniCreateString(C_JNIEnv* env, const jchar* unicodeChars, jsize len) {
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
return (*env)->NewString(e, unicodeChars, len);
}
......@@ -28,57 +28,43 @@
static std::atomic<bool> g_constants_initialized(false);
static std::mutex g_constants_mutex;
jclass JniConstants::bigDecimalClass;
jclass JniConstants::booleanClass;
jclass JniConstants::byteArrayClass;
jclass JniConstants::byteClass;
jclass JniConstants::calendarClass;
jclass JniConstants::characterClass;
jclass JniConstants::charsetICUClass;
jclass JniConstants::constructorClass;
jclass JniConstants::deflaterClass;
jclass JniConstants::doubleClass;
jclass JniConstants::errnoExceptionClass;
jclass JniConstants::fieldClass;
jclass JniConstants::fileDescriptorClass;
jclass JniConstants::floatClass;
jclass JniConstants::gaiExceptionClass;
jclass JniConstants::inet6AddressClass;
jclass JniConstants::inet6AddressHolderClass;
jclass JniConstants::inetAddressClass;
jclass JniConstants::inetAddressHolderClass;
jclass JniConstants::inetSocketAddressClass;
jclass JniConstants::inetSocketAddressHolderClass;
jclass JniConstants::inflaterClass;
jclass JniConstants::inputStreamClass;
jclass JniConstants::integerClass;
jclass JniConstants::localeDataClass;
jclass JniConstants::longClass;
jclass JniConstants::methodClass;
jclass JniConstants::mutableIntClass;
jclass JniConstants::mutableLongClass;
jclass JniConstants::netlinkSocketAddressClass;
jclass JniConstants::objectClass;
jclass JniConstants::objectArrayClass;
jclass JniConstants::outputStreamClass;
jclass JniConstants::packetSocketAddressClass;
jclass JniConstants::parsePositionClass;
jclass JniConstants::patternSyntaxExceptionClass;
jclass JniConstants::referenceClass;
jclass JniConstants::shortClass;
jclass JniConstants::socketClass;
jclass JniConstants::socketImplClass;
jclass JniConstants::socketTaggerClass;
jclass JniConstants::stringClass;
jclass JniConstants::structAddrinfoClass;
jclass JniConstants::structFlockClass;
jclass JniConstants::structGroupReqClass;
jclass JniConstants::structGroupSourceReqClass;
jclass JniConstants::structIfaddrs;
jclass JniConstants::structLingerClass;
jclass JniConstants::structPasswdClass;
jclass JniConstants::structPollfdClass;
jclass JniConstants::structStatClass;
jclass JniConstants::structStatVfsClass;
jclass JniConstants::structTimevalClass;
jclass JniConstants::structTimespecClass;
jclass JniConstants::structUcredClass;
jclass JniConstants::structUtsnameClass;
jclass JniConstants::unixSocketAddressClass;
......@@ -108,57 +94,43 @@ void JniConstants::init(JNIEnv* env) {
return;
}
bigDecimalClass = findClass(env, "java/math/BigDecimal");
booleanClass = findClass(env, "java/lang/Boolean");
byteClass = findClass(env, "java/lang/Byte");
byteArrayClass = findClass(env, "[B");
calendarClass = findClass(env, "java/util/Calendar");
characterClass = findClass(env, "java/lang/Character");
charsetICUClass = findClass(env, "java/nio/charset/CharsetICU");
constructorClass = findClass(env, "java/lang/reflect/Constructor");
floatClass = findClass(env, "java/lang/Float");
deflaterClass = findClass(env, "java/util/zip/Deflater");
doubleClass = findClass(env, "java/lang/Double");
errnoExceptionClass = findClass(env, "android/system/ErrnoException");
fieldClass = findClass(env, "java/lang/reflect/Field");
fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
gaiExceptionClass = findClass(env, "android/system/GaiException");
inet6AddressClass = findClass(env, "java/net/Inet6Address");
inet6AddressHolderClass = findClass(env, "java/net/Inet6Address$Inet6AddressHolder");
inetAddressClass = findClass(env, "java/net/InetAddress");
inetAddressHolderClass = findClass(env, "java/net/InetAddress$InetAddressHolder");
inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
inetSocketAddressHolderClass = findClass(env, "java/net/InetSocketAddress$InetSocketAddressHolder");
inflaterClass = findClass(env, "java/util/zip/Inflater");
inputStreamClass = findClass(env, "java/io/InputStream");
integerClass = findClass(env, "java/lang/Integer");
localeDataClass = findClass(env, "libcore/icu/LocaleData");
longClass = findClass(env, "java/lang/Long");
methodClass = findClass(env, "java/lang/reflect/Method");
mutableIntClass = findClass(env, "android/util/MutableInt");
mutableLongClass = findClass(env, "android/util/MutableLong");
netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress");
objectClass = findClass(env, "java/lang/Object");
objectArrayClass = findClass(env, "[Ljava/lang/Object;");
outputStreamClass = findClass(env, "java/io/OutputStream");
packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress");
parsePositionClass = findClass(env, "java/text/ParsePosition");
patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
referenceClass = findClass(env, "java/lang/ref/Reference");
shortClass = findClass(env, "java/lang/Short");
socketClass = findClass(env, "java/net/Socket");
socketTaggerClass = findClass(env, "dalvik/system/SocketTagger");
socketImplClass = findClass(env, "java/net/SocketImpl");
stringClass = findClass(env, "java/lang/String");
structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
structFlockClass = findClass(env, "android/system/StructFlock");
structGroupReqClass = findClass(env, "android/system/StructGroupReq");
structGroupSourceReqClass = findClass(env, "android/system/StructGroupSourceReq");
structIfaddrs = findClass(env, "android/system/StructIfaddrs");
structLingerClass = findClass(env, "android/system/StructLinger");
structPasswdClass = findClass(env, "android/system/StructPasswd");
structPollfdClass = findClass(env, "android/system/StructPollfd");
structStatClass = findClass(env, "android/system/StructStat");
structStatVfsClass = findClass(env, "android/system/StructStatVfs");
structTimevalClass = findClass(env, "android/system/StructTimeval");
structTimespecClass = findClass(env, "android/system/StructTimespec");
structUcredClass = findClass(env, "android/system/StructUcred");
structUtsnameClass = findClass(env, "android/system/StructUtsname");
unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress");
......
......@@ -17,7 +17,6 @@
#ifndef ASYNCHRONOUS_CLOSE_MONITOR_H_included
#define ASYNCHRONOUS_CLOSE_MONITOR_H_included
#include "ScopedPthreadMutexLock.h"
#include <pthread.h>
/**
......@@ -43,7 +42,7 @@
*/
class AsynchronousCloseMonitor {
public:
AsynchronousCloseMonitor(int fd);
explicit AsynchronousCloseMonitor(int fd);
~AsynchronousCloseMonitor();
bool wasSignaled() const;
......
......@@ -103,6 +103,12 @@ void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value);
*/
jobject jniGetReferent(C_JNIEnv* env, jobject ref);
/*
* Returns a Java String object created from UTF-16 data either from jchar or,
* if called from C++11, char16_t (a bitwise identical distinct type).
*/
jstring jniCreateString(C_JNIEnv* env, const jchar* unicodeChars, jsize len);
/*
* Log a message and an exception.
* If exception is NULL, logs the current exception in the JNI environment.
......@@ -168,6 +174,16 @@ inline jobject jniGetReferent(JNIEnv* env, jobject ref) {
return jniGetReferent(&env->functions, ref);
}
inline jstring jniCreateString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
return jniCreateString(&env->functions, unicodeChars, len);
}
#if __cplusplus >= 201103L
inline jstring jniCreateString(JNIEnv* env, const char16_t* unicodeChars, jsize len) {
return jniCreateString(&env->functions, reinterpret_cast<const jchar*>(unicodeChars), len);
}
#endif // __cplusplus >= 201103L
inline void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception = NULL) {
jniLogException(&env->functions, priority, tag, exception);
}
......
......@@ -39,57 +39,43 @@
struct JniConstants {
static void init(JNIEnv* env);
static jclass bigDecimalClass;
static jclass booleanClass;
static jclass byteArrayClass;
static jclass byteClass;
static jclass calendarClass;
static jclass characterClass;
static jclass charsetICUClass;
static jclass constructorClass;
static jclass deflaterClass;
static jclass doubleClass;
static jclass errnoExceptionClass;
static jclass fieldClass;
static jclass fileDescriptorClass;
static jclass floatClass;
static jclass gaiExceptionClass;
static jclass inet6AddressClass;
static jclass inet6AddressHolderClass;
static jclass inetAddressClass;
static jclass inetAddressHolderClass;
static jclass inetSocketAddressClass;
static jclass inetSocketAddressHolderClass;
static jclass inflaterClass;
static jclass inputStreamClass;
static jclass integerClass;
static jclass localeDataClass;
static jclass longClass;
static jclass methodClass;
static jclass mutableIntClass;
static jclass mutableLongClass;
static jclass netlinkSocketAddressClass;
static jclass objectClass;
static jclass objectArrayClass;
static jclass outputStreamClass;
static jclass packetSocketAddressClass;
static jclass parsePositionClass;
static jclass patternSyntaxExceptionClass;
static jclass referenceClass;
static jclass shortClass;
static jclass socketClass;
static jclass socketImplClass;
static jclass socketTaggerClass;
static jclass stringClass;
static jclass structAddrinfoClass;
static jclass structFlockClass;
static jclass structGroupReqClass;
static jclass structGroupSourceReqClass;
static jclass structIfaddrs;
static jclass structLingerClass;
static jclass structPasswdClass;
static jclass structPollfdClass;
static jclass structStatClass;
static jclass structStatVfsClass;
static jclass structTimevalClass;
static jclass structTimespecClass;
static jclass structUcredClass;
static jclass structUtsnameClass;
static jclass unixSocketAddressClass;
......
/*
* Copyright (C) 2009 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_FD_H_included
#define SCOPED_FD_H_included
#include <unistd.h>
#include "JNIHelp.h" // for DISALLOW_COPY_AND_ASSIGN.
// A smart pointer that closes the given fd on going out of scope.
// Use this when the fd is incidental to the purpose of your function,
// but needs to be cleaned up on exit.
class ScopedFd final {
public:
explicit ScopedFd(int fd) : fd_(fd) {
}
ScopedFd() : ScopedFd(-1) {}
~ScopedFd() {
reset();
}
ScopedFd(ScopedFd&& other) : fd_(other.release()) {}
ScopedFd& operator = (ScopedFd&& s) {
reset(s.release());
return *this;
}
int get() const {
return fd_;
}
int release() __attribute__((warn_unused_result)) {
int localFd = fd_;
fd_ = -1;
return localFd;
}
void reset(int new_fd = -1) {
if (fd_ != -1) {
// Even if close(2) fails with EINTR, the fd will have been closed.
// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
close(fd_);
}
fd_ = new_fd;
}
private:
int fd_;
DISALLOW_COPY_AND_ASSIGN(ScopedFd);
};
#endif // SCOPED_FD_H_included
......@@ -21,7 +21,7 @@
class ScopedLocalFrame {
public:
ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
explicit ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
mEnv->PushLocalFrame(128);
}
......
......@@ -19,6 +19,18 @@
#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
......@@ -62,7 +74,7 @@
static const jsize buffer_size = 1024; \
JNIEnv* const mEnv; \
PRIMITIVE_TYPE ## Array mJavaArray; \
PRIMITIVE_TYPE* mRawArray; \
POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
jsize mSize; \
PRIMITIVE_TYPE mBuffer[buffer_size]; \
DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRO); \
......@@ -108,13 +120,13 @@ INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
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]; } \
PRIMITIVE_TYPE* get() { return mRawArray; } \
PRIMITIVE_TYPE& operator[](size_t n) { 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; \
PRIMITIVE_TYPE* mRawArray; \
POINTER_TYPE(PRIMITIVE_TYPE) mRawArray; \
DISALLOW_COPY_AND_ASSIGN(Scoped ## NAME ## ArrayRW); \
}
......@@ -128,5 +140,7 @@ 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_included
......@@ -22,30 +22,53 @@
// 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 NULL.
// 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() == NULL) {
// return NULL;
// if (name.c_str() == nullptr) {
// return nullptr;
// }
class ScopedUtfChars {
public:
ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
if (s == NULL) {
utf_chars_ = NULL;
jniThrowNullPointerException(env, NULL);
if (s == nullptr) {
utf_chars_ = nullptr;
jniThrowNullPointerException(env, nullptr);
} else {
utf_chars_ = env->GetStringUTFChars(s, NULL);
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_;
}
......@@ -59,8 +82,8 @@ class ScopedUtfChars {
}
private:
JNIEnv* const env_;
const jstring string_;
JNIEnv* env_;
jstring string_;
const char* utf_chars_;
DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
......
......@@ -47,14 +47,14 @@ jobjectArray toStringArray(JNIEnv* env, Counter* counter, Getter* getter) {
struct VectorCounter {
const std::vector<std::string>& strings;
VectorCounter(const std::vector<std::string>& strings) : strings(strings) {}
explicit VectorCounter(const std::vector<std::string>& strings) : strings(strings) {}
size_t operator()() {
return strings.size();
}
};
struct VectorGetter {
const std::vector<std::string>& strings;
VectorGetter(const std::vector<std::string>& strings) : strings(strings) {}
explicit VectorGetter(const std::vector<std::string>& strings) : strings(strings) {}
const char* operator()(size_t i) {
return strings[i].c_str();
}
......
../include/nativehelper/AsynchronousCloseMonitor.h
\ No newline at end of file
../include/nativehelper/JNIHelp.h
\ No newline at end of file
../include/nativehelper/JniConstants.h
\ No newline at end of file