| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/android/jni_array.h" | 5 #include "base/android/jni_array.h" |
| 6 | 6 |
| 7 #include "base/android/jni_android.h" | 7 #include "base/android/jni_android.h" |
| 8 #include "base/android/jni_string.h" | 8 #include "base/android/jni_string.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 | 10 |
| 11 namespace base { | 11 namespace base { |
| 12 namespace android { | 12 namespace android { |
| 13 namespace { |
| 14 |
| 15 // As |GetArrayLength| makes no guarantees about the returned value (e.g., it |
| 16 // may be -1 if |array| is not a valid Java array), provide a safe wrapper |
| 17 // that always returns a valid, non-negative size. |
| 18 template <typename JavaArrayType> |
| 19 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) { |
| 20 DCHECK(jarray); |
| 21 jsize length = env->GetArrayLength(jarray); |
| 22 DCHECK_GE(length, 0) << "Invalid array length: " << length; |
| 23 return static_cast<size_t>(std::max(0, length)); |
| 24 } |
| 25 |
| 26 } // namespace |
| 13 | 27 |
| 14 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( | 28 ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( |
| 15 JNIEnv* env, const uint8* bytes, size_t len) { | 29 JNIEnv* env, const uint8* bytes, size_t len) { |
| 16 jbyteArray byte_array = env->NewByteArray(len); | 30 jbyteArray byte_array = env->NewByteArray(len); |
| 17 CheckException(env); | 31 CheckException(env); |
| 18 DCHECK(byte_array); | 32 DCHECK(byte_array); |
| 19 | 33 |
| 20 env->SetByteArrayRegion( | 34 env->SetByteArrayRegion( |
| 21 byte_array, 0, len, reinterpret_cast<const jbyte*>(bytes)); | 35 byte_array, 0, len, reinterpret_cast<const jbyte*>(bytes)); |
| 22 CheckException(env); | 36 CheckException(env); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 } | 115 } |
| 102 return ScopedJavaLocalRef<jobjectArray>(env, joa); | 116 return ScopedJavaLocalRef<jobjectArray>(env, joa); |
| 103 } | 117 } |
| 104 | 118 |
| 105 void AppendJavaStringArrayToStringVector(JNIEnv* env, | 119 void AppendJavaStringArrayToStringVector(JNIEnv* env, |
| 106 jobjectArray array, | 120 jobjectArray array, |
| 107 std::vector<string16>* out) { | 121 std::vector<string16>* out) { |
| 108 DCHECK(out); | 122 DCHECK(out); |
| 109 if (!array) | 123 if (!array) |
| 110 return; | 124 return; |
| 111 jsize len = env->GetArrayLength(array); | 125 size_t len = SafeGetArrayLength(env, array); |
| 112 size_t back = out->size(); | 126 size_t back = out->size(); |
| 113 out->resize(back + len); | 127 out->resize(back + len); |
| 114 for (jsize i = 0; i < len; ++i) { | 128 for (size_t i = 0; i < len; ++i) { |
| 115 ScopedJavaLocalRef<jstring> str(env, | 129 ScopedJavaLocalRef<jstring> str(env, |
| 116 static_cast<jstring>(env->GetObjectArrayElement(array, i))); | 130 static_cast<jstring>(env->GetObjectArrayElement(array, i))); |
| 117 ConvertJavaStringToUTF16(env, str.obj(), &((*out)[back + i])); | 131 ConvertJavaStringToUTF16(env, str.obj(), &((*out)[back + i])); |
| 118 } | 132 } |
| 119 } | 133 } |
| 120 | 134 |
| 121 void AppendJavaStringArrayToStringVector(JNIEnv* env, | 135 void AppendJavaStringArrayToStringVector(JNIEnv* env, |
| 122 jobjectArray array, | 136 jobjectArray array, |
| 123 std::vector<std::string>* out) { | 137 std::vector<std::string>* out) { |
| 124 DCHECK(out); | 138 DCHECK(out); |
| 125 if (!array) | 139 if (!array) |
| 126 return; | 140 return; |
| 127 jsize len = env->GetArrayLength(array); | 141 size_t len = SafeGetArrayLength(env, array); |
| 128 size_t back = out->size(); | 142 size_t back = out->size(); |
| 129 out->resize(back + len); | 143 out->resize(back + len); |
| 130 for (jsize i = 0; i < len; ++i) { | 144 for (size_t i = 0; i < len; ++i) { |
| 131 ScopedJavaLocalRef<jstring> str(env, | 145 ScopedJavaLocalRef<jstring> str(env, |
| 132 static_cast<jstring>(env->GetObjectArrayElement(array, i))); | 146 static_cast<jstring>(env->GetObjectArrayElement(array, i))); |
| 133 ConvertJavaStringToUTF8(env, str.obj(), &((*out)[back + i])); | 147 ConvertJavaStringToUTF8(env, str.obj(), &((*out)[back + i])); |
| 134 } | 148 } |
| 135 } | 149 } |
| 136 | 150 |
| 137 void AppendJavaByteArrayToByteVector(JNIEnv* env, | 151 void AppendJavaByteArrayToByteVector(JNIEnv* env, |
| 138 jbyteArray byte_array, | 152 jbyteArray byte_array, |
| 139 std::vector<uint8>* out) { | 153 std::vector<uint8>* out) { |
| 140 DCHECK(out); | 154 DCHECK(out); |
| 141 if (!byte_array) | 155 if (!byte_array) |
| 142 return; | 156 return; |
| 143 jsize len = env->GetArrayLength(byte_array); | 157 size_t len = SafeGetArrayLength(env, byte_array); |
| 144 jbyte* bytes = env->GetByteArrayElements(byte_array, NULL); | 158 if (!len) |
| 145 out->insert(out->end(), bytes, bytes + len); | 159 return; |
| 146 env->ReleaseByteArrayElements(byte_array, bytes, JNI_ABORT); | 160 size_t back = out->size(); |
| 161 out->resize(back + len); |
| 162 env->GetByteArrayRegion(byte_array, 0, len, |
| 163 reinterpret_cast<int8*>(&(*out)[back])); |
| 147 } | 164 } |
| 148 | 165 |
| 149 void JavaByteArrayToByteVector(JNIEnv* env, | 166 void JavaByteArrayToByteVector(JNIEnv* env, |
| 150 jbyteArray byte_array, | 167 jbyteArray byte_array, |
| 151 std::vector<uint8>* out) { | 168 std::vector<uint8>* out) { |
| 152 DCHECK(out); | 169 DCHECK(out); |
| 170 DCHECK(byte_array); |
| 153 out->clear(); | 171 out->clear(); |
| 154 AppendJavaByteArrayToByteVector(env, byte_array, out); | 172 AppendJavaByteArrayToByteVector(env, byte_array, out); |
| 155 } | 173 } |
| 156 | 174 |
| 157 void JavaIntArrayToIntVector(JNIEnv* env, | 175 void JavaIntArrayToIntVector(JNIEnv* env, |
| 158 jintArray int_array, | 176 jintArray int_array, |
| 159 std::vector<int>* out) { | 177 std::vector<int>* out) { |
| 160 DCHECK(out); | 178 DCHECK(out); |
| 161 out->clear(); | 179 size_t len = SafeGetArrayLength(env, int_array); |
| 162 jsize len = env->GetArrayLength(int_array); | 180 out->resize(len); |
| 163 jint* ints = env->GetIntArrayElements(int_array, NULL); | 181 if (!len) |
| 164 for (jsize i = 0; i < len; ++i) { | 182 return; |
| 165 out->push_back(static_cast<int>(ints[i])); | 183 // TODO(jdduke): Use |out->data()| for pointer access after switch to libc++, |
| 166 } | 184 // both here and in the other conversion routines. See crbug.com/427718. |
| 167 env->ReleaseIntArrayElements(int_array, ints, JNI_ABORT); | 185 env->GetIntArrayRegion(int_array, 0, len, &(*out)[0]); |
| 168 } | 186 } |
| 169 | 187 |
| 170 void JavaLongArrayToLongVector(JNIEnv* env, | 188 void JavaLongArrayToLongVector(JNIEnv* env, |
| 171 jlongArray long_array, | 189 jlongArray long_array, |
| 172 std::vector<long>* out) { | 190 std::vector<jlong>* out) { |
| 173 DCHECK(out); | 191 DCHECK(out); |
| 174 out->clear(); | 192 size_t len = SafeGetArrayLength(env, long_array); |
| 175 jsize len = env->GetArrayLength(long_array); | 193 out->resize(len); |
| 176 jlong* longs = env->GetLongArrayElements(long_array, NULL); | 194 if (!len) |
| 177 for (jsize i = 0; i < len; ++i) { | 195 return; |
| 178 out->push_back(static_cast<long>(longs[i])); | 196 env->GetLongArrayRegion(long_array, 0, len, &(*out)[0]); |
| 179 } | |
| 180 env->ReleaseLongArrayElements(long_array, longs, JNI_ABORT); | |
| 181 } | 197 } |
| 182 | 198 |
| 183 void JavaFloatArrayToFloatVector(JNIEnv* env, | 199 void JavaFloatArrayToFloatVector(JNIEnv* env, |
| 184 jfloatArray float_array, | 200 jfloatArray float_array, |
| 185 std::vector<float>* out) { | 201 std::vector<float>* out) { |
| 186 DCHECK(out); | 202 DCHECK(out); |
| 187 out->clear(); | 203 size_t len = SafeGetArrayLength(env, float_array); |
| 188 jsize len = env->GetArrayLength(float_array); | 204 out->resize(len); |
| 189 jfloat* floats = env->GetFloatArrayElements(float_array, NULL); | 205 if (!len) |
| 190 for (jsize i = 0; i < len; ++i) { | 206 return; |
| 191 out->push_back(static_cast<float>(floats[i])); | 207 env->GetFloatArrayRegion(float_array, 0, len, &(*out)[0]); |
| 192 } | |
| 193 env->ReleaseFloatArrayElements(float_array, floats, JNI_ABORT); | |
| 194 } | 208 } |
| 195 | 209 |
| 196 void JavaArrayOfByteArrayToStringVector( | 210 void JavaArrayOfByteArrayToStringVector( |
| 197 JNIEnv* env, | 211 JNIEnv* env, |
| 198 jobjectArray array, | 212 jobjectArray array, |
| 199 std::vector<std::string>* out) { | 213 std::vector<std::string>* out) { |
| 200 DCHECK(out); | 214 DCHECK(out); |
| 201 out->clear(); | 215 size_t len = SafeGetArrayLength(env, array); |
| 202 jsize len = env->GetArrayLength(array); | |
| 203 out->resize(len); | 216 out->resize(len); |
| 204 for (jsize i = 0; i < len; ++i) { | 217 for (size_t i = 0; i < len; ++i) { |
| 205 ScopedJavaLocalRef<jbyteArray> bytes_array( | 218 ScopedJavaLocalRef<jbyteArray> bytes_array( |
| 206 env, static_cast<jbyteArray>( | 219 env, static_cast<jbyteArray>( |
| 207 env->GetObjectArrayElement(array, i))); | 220 env->GetObjectArrayElement(array, i))); |
| 208 jsize bytes_len = env->GetArrayLength(bytes_array.obj()); | 221 jsize bytes_len = env->GetArrayLength(bytes_array.obj()); |
| 209 jbyte* bytes = env->GetByteArrayElements(bytes_array.obj(), NULL); | 222 jbyte* bytes = env->GetByteArrayElements(bytes_array.obj(), NULL); |
| 210 (*out)[i].assign(reinterpret_cast<const char*>(bytes), bytes_len); | 223 (*out)[i].assign(reinterpret_cast<const char*>(bytes), bytes_len); |
| 211 env->ReleaseByteArrayElements(bytes_array.obj(), bytes, JNI_ABORT); | 224 env->ReleaseByteArrayElements(bytes_array.obj(), bytes, JNI_ABORT); |
| 212 } | 225 } |
| 213 } | 226 } |
| 214 | 227 |
| 215 } // namespace android | 228 } // namespace android |
| 216 } // namespace base | 229 } // namespace base |
| OLD | NEW |