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 |