| // Copyright 2012 The Chromium Authors |
| // 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 <cstdint> |
| #include <string> |
| #include <vector> |
| |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_string.h" |
| #include "base/check_op.h" |
| #include "base/containers/span.h" |
| #include "base/strings/string_view_util.h" |
| #include "third_party/jni_zero/default_conversions.h" |
| |
| namespace base::android { |
| |
| ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, |
| const uint8_t* bytes, |
| size_t len) { |
| return ToJavaByteArray( |
| env, |
| // SAFETY: required from caller, see UNSAFE_BUFFER_USAGE in header. |
| UNSAFE_BUFFERS(base::span(bytes, len))); |
| } |
| |
| ScopedJavaLocalRef<jbyteArray> ToJavaByteArray( |
| JNIEnv* env, |
| base::span<const uint8_t> bytes) { |
| return jni_zero::NewArray<uint8_t>(env, bytes); |
| } |
| |
| ScopedJavaLocalRef<jbyteArray> ToJavaByteArray(JNIEnv* env, |
| std::string_view str) { |
| return ToJavaByteArray(env, base::as_byte_span(str)); |
| } |
| |
| ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray( |
| JNIEnv* env, |
| const std::vector<bool>& bools) { |
| return jni_zero::NewArray(env, bools); |
| } |
| |
| ScopedJavaLocalRef<jbooleanArray> ToJavaBooleanArray( |
| JNIEnv* env, |
| base::span<const bool> bools) { |
| return jni_zero::NewArray<bool>(env, bools); |
| } |
| |
| ScopedJavaLocalRef<jintArray> ToJavaIntArray(JNIEnv* env, |
| base::span<const int32_t> ints) { |
| return jni_zero::NewArray<int32_t>(env, ints); |
| } |
| |
| ScopedJavaLocalRef<jlongArray> ToJavaLongArray( |
| JNIEnv* env, |
| base::span<const int64_t> longs) { |
| return jni_zero::NewArray<int64_t>(env, longs); |
| } |
| |
| ScopedJavaLocalRef<jfloatArray> ToJavaFloatArray( |
| JNIEnv* env, |
| base::span<const float> floats) { |
| return jni_zero::NewArray<float>(env, floats); |
| } |
| |
| ScopedJavaLocalRef<jdoubleArray> ToJavaDoubleArray( |
| JNIEnv* env, |
| base::span<const double> doubles) { |
| return jni_zero::NewArray<double>(env, doubles); |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects( |
| JNIEnv* env, |
| jclass clazz, |
| base::span<const ScopedJavaLocalRef<jobject>> v) { |
| return jni_zero::NewArray<jobject>(env, v, clazz); |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfObjects( |
| JNIEnv* env, |
| base::span<const ScopedJavaLocalRef<jobject>> v) { |
| return jni_zero::NewObjectArray<ScopedJavaLocalRef<jobject>>(env, v); |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToTypedJavaArrayOfObjects( |
| JNIEnv* env, |
| base::span<const ScopedJavaLocalRef<jobject>> v, |
| jclass type) { |
| return jni_zero::NewArray<jobject>(env, v, type); |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray( |
| JNIEnv* env, |
| base::span<const std::string> v) { |
| ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B"); |
| ScopedJavaLocalRef<jobjectArray> joa = |
| jni_zero::NewArray<jobject>(env, v.size(), byte_array_clazz.obj()); |
| for (size_t i = 0; i < v.size(); ++i) { |
| ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(env, v[i]); |
| joa.Set(env, i, byte_array); |
| } |
| return joa; |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfByteArray( |
| JNIEnv* env, |
| base::span<const std::vector<uint8_t>> v) { |
| ScopedJavaLocalRef<jclass> byte_array_clazz = GetClass(env, "[B"); |
| ScopedJavaLocalRef<jobjectArray> joa = |
| jni_zero::NewArray<jobject>(env, v.size(), byte_array_clazz.obj()); |
| for (size_t i = 0; i < v.size(); ++i) { |
| ScopedJavaLocalRef<jbyteArray> byte_array = ToJavaByteArray(env, v[i]); |
| joa.Set(env, i, byte_array); |
| } |
| return joa; |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings( |
| JNIEnv* env, |
| base::span<const std::string> v) { |
| return jni_zero::NewStringArray<std::string>(env, v); |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStringArray( |
| JNIEnv* env, |
| base::span<const std::vector<std::string>> vec_outer) { |
| ScopedJavaLocalRef<jclass> string_array_clazz = |
| GetClass(env, "[Ljava/lang/String;"); |
| |
| ScopedJavaLocalRef<jobjectArray> joa = jni_zero::NewArray<jobject>( |
| env, vec_outer.size(), string_array_clazz.obj()); |
| |
| for (size_t i = 0; i < vec_outer.size(); ++i) { |
| ScopedJavaLocalRef<jobjectArray> inner = |
| ToJavaArrayOfStrings(env, vec_outer[i]); |
| joa.Set(env, i, inner); |
| } |
| |
| return 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;"); |
| |
| ScopedJavaLocalRef<jobjectArray> joa = jni_zero::NewArray<jobject>( |
| env, vec_outer.size(), string_array_clazz.obj()); |
| |
| for (size_t i = 0; i < vec_outer.size(); ++i) { |
| ScopedJavaLocalRef<jobjectArray> inner = |
| ToJavaArrayOfStrings(env, vec_outer[i]); |
| joa.Set(env, i, inner); |
| } |
| |
| return joa; |
| } |
| |
| ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfStrings( |
| JNIEnv* env, |
| base::span<const std::u16string> v) { |
| return jni_zero::NewStringArray<std::u16string>(env, v); |
| } |
| |
| void AppendJavaStringArrayToStringVector(JNIEnv* env, |
| const JavaRef<jobjectArray>& array, |
| std::vector<std::u16string>* out) { |
| DCHECK(out); |
| if (!array) { |
| return; |
| } |
| size_t len = array.GetSize(env); |
| if (!len) { |
| return; |
| } |
| size_t old_size = out->size(); |
| out->resize(old_size + len); |
| span<std::u16string> back = span(*out).last(len); |
| for (size_t i = 0; i < len; ++i) { |
| back[i] = array.GetAs<std::u16string>(env, i); |
| } |
| } |
| |
| void AppendJavaStringArrayToStringVector(JNIEnv* env, |
| const JavaRef<jobjectArray>& array, |
| std::vector<std::string>* out) { |
| DCHECK(out); |
| if (!array) { |
| return; |
| } |
| size_t len = array.GetSize(env); |
| if (!len) { |
| return; |
| } |
| size_t old_size = out->size(); |
| out->resize(old_size + len); |
| span<std::string> back = span(*out).last(len); |
| for (size_t i = 0; i < len; ++i) { |
| back[i] = array.GetAs<std::string>(env, i); |
| } |
| } |
| |
| void AppendJavaByteArrayToByteVector(JNIEnv* env, |
| const JavaRef<jbyteArray>& byte_array, |
| std::vector<uint8_t>* out) { |
| DCHECK(out); |
| if (!byte_array) { |
| return; |
| } |
| size_t len = byte_array.GetSize(env); |
| if (!len) { |
| return; |
| } |
| size_t old_size = out->size(); |
| out->resize(old_size + len); |
| byte_array.CopyTo(env, span(*out).subspan(old_size).data(), len); |
| } |
| |
| void JavaByteArrayToByteVector(JNIEnv* env, |
| const JavaRef<jbyteArray>& byte_array, |
| std::vector<uint8_t>* out) { |
| DCHECK(out); |
| DCHECK(byte_array); |
| size_t len = byte_array.GetSize(env); |
| out->resize(len); |
| byte_array.CopyTo(env, out->data(), len); |
| } |
| |
| size_t JavaByteArrayToByteSpan(JNIEnv* env, |
| const JavaRef<jbyteArray>& byte_array, |
| base::span<uint8_t> dest) { |
| CHECK(byte_array); |
| size_t len = byte_array.GetSize(env); |
| CHECK_GE(dest.size(), len); |
| byte_array.CopyTo(env, dest.data(), len); |
| return len; |
| } |
| |
| void JavaByteArrayToString(JNIEnv* env, |
| const JavaRef<jbyteArray>& byte_array, |
| std::string* out) { |
| DCHECK(out); |
| CHECK(byte_array); |
| size_t len = byte_array.GetSize(env); |
| out->resize(len); |
| byte_array.CopyTo(env, out->data(), len); |
| } |
| |
| void JavaBooleanArrayToBoolVector(JNIEnv* env, |
| const JavaRef<jbooleanArray>& boolean_array, |
| std::vector<bool>* out) { |
| DCHECK(out); |
| if (!boolean_array) { |
| return; |
| } |
| *out = jni_zero::FromJniArray<std::vector<bool>>(env, boolean_array); |
| } |
| |
| void JavaIntArrayToIntVector(JNIEnv* env, |
| const JavaRef<jintArray>& int_array, |
| std::vector<int>* out) { |
| DCHECK(out); |
| size_t len = int_array.GetSize(env); |
| out->resize(len); |
| int_array.CopyTo(env, out->data(), len); |
| } |
| |
| void JavaLongArrayToInt64Vector(JNIEnv* env, |
| const JavaRef<jlongArray>& long_array, |
| std::vector<int64_t>* out) { |
| JavaLongArrayToLongVector(env, long_array, out); |
| } |
| |
| void JavaLongArrayToLongVector(JNIEnv* env, |
| const JavaRef<jlongArray>& long_array, |
| std::vector<int64_t>* out) { |
| DCHECK(out); |
| size_t len = long_array.GetSize(env); |
| out->resize(len); |
| long_array.CopyTo(env, out->data(), len); |
| } |
| |
| void JavaFloatArrayToFloatVector(JNIEnv* env, |
| const JavaRef<jfloatArray>& float_array, |
| std::vector<float>* out) { |
| DCHECK(out); |
| size_t len = float_array.GetSize(env); |
| out->resize(len); |
| float_array.CopyTo(env, out->data(), len); |
| } |
| |
| void JavaDoubleArrayToDoubleVector(JNIEnv* env, |
| const JavaRef<jdoubleArray>& double_array, |
| std::vector<double>* out) { |
| DCHECK(out); |
| size_t len = double_array.GetSize(env); |
| out->resize(len); |
| double_array.CopyTo(env, out->data(), len); |
| } |
| |
| void JavaArrayOfByteArrayToStringVector(JNIEnv* env, |
| const JavaRef<jobjectArray>& array, |
| std::vector<std::string>* out) { |
| DCHECK(out); |
| size_t len = array.GetSize(env); |
| out->resize(len); |
| for (size_t i = 0; i < len; ++i) { |
| ScopedJavaLocalRef<jbyteArray> bytes_array = |
| array.GetAs<jbyteArray>(env, i); |
| JavaByteArrayToString(env, bytes_array, &(*out)[i]); |
| } |
| } |
| |
| void JavaArrayOfByteArrayToBytesVector(JNIEnv* env, |
| const JavaRef<jobjectArray>& array, |
| std::vector<std::vector<uint8_t>>* out) { |
| DCHECK(out); |
| const size_t len = array.GetSize(env); |
| out->resize(len); |
| for (size_t i = 0; i < len; ++i) { |
| ScopedJavaLocalRef<jbyteArray> bytes_array = |
| array.GetAs<jbyteArray>(env, 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 = array.GetSize(env); |
| out->resize(len); |
| for (size_t i = 0; i < len; ++i) { |
| ScopedJavaLocalRef<jobjectArray> strings_array = |
| array.GetAs<jobjectArray>(env, i); |
| (*out)[i].clear(); |
| AppendJavaStringArrayToStringVector(env, strings_array, &(*out)[i]); |
| } |
| } |
| |
| void Java2dStringArrayTo2dStringVector( |
| JNIEnv* env, |
| const JavaRef<jobjectArray>& array, |
| std::vector<std::vector<std::string>>* out) { |
| DCHECK(out); |
| size_t len = array.GetSize(env); |
| out->resize(len); |
| for (size_t i = 0; i < len; ++i) { |
| ScopedJavaLocalRef<jobjectArray> strings_array = |
| array.GetAs<jobjectArray>(env, i); |
| (*out)[i].clear(); |
| AppendJavaStringArrayToStringVector(env, strings_array, &(*out)[i]); |
| } |
| } |
| |
| void JavaArrayOfIntArrayToIntVector(JNIEnv* env, |
| const JavaRef<jobjectArray>& array, |
| std::vector<std::vector<int>>* out) { |
| DCHECK(out); |
| size_t len = array.GetSize(env); |
| out->resize(len); |
| for (size_t i = 0; i < len; ++i) { |
| ScopedJavaLocalRef<jintArray> int_array = array.GetAs<jintArray>(env, i); |
| JavaIntArrayToIntVector(env, int_array, &(*out)[i]); |
| } |
| } |
| |
| } // namespace base::android |