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
3 // found in the LICENSE file.
5 #include "base/android/jni_array.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/logging.h"
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
) {
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
));
28 ScopedJavaLocalRef
<jbyteArray
> ToJavaByteArray(
29 JNIEnv
* env
, const uint8
* bytes
, size_t len
) {
30 jbyteArray byte_array
= env
->NewByteArray(len
);
34 env
->SetByteArrayRegion(
35 byte_array
, 0, len
, reinterpret_cast<const jbyte
*>(bytes
));
38 return ScopedJavaLocalRef
<jbyteArray
>(env
, byte_array
);
41 ScopedJavaLocalRef
<jintArray
> ToJavaIntArray(
42 JNIEnv
* env
, const int* ints
, size_t len
) {
43 jintArray int_array
= env
->NewIntArray(len
);
47 env
->SetIntArrayRegion(
48 int_array
, 0, len
, reinterpret_cast<const jint
*>(ints
));
51 return ScopedJavaLocalRef
<jintArray
>(env
, int_array
);
54 ScopedJavaLocalRef
<jintArray
> ToJavaIntArray(
55 JNIEnv
* env
, const std::vector
<int>& ints
) {
56 return ToJavaIntArray(env
, ints
.data(), ints
.size());
59 ScopedJavaLocalRef
<jlongArray
> ToJavaLongArray(
60 JNIEnv
* env
, const int64
* longs
, size_t len
) {
61 jlongArray long_array
= env
->NewLongArray(len
);
65 env
->SetLongArrayRegion(
66 long_array
, 0, len
, reinterpret_cast<const jlong
*>(longs
));
69 return ScopedJavaLocalRef
<jlongArray
>(env
, long_array
);
72 // Returns a new Java long array converted from the given int64 array.
73 BASE_EXPORT ScopedJavaLocalRef
<jlongArray
> ToJavaLongArray(
74 JNIEnv
* env
, const std::vector
<int64
>& longs
) {
75 return ToJavaLongArray(env
, longs
.data(), longs
.size());
78 ScopedJavaLocalRef
<jobjectArray
> ToJavaArrayOfByteArray(
79 JNIEnv
* env
, const std::vector
<std::string
>& v
) {
80 ScopedJavaLocalRef
<jclass
> byte_array_clazz
= GetClass(env
, "[B");
81 jobjectArray joa
= env
->NewObjectArray(v
.size(),
82 byte_array_clazz
.obj(), NULL
);
85 for (size_t i
= 0; i
< v
.size(); ++i
) {
86 ScopedJavaLocalRef
<jbyteArray
> byte_array
= ToJavaByteArray(env
,
87 reinterpret_cast<const uint8
*>(v
[i
].data()), v
[i
].length());
88 env
->SetObjectArrayElement(joa
, i
, byte_array
.obj());
90 return ScopedJavaLocalRef
<jobjectArray
>(env
, joa
);
93 ScopedJavaLocalRef
<jobjectArray
> ToJavaArrayOfStrings(
94 JNIEnv
* env
, const std::vector
<std::string
>& v
) {
95 ScopedJavaLocalRef
<jclass
> string_clazz
= GetClass(env
, "java/lang/String");
96 jobjectArray joa
= env
->NewObjectArray(v
.size(), string_clazz
.obj(), NULL
);
99 for (size_t i
= 0; i
< v
.size(); ++i
) {
100 ScopedJavaLocalRef
<jstring
> item
= ConvertUTF8ToJavaString(env
, v
[i
]);
101 env
->SetObjectArrayElement(joa
, i
, item
.obj());
103 return ScopedJavaLocalRef
<jobjectArray
>(env
, joa
);
106 ScopedJavaLocalRef
<jobjectArray
> ToJavaArrayOfStrings(
107 JNIEnv
* env
, const std::vector
<string16
>& v
) {
108 ScopedJavaLocalRef
<jclass
> string_clazz
= GetClass(env
, "java/lang/String");
109 jobjectArray joa
= env
->NewObjectArray(v
.size(), string_clazz
.obj(), NULL
);
112 for (size_t i
= 0; i
< v
.size(); ++i
) {
113 ScopedJavaLocalRef
<jstring
> item
= ConvertUTF16ToJavaString(env
, v
[i
]);
114 env
->SetObjectArrayElement(joa
, i
, item
.obj());
116 return ScopedJavaLocalRef
<jobjectArray
>(env
, joa
);
119 void AppendJavaStringArrayToStringVector(JNIEnv
* env
,
121 std::vector
<string16
>* out
) {
125 size_t len
= SafeGetArrayLength(env
, array
);
126 size_t back
= out
->size();
127 out
->resize(back
+ len
);
128 for (size_t i
= 0; i
< len
; ++i
) {
129 ScopedJavaLocalRef
<jstring
> str(env
,
130 static_cast<jstring
>(env
->GetObjectArrayElement(array
, i
)));
131 ConvertJavaStringToUTF16(env
, str
.obj(), &((*out
)[back
+ i
]));
135 void AppendJavaStringArrayToStringVector(JNIEnv
* env
,
137 std::vector
<std::string
>* out
) {
141 size_t len
= SafeGetArrayLength(env
, array
);
142 size_t back
= out
->size();
143 out
->resize(back
+ len
);
144 for (size_t i
= 0; i
< len
; ++i
) {
145 ScopedJavaLocalRef
<jstring
> str(env
,
146 static_cast<jstring
>(env
->GetObjectArrayElement(array
, i
)));
147 ConvertJavaStringToUTF8(env
, str
.obj(), &((*out
)[back
+ i
]));
151 void AppendJavaByteArrayToByteVector(JNIEnv
* env
,
152 jbyteArray byte_array
,
153 std::vector
<uint8
>* out
) {
157 size_t len
= SafeGetArrayLength(env
, byte_array
);
160 size_t back
= out
->size();
161 out
->resize(back
+ len
);
162 env
->GetByteArrayRegion(byte_array
, 0, len
,
163 reinterpret_cast<int8
*>(&(*out
)[back
]));
166 void JavaByteArrayToByteVector(JNIEnv
* env
,
167 jbyteArray byte_array
,
168 std::vector
<uint8
>* out
) {
172 AppendJavaByteArrayToByteVector(env
, byte_array
, out
);
175 void JavaIntArrayToIntVector(JNIEnv
* env
,
177 std::vector
<int>* out
) {
179 size_t len
= SafeGetArrayLength(env
, int_array
);
183 // TODO(jdduke): Use |out->data()| for pointer access after switch to libc++,
184 // both here and in the other conversion routines. See crbug.com/427718.
185 env
->GetIntArrayRegion(int_array
, 0, len
, &(*out
)[0]);
188 void JavaLongArrayToLongVector(JNIEnv
* env
,
189 jlongArray long_array
,
190 std::vector
<jlong
>* out
) {
192 size_t len
= SafeGetArrayLength(env
, long_array
);
196 env
->GetLongArrayRegion(long_array
, 0, len
, &(*out
)[0]);
199 void JavaFloatArrayToFloatVector(JNIEnv
* env
,
200 jfloatArray float_array
,
201 std::vector
<float>* out
) {
203 size_t len
= SafeGetArrayLength(env
, float_array
);
207 env
->GetFloatArrayRegion(float_array
, 0, len
, &(*out
)[0]);
210 void JavaArrayOfByteArrayToStringVector(
213 std::vector
<std::string
>* out
) {
215 size_t len
= SafeGetArrayLength(env
, array
);
217 for (size_t i
= 0; i
< len
; ++i
) {
218 ScopedJavaLocalRef
<jbyteArray
> bytes_array(
219 env
, static_cast<jbyteArray
>(
220 env
->GetObjectArrayElement(array
, i
)));
221 jsize bytes_len
= env
->GetArrayLength(bytes_array
.obj());
222 jbyte
* bytes
= env
->GetByteArrayElements(bytes_array
.obj(), NULL
);
223 (*out
)[i
].assign(reinterpret_cast<const char*>(bytes
), bytes_len
);
224 env
->ReleaseByteArrayElements(bytes_array
.obj(), bytes
, JNI_ABORT
);
228 } // namespace android