blob: ee6bf44281fadea6b30c3187881e8b462b721d23 [file]
// 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