123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "base/android/jni_array.h"
- #include <ostream>
- #include "base/android/jni_android.h"
- #include "base/android/jni_string.h"
- #include "base/check_op.h"
- #include "base/numerics/safe_conversions.h"
- namespace base {
- namespace android {
- namespace {
- // As |GetArrayLength| makes no guarantees about the returned value (e.g., it
- // may be -1 if |array| is not a valid Java array), provide a safe wrapper
- // that always returns a valid, non-negative size.
- template <typename JavaArrayType>
- size_t SafeGetArrayLength(JNIEnv* env, const JavaRef<JavaArrayType>& jarray) {
- DCHECK(jarray);
- jsize length = env->GetArrayLength(jarray.obj());
- DCHECK_GE(length, 0) << "Invalid array length: " << length;
- return static_cast<size_t>(std::max(0, length));
- }
- } // namespace
- ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env,
- const uint8_t* bytes,
- size_t len) {
- const jsize len_jsize = checked_cast<jsize>(len);
- jbyteArray byte_array = env->NewByteArray(len_jsize);
- CheckException(env);
- DCHECK(byte_array);
- env->SetByteArrayRegion(byte_array, 0, len_jsize,
- reinterpret_cast<const jbyte*>(bytes));
- CheckException(env);
- return ScopedJavaLocalRef<jbyteArray>(env, byte_array);
- }
- ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(
- JNIEnv* env,
- base::span<const uint8_t> bytes) {
- return ToJavaByteArray(env, bytes.data(), bytes.size());
- }
- ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env,
- const std::string& str) {
- return ToJavaByteArray(env, reinterpret_cast<const uint8_t*>(str.data()),
- str.size());
- }
- ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray(JNIEnv* env,
- const bool* bools,
- size_t len) {
- const jsize len_jsize = checked_cast<jsize>(len);
- jbooleanArray boolean_array = env->NewBooleanArray(len_jsize);
- CheckException(env);
- DCHECK(boolean_array);
- env->SetBooleanArrayRegion(boolean_array, 0, len_jsize,
- reinterpret_cast<const jboolean*>(bools));
- CheckException(env);
- return ScopedJavaLocalRef<jbooleanArray>(env, boolean_array);
- }
- ScopedJavaLocalRef<jintArray> ToJavaIntArray(JNIEnv* env,
- const int* ints,
- size_t len) {
- const jsize len_jsize = checked_cast<jsize>(len);
- jintArray int_array = env->NewIntArray(len_jsize);
- CheckException(env);
- DCHECK(int_array);
- env->SetIntArrayRegion(int_array, 0, len_jsize,
- reinterpret_cast<const jint*>(ints));
- CheckException(env);
- return ScopedJavaLocalRef<jintArray>(env, int_array);
- }
- ScopedJavaLocalRef<jintArray> ToJavaIntArray(JNIEnv* env,
- base::span<const int> ints) {
- return ToJavaIntArray(env, ints.data(), ints.size());
- }
- ScopedJavaLocalRef<jlongArray> ToJavaLongArray(JNIEnv* env,
- const int64_t* longs,
- size_t len) {
- const jsize len_jsize = checked_cast<jsize>(len);
- jlongArray long_array = env->NewLongArray(len_jsize);
- CheckException(env);
- DCHECK(long_array);
- env->SetLongArrayRegion(long_array, 0, len_jsize,
- reinterpret_cast<const jlong*>(longs));
- CheckException(env);
- return ScopedJavaLocalRef<jlongArray>(env, long_array);
- }
- // Returns a new Java long array converted from the given int64_t array.
- BASE_EXPORT ScopedJavaLocalRef<jlongArray> ToJavaLongArray(
- JNIEnv* env,
- base::span<const int64_t> longs) {
- return ToJavaLongArray(env, longs.data(), longs.size());
- }
- // Returns a new Java float array converted from the given C++ float array.
- BASE_EXPORT ScopedJavaLocalRef<jfloatArray>
- ToJavaFloatArray(JNIEnv* env, const float* floats, size_t len) {
- const jsize len_jsize = checked_cast<jsize>(len);
- jfloatArray float_array = env->NewFloatArray(len_jsize);
- CheckException(env);
- DCHECK(float_array);
- env->SetFloatArrayRegion(float_array, 0, len_jsize,
- reinterpret_cast<const jfloat*>(floats));
- CheckException(env);
- return ScopedJavaLocalRef<jfloatArray>(env, float_array);
- }
- BASE_EXPORT ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray(
- JNIEnv* env,
- base::span<const float> floats) {
- return ToJavaFloatArray(env, floats.data(), floats.size());
- }
- BASE_EXPORT ScopedJavaLocalRef<jdoubleArray>
- ToJavaDoubleArray(JNIEnv* env, const double* doubles, size_t len) {
- const jsize len_jsize = checked_cast<jsize>(len);
- jdoubleArray double_array = env->NewDoubleArray(len_jsize);
- CheckException(env);
- DCHECK(double_array);
- env->SetDoubleArrayRegion(double_array, 0, len_jsize,
- reinterpret_cast<const jdouble*>(doubles));
- CheckException(env);
- return ScopedJavaLocalRef<jdoubleArray>(env, double_array);
- }
- BASE_EXPORT ScopedJavaLocalRef<jdoubleArray> ToJavaDoubleArray(
- JNIEnv* env,
- base::span<const double> doubles) {
- return ToJavaDoubleArray(env, doubles.data(), doubles.size());
- }
- BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects(
- JNIEnv* env,
- ScopedJavaLocalRef<jclass> clazz,
- base::span<const ScopedJavaLocalRef<jobject>> v) {
- jobjectArray joa =
- env->NewObjectArray(checked_cast<jsize>(v.size()), clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), v[i].obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects(
- JNIEnv* env,
- base::span<const ScopedJavaLocalRef<jobject>> v) {
- return ToJavaArrayOfObjects(env, GetClass(env, "java/lang/Object"), v);
- }
- BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects(
- JNIEnv* env,
- base::span<const ScopedJavaGlobalRef<jobject>> v) {
- ScopedJavaLocalRef<jclass> object_array_clazz =
- GetClass(env, "java/lang/Object");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
- object_array_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), v[i].obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
- JNIEnv* env,
- base::span<const ScopedJavaLocalRef<jobject>> v,
- ScopedJavaLocalRef<jclass> type) {
- jobjectArray joa =
- env->NewObjectArray(checked_cast<jsize>(v.size()), type.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), v[i].obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- BASE_EXPORT ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects(
- JNIEnv* env,
- base::span<const ScopedJavaGlobalRef<jobject>> v,
- ScopedJavaLocalRef<jclass> type) {
- jobjectArray joa =
- env->NewObjectArray(checked_cast<jsize>(v.size()), type.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), v[i].obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
- JNIEnv* env,
- base::span<const std::string> v) {
- ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
- byte_array_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(
- env, reinterpret_cast<const uint8_t*>(v[i].data()), v[i].length());
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), byte_array.obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray(
- JNIEnv* env,
- base::span<const std::vector<uint8_t>> v) {
- ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
- byte_array_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- ScopedJavaLocalRef<jbyteArray> byte_array =
- ToJavaByteArray(env, v[i].data(), v[i].size());
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), byte_array.obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
- JNIEnv* env,
- base::span<const std::string> v) {
- ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
- string_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- ScopedJavaLocalRef<jstring> item = ConvertUTF8ToJavaString(env, v[i]);
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), item.obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray(
- JNIEnv* env,
- base::span<const std::vector<std::string>> vec_outer) {
- ScopedJavaLocalRef<jclass> string_array_clazz =
- GetClass(env, "[Ljava/lang/String;");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(vec_outer.size()),
- string_array_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < vec_outer.size(); ++i) {
- ScopedJavaLocalRef<jobjectArray> inner =
- ToJavaArrayOfStrings(env, vec_outer[i]);
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), inner.obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray(
- JNIEnv* env,
- base::span<const std::vector<std::u16string>> vec_outer) {
- ScopedJavaLocalRef<jclass> string_array_clazz =
- GetClass(env, "[Ljava/lang/String;");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(vec_outer.size()),
- string_array_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < vec_outer.size(); ++i) {
- ScopedJavaLocalRef<jobjectArray> inner =
- ToJavaArrayOfStrings(env, vec_outer[i]);
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), inner.obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings(
- JNIEnv* env,
- base::span<const std::u16string> v) {
- ScopedJavaLocalRef<jclass> string_clazz = GetClass(env, "java/lang/String");
- jobjectArray joa = env->NewObjectArray(checked_cast<jsize>(v.size()),
- string_clazz.obj(), nullptr);
- CheckException(env);
- for (size_t i = 0; i < v.size(); ++i) {
- ScopedJavaLocalRef<jstring> item = ConvertUTF16ToJavaString(env, v[i]);
- env->SetObjectArrayElement(joa, static_cast<jsize>(i), item.obj());
- }
- return ScopedJavaLocalRef<jobjectArray>(env, joa);
- }
- void AppendJavaStringArrayToStringVector(JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::u16string>* out) {
- DCHECK(out);
- if (!array)
- return;
- size_t len = SafeGetArrayLength(env, array);
- size_t back = out->size();
- out->resize(back + len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jstring> str(
- env, static_cast<jstring>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- ConvertJavaStringToUTF16(env, str.obj(), out->data() + back + i);
- }
- }
- void AppendJavaStringArrayToStringVector(JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::string>* out) {
- DCHECK(out);
- if (!array)
- return;
- size_t len = SafeGetArrayLength(env, array);
- size_t back = out->size();
- out->resize(back + len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jstring> str(
- env, static_cast<jstring>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- ConvertJavaStringToUTF8(env, str.obj(), out->data() + back + i);
- }
- }
- void AppendJavaByteArrayToByteVector(JNIEnv* env,
- const JavaRef<jbyteArray>& byte_array,
- std::vector<uint8_t>* out) {
- DCHECK(out);
- if (!byte_array)
- return;
- size_t len = SafeGetArrayLength(env, byte_array);
- if (!len)
- return;
- size_t back = out->size();
- out->resize(back + len);
- env->GetByteArrayRegion(byte_array.obj(), 0, static_cast<jsize>(len),
- reinterpret_cast<int8_t*>(out->data() + back));
- }
- void JavaByteArrayToByteVector(JNIEnv* env,
- const JavaRef<jbyteArray>& byte_array,
- std::vector<uint8_t>* out) {
- DCHECK(out);
- DCHECK(byte_array);
- out->clear();
- AppendJavaByteArrayToByteVector(env, byte_array, out);
- }
- void JavaByteArrayToString(JNIEnv* env,
- const JavaRef<jbyteArray>& byte_array,
- std::string* out) {
- DCHECK(out);
- DCHECK(byte_array);
- std::vector<uint8_t> byte_vector;
- JavaByteArrayToByteVector(env, byte_array, &byte_vector);
- out->assign(byte_vector.begin(), byte_vector.end());
- }
- void JavaBooleanArrayToBoolVector(JNIEnv* env,
- const JavaRef<jbooleanArray>& boolean_array,
- std::vector<bool>* out) {
- DCHECK(out);
- if (!boolean_array)
- return;
- size_t len = SafeGetArrayLength(env, boolean_array);
- if (!len)
- return;
- out->resize(len);
- // It is not possible to get bool* out of vector<bool>.
- jboolean* values = env->GetBooleanArrayElements(boolean_array.obj(), nullptr);
- for (size_t i = 0; i < len; ++i) {
- out->at(i) = static_cast<bool>(values[i]);
- }
- env->ReleaseBooleanArrayElements(boolean_array.obj(), values, JNI_ABORT);
- }
- void JavaIntArrayToIntVector(JNIEnv* env,
- const JavaRef<jintArray>& int_array,
- std::vector<int>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, int_array);
- out->resize(len);
- if (!len)
- return;
- env->GetIntArrayRegion(int_array.obj(), 0, static_cast<jsize>(len),
- out->data());
- }
- void JavaLongArrayToInt64Vector(JNIEnv* env,
- const JavaRef<jlongArray>& long_array,
- std::vector<int64_t>* out) {
- DCHECK(out);
- std::vector<jlong> temp;
- JavaLongArrayToLongVector(env, long_array, &temp);
- out->resize(0);
- out->insert(out->begin(), temp.begin(), temp.end());
- }
- void JavaLongArrayToLongVector(JNIEnv* env,
- const JavaRef<jlongArray>& long_array,
- std::vector<jlong>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, long_array);
- out->resize(len);
- if (!len)
- return;
- env->GetLongArrayRegion(long_array.obj(), 0, static_cast<jsize>(len),
- out->data());
- }
- void JavaFloatArrayToFloatVector(JNIEnv* env,
- const JavaRef<jfloatArray>& float_array,
- std::vector<float>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, float_array);
- out->resize(len);
- if (!len)
- return;
- env->GetFloatArrayRegion(float_array.obj(), 0, static_cast<jsize>(len),
- out->data());
- }
- void JavaDoubleArrayToDoubleVector(JNIEnv* env,
- const JavaRef<jdoubleArray>& double_array,
- std::vector<double>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, double_array);
- out->resize(len);
- if (!len)
- return;
- env->GetDoubleArrayRegion(double_array.obj(), 0, static_cast<jsize>(len),
- out->data());
- }
- void JavaArrayOfByteArrayToStringVector(JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::string>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, array);
- out->resize(len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jbyteArray> bytes_array(
- env, static_cast<jbyteArray>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- size_t bytes_len = SafeGetArrayLength(env, bytes_array);
- jbyte* bytes = env->GetByteArrayElements(bytes_array.obj(), nullptr);
- (*out)[i].assign(reinterpret_cast<const char*>(bytes), bytes_len);
- env->ReleaseByteArrayElements(bytes_array.obj(), bytes, JNI_ABORT);
- }
- }
- void JavaArrayOfByteArrayToBytesVector(JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::vector<uint8_t>>* out) {
- DCHECK(out);
- const size_t len = SafeGetArrayLength(env, array);
- out->resize(len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jbyteArray> bytes_array(
- env, static_cast<jbyteArray>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- JavaByteArrayToByteVector(env, bytes_array, &(*out)[i]);
- }
- }
- void Java2dStringArrayTo2dStringVector(
- JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::vector<std::u16string>>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, array);
- out->resize(len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jobjectArray> strings_array(
- env, static_cast<jobjectArray>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- out->at(i).clear();
- AppendJavaStringArrayToStringVector(env, strings_array, &out->at(i));
- }
- }
- void Java2dStringArrayTo2dStringVector(
- JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::vector<std::string>>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, array);
- out->resize(len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jobjectArray> strings_array(
- env, static_cast<jobjectArray>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- out->at(i).clear();
- AppendJavaStringArrayToStringVector(env, strings_array, &out->at(i));
- }
- }
- void JavaArrayOfIntArrayToIntVector(JNIEnv* env,
- const JavaRef<jobjectArray>& array,
- std::vector<std::vector<int>>* out) {
- DCHECK(out);
- size_t len = SafeGetArrayLength(env, array);
- out->resize(len);
- for (size_t i = 0; i < len; ++i) {
- ScopedJavaLocalRef<jintArray> int_array(
- env, static_cast<jintArray>(env->GetObjectArrayElement(
- array.obj(), static_cast<jsize>(i))));
- JavaIntArrayToIntVector(env, int_array, &out->at(i));
- }
- }
- } // namespace android
- } // namespace base
|