blob: 95625678be772344b3a8af7b64eea40ecc847d18 [file] [log] [blame]
[email protected]fe0f1ab2012-02-09 21:02:271// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f98d7b92011-09-09 10:17:352// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_ANDROID_SCOPED_JAVA_REF_H_
6#define BASE_ANDROID_SCOPED_JAVA_REF_H_
7
8#include <jni.h>
9#include <stddef.h>
10
tzik403cb6c2016-03-10 07:17:2511#include <type_traits>
tornec6bc15d2016-08-25 15:42:5712#include <utility>
tzik403cb6c2016-03-10 07:17:2513
[email protected]be363b22012-11-01 17:38:4714#include "base/base_export.h"
tornecf273552015-08-24 17:41:3415#include "base/logging.h"
avib30f2402015-12-24 03:43:2816#include "base/macros.h"
[email protected]f98d7b92011-09-09 10:17:3517
18namespace base {
19namespace android {
20
[email protected]b3fd32d2014-04-08 01:01:5021// Creates a new local reference frame, in which at least a given number of
22// local references can be created. Note that local references already created
23// in previous local frames are still valid in the current local frame.
24class BASE_EXPORT ScopedJavaLocalFrame {
25 public:
26 explicit ScopedJavaLocalFrame(JNIEnv* env);
27 ScopedJavaLocalFrame(JNIEnv* env, int capacity);
28 ~ScopedJavaLocalFrame();
29
30 private:
31 // This class is only good for use on the thread it was created on so
32 // it's safe to cache the non-threadsafe JNIEnv* inside this object.
33 JNIEnv* env_;
34
35 DISALLOW_COPY_AND_ASSIGN(ScopedJavaLocalFrame);
36};
37
[email protected]f98d7b92011-09-09 10:17:3538// Forward declare the generic java reference template class.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5939template <typename T>
40class JavaRef;
[email protected]f98d7b92011-09-09 10:17:3541
42// Template specialization of JavaRef, which acts as the base class for all
43// other JavaRef<> template types. This allows you to e.g. pass
44// ScopedJavaLocalRef<jstring> into a function taking const JavaRef<jobject>&
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5945template <>
[email protected]be363b22012-11-01 17:38:4746class BASE_EXPORT JavaRef<jobject> {
[email protected]f98d7b92011-09-09 10:17:3547 public:
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5948 // Initializes a null reference.
49 constexpr JavaRef() {}
torne7588d912016-11-30 10:55:2450
torne8a47be62015-12-03 13:08:0051 // Allow nullptr to be converted to JavaRef. This avoids having to declare an
torne7588d912016-11-30 10:55:2452 // empty JavaRef just to pass null to a function, and makes C++ "nullptr" and
53 // Java "null" equivalent.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5954 constexpr JavaRef(std::nullptr_t) {}
torne8a47be62015-12-03 13:08:0055
torne7588d912016-11-30 10:55:2456 // Public to allow destruction of null JavaRef objects.
torne8a47be62015-12-03 13:08:0057 ~JavaRef() {}
58
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5959 // TODO(torne): maybe rename this to get() for consistency with unique_ptr
60 // once there's fewer unnecessary uses of it in the codebase.
[email protected]f98d7b92011-09-09 10:17:3561 jobject obj() const { return obj_; }
62
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5963 explicit operator bool() const { return obj_ != nullptr; }
64
65 // Deprecated. Just use bool conversion.
66 // TODO(torne): replace usage and remove this.
torne8a372f7252016-08-08 16:29:1867 bool is_null() const { return obj_ == nullptr; }
[email protected]fe0f1ab2012-02-09 21:02:2768
[email protected]f98d7b92011-09-09 10:17:3569 protected:
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5970// Takes ownership of the |obj| reference passed; requires it to be a local
71// reference type.
tornecf273552015-08-24 17:41:3472#if DCHECK_IS_ON()
73 // Implementation contains a DCHECK; implement out-of-line when DCHECK_IS_ON.
[email protected]f98d7b92011-09-09 10:17:3574 JavaRef(JNIEnv* env, jobject obj);
tornecf273552015-08-24 17:41:3475#else
tornecf273552015-08-24 17:41:3476 JavaRef(JNIEnv* env, jobject obj) : obj_(obj) {}
77#endif
[email protected]f98d7b92011-09-09 10:17:3578
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5979 // Used for move semantics. obj_ must have been released first if non-null.
80 void steal(JavaRef&& other) {
81 obj_ = other.obj_;
82 other.obj_ = nullptr;
83 }
tornec6bc15d2016-08-25 15:42:5784
[email protected]f98d7b92011-09-09 10:17:3585 // The following are implementation detail convenience methods, for
86 // use by the sub-classes.
[email protected]6b5324292012-03-22 13:52:5787 JNIEnv* SetNewLocalRef(JNIEnv* env, jobject obj);
[email protected]f98d7b92011-09-09 10:17:3588 void SetNewGlobalRef(JNIEnv* env, jobject obj);
[email protected]6b5324292012-03-22 13:52:5789 void ResetLocalRef(JNIEnv* env);
[email protected]fe0f1ab2012-02-09 21:02:2790 void ResetGlobalRef();
[email protected]f98d7b92011-09-09 10:17:3591 jobject ReleaseInternal();
92
93 private:
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:5994 jobject obj_ = nullptr;
[email protected]f98d7b92011-09-09 10:17:3595
96 DISALLOW_COPY_AND_ASSIGN(JavaRef);
97};
98
Torne (Richard Coles)f73cd9d2019-04-29 20:56:1499// Forward declare the object array reader for the convenience function.
100template <typename T>
101class JavaObjectArrayReader;
102
[email protected]f98d7b92011-09-09 10:17:35103// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
104// for allowing functions to accept a reference without having to mandate
105// whether it is a local or global type.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59106template <typename T>
[email protected]f98d7b92011-09-09 10:17:35107class JavaRef : public JavaRef<jobject> {
108 public:
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59109 constexpr JavaRef() {}
110 constexpr JavaRef(std::nullptr_t) {}
torne8a47be62015-12-03 13:08:00111 ~JavaRef() {}
112
[email protected]f98d7b92011-09-09 10:17:35113 T obj() const { return static_cast<T>(JavaRef<jobject>::obj()); }
114
Torne (Richard Coles)f73cd9d2019-04-29 20:56:14115 // Get a JavaObjectArrayReader for the array pointed to by this reference.
116 // Only defined for JavaRef<jobjectArray>.
117 // You must pass the type of the array elements (usually jobject) as the
118 // template parameter.
119 template <typename ElementType,
120 typename T_ = T,
121 typename = std::enable_if_t<std::is_same<T_, jobjectArray>::value>>
122 JavaObjectArrayReader<ElementType> ReadElements() const {
123 return JavaObjectArrayReader<ElementType>(*this);
124 }
125
[email protected]f98d7b92011-09-09 10:17:35126 protected:
[email protected]f98d7b92011-09-09 10:17:35127 JavaRef(JNIEnv* env, T obj) : JavaRef<jobject>(env, obj) {}
128
129 private:
130 DISALLOW_COPY_AND_ASSIGN(JavaRef);
131};
132
torne89cc5d92015-09-04 11:16:35133// Holds a local reference to a JNI method parameter.
134// Method parameters should not be deleted, and so this class exists purely to
135// wrap them as a JavaRef<T> in the JNI binding generator. Do not create
136// instances manually.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59137template <typename T>
torne89cc5d92015-09-04 11:16:35138class JavaParamRef : public JavaRef<T> {
139 public:
140 // Assumes that |obj| is a parameter passed to a JNI method from Java.
141 // Does not assume ownership as parameters should not be deleted.
142 JavaParamRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj) {}
143
Torne (Richard Coles)0b2cd652015-11-27 18:12:28144 // Allow nullptr to be converted to JavaParamRef. Some unit tests call JNI
145 // methods directly from C++ and pass null for objects which are not actually
146 // used by the implementation (e.g. the caller object); allow this to keep
147 // working.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59148 JavaParamRef(std::nullptr_t) {}
Torne (Richard Coles)0b2cd652015-11-27 18:12:28149
torne89cc5d92015-09-04 11:16:35150 ~JavaParamRef() {}
151
152 // TODO(torne): remove this cast once we're using JavaRef consistently.
153 // http://crbug.com/506850
154 operator T() const { return JavaRef<T>::obj(); }
155
156 private:
157 DISALLOW_COPY_AND_ASSIGN(JavaParamRef);
158};
159
[email protected]f98d7b92011-09-09 10:17:35160// Holds a local reference to a Java object. The local reference is scoped
[email protected]6b5324292012-03-22 13:52:57161// to the lifetime of this object.
162// Instances of this class may hold onto any JNIEnv passed into it until
163// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
164// thread, objects of this class must be created, used, and destroyed, on a
165// single thread.
166// Therefore, this class should only be used as a stack-based object and from a
167// single thread. If you wish to have the reference outlive the current
168// callstack (e.g. as a class member) or you wish to pass it across threads,
169// use a ScopedJavaGlobalRef instead.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59170template <typename T>
[email protected]f98d7b92011-09-09 10:17:35171class ScopedJavaLocalRef : public JavaRef<T> {
172 public:
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59173 // Take ownership of a bare jobject. This does not create a new reference.
174 // This should only be used by JNI helper functions, or in cases where code
175 // must call JNIEnv methods directly.
176 static ScopedJavaLocalRef Adopt(JNIEnv* env, T obj) {
177 return ScopedJavaLocalRef(env, obj);
[email protected]f98d7b92011-09-09 10:17:35178 }
179
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59180 constexpr ScopedJavaLocalRef() {}
181 constexpr ScopedJavaLocalRef(std::nullptr_t) {}
182
183 // Copy constructor. This is required in addition to the copy conversion
184 // constructor below.
185 ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) {
186 JavaRef<T>::SetNewLocalRef(env_, other.obj());
tornec6bc15d2016-08-25 15:42:57187 }
188
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59189 // Copy conversion constructor.
190 template <typename U,
191 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
192 ScopedJavaLocalRef(const ScopedJavaLocalRef<U>& other) : env_(other.env_) {
193 JavaRef<T>::SetNewLocalRef(env_, other.obj());
[email protected]f98d7b92011-09-09 10:17:35194 }
195
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59196 // Move constructor. This is required in addition to the move conversion
197 // constructor below.
198 ScopedJavaLocalRef(ScopedJavaLocalRef&& other) : env_(other.env_) {
199 JavaRef<T>::steal(std::move(other));
200 }
201
202 // Move conversion constructor.
203 template <typename U,
204 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
205 ScopedJavaLocalRef(ScopedJavaLocalRef<U>&& other) : env_(other.env_) {
206 JavaRef<T>::steal(std::move(other));
207 }
208
209 // Constructor for other JavaRef types.
210 explicit ScopedJavaLocalRef(const JavaRef<T>& other) { Reset(other); }
211
[email protected]f98d7b92011-09-09 10:17:35212 // Assumes that |obj| is a local reference to a Java object and takes
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59213 // ownership of this local reference.
214 // TODO(torne): make legitimate uses call Adopt() instead, and make this
215 // private.
[email protected]6b5324292012-03-22 13:52:57216 ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(env, obj), env_(env) {}
[email protected]f98d7b92011-09-09 10:17:35217
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59218 ~ScopedJavaLocalRef() { Reset(); }
219
220 // Null assignment, for disambiguation.
221 ScopedJavaLocalRef& operator=(std::nullptr_t) {
222 Reset();
223 return *this;
[email protected]f98d7b92011-09-09 10:17:35224 }
225
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59226 // Copy assignment.
227 ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef& other) {
228 Reset(other);
229 return *this;
[email protected]f98d7b92011-09-09 10:17:35230 }
231
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59232 // Copy conversion assignment.
233 template <typename U,
234 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
235 ScopedJavaLocalRef& operator=(const ScopedJavaLocalRef<U>& other) {
236 Reset(other);
237 return *this;
238 }
239
240 // Move assignment.
241 template <typename U,
242 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
243 ScopedJavaLocalRef& operator=(ScopedJavaLocalRef<U>&& other) {
tornec6bc15d2016-08-25 15:42:57244 env_ = other.env_;
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59245 Reset();
246 JavaRef<T>::steal(std::move(other));
247 return *this;
tornec6bc15d2016-08-25 15:42:57248 }
249
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59250 // Assignment for other JavaRef types.
251 ScopedJavaLocalRef& operator=(const JavaRef<T>& other) {
252 Reset(other);
253 return *this;
[email protected]6b5324292012-03-22 13:52:57254 }
255
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59256 void Reset() { JavaRef<T>::ResetLocalRef(env_); }
257
258 template <typename U,
259 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
260 void Reset(const ScopedJavaLocalRef<U>& other) {
[email protected]6b5324292012-03-22 13:52:57261 // We can copy over env_ here as |other| instance must be from the same
262 // thread as |this| local ref. (See class comment for multi-threading
263 // limitations, and alternatives).
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59264 Reset(other.env_, other.obj());
[email protected]f98d7b92011-09-09 10:17:35265 }
266
torne7588d912016-11-30 10:55:24267 void Reset(const JavaRef<T>& other) {
torne8a372f7252016-08-08 16:29:18268 // If |env_| was not yet set (is still null) it will be attached to the
[email protected]6b5324292012-03-22 13:52:57269 // current thread in SetNewLocalRef().
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59270 Reset(env_, other.obj());
[email protected]f98d7b92011-09-09 10:17:35271 }
272
torne7588d912016-11-30 10:55:24273 // Creates a new local reference to the Java object, unlike the constructor
274 // with the same parameters that takes ownership of the existing reference.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59275 // Deprecated. Don't use bare jobjects; use a JavaRef as the input.
276 // TODO(torne): fix existing usage and remove this.
277 void Reset(JNIEnv* env, T obj) {
278 env_ = JavaRef<T>::SetNewLocalRef(env, obj);
279 }
[email protected]f98d7b92011-09-09 10:17:35280
281 // Releases the local reference to the caller. The caller *must* delete the
torneb105fe32015-08-27 16:57:44282 // local reference when it is done with it. Note that calling a Java method
283 // is *not* a transfer of ownership and Release() should not be used.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59284 T Release() { return static_cast<T>(JavaRef<T>::ReleaseInternal()); }
[email protected]6b5324292012-03-22 13:52:57285
286 private:
287 // This class is only good for use on the thread it was created on so
288 // it's safe to cache the non-threadsafe JNIEnv* inside this object.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59289 JNIEnv* env_ = nullptr;
tornea8dd7a42015-09-09 13:53:07290
291 // Prevent ScopedJavaLocalRef(JNIEnv*, T obj) from being used to take
292 // ownership of a JavaParamRef's underlying object - parameters are not
293 // allowed to be deleted and so should not be owned by ScopedJavaLocalRef.
294 // TODO(torne): this can be removed once JavaParamRef no longer has an
295 // implicit conversion back to T.
296 ScopedJavaLocalRef(JNIEnv* env, const JavaParamRef<T>& other);
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59297
298 // Friend required to get env_ from conversions.
299 template <typename U>
300 friend class ScopedJavaLocalRef;
Torne (Richard Coles)f73cd9d2019-04-29 20:56:14301
302 // Avoids JavaObjectArrayReader having to accept and store its own env.
303 template <typename U>
304 friend class JavaObjectArrayReader;
[email protected]f98d7b92011-09-09 10:17:35305};
306
307// Holds a global reference to a Java object. The global reference is scoped
[email protected]6b5324292012-03-22 13:52:57308// to the lifetime of this object. This class does not hold onto any JNIEnv*
309// passed to it, hence it is safe to use across threads (within the constraints
310// imposed by the underlying Java object that it references).
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59311template <typename T>
[email protected]f98d7b92011-09-09 10:17:35312class ScopedJavaGlobalRef : public JavaRef<T> {
313 public:
Gabriel Charette63fe7062018-01-25 14:14:29314 constexpr ScopedJavaGlobalRef() {}
315 constexpr ScopedJavaGlobalRef(std::nullptr_t) {}
[email protected]f98d7b92011-09-09 10:17:35316
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59317 // Copy constructor. This is required in addition to the copy conversion
318 // constructor below.
319 ScopedJavaGlobalRef(const ScopedJavaGlobalRef& other) { Reset(other); }
320
321 // Copy conversion constructor.
322 template <typename U,
323 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
324 ScopedJavaGlobalRef(const ScopedJavaGlobalRef<U>& other) {
325 Reset(other);
[email protected]f98d7b92011-09-09 10:17:35326 }
327
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59328 // Move constructor. This is required in addition to the move conversion
329 // constructor below.
330 ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other) {
331 JavaRef<T>::steal(std::move(other));
[email protected]f98d7b92011-09-09 10:17:35332 }
333
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59334 // Move conversion constructor.
335 template <typename U,
336 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
337 ScopedJavaGlobalRef(ScopedJavaGlobalRef<U>&& other) {
338 JavaRef<T>::steal(std::move(other));
aberente6c87d5c2015-12-17 13:35:07339 }
340
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59341 // Conversion constructor for other JavaRef types.
342 explicit ScopedJavaGlobalRef(const JavaRef<T>& other) { Reset(other); }
tornec6bc15d2016-08-25 15:42:57343
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59344 // Create a new global reference to the object.
345 // Deprecated. Don't use bare jobjects; use a JavaRef as the input.
346 ScopedJavaGlobalRef(JNIEnv* env, T obj) { Reset(env, obj); }
347
348 ~ScopedJavaGlobalRef() { Reset(); }
349
350 // Null assignment, for disambiguation.
351 ScopedJavaGlobalRef& operator=(std::nullptr_t) {
352 Reset();
353 return *this;
[email protected]f98d7b92011-09-09 10:17:35354 }
355
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59356 // Copy assignment.
357 ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef& other) {
358 Reset(other);
359 return *this;
360 }
[email protected]f98d7b92011-09-09 10:17:35361
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59362 // Copy conversion assignment.
363 template <typename U,
364 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
365 ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef<U>& other) {
366 Reset(other);
367 return *this;
368 }
369
370 // Move assignment.
371 template <typename U,
372 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
373 ScopedJavaGlobalRef& operator=(ScopedJavaGlobalRef<U>&& other) {
374 Reset();
375 JavaRef<T>::steal(std::move(other));
376 return *this;
377 }
378
379 // Assignment for other JavaRef types.
380 ScopedJavaGlobalRef& operator=(const JavaRef<T>& other) {
381 Reset(other);
382 return *this;
383 }
384
385 void Reset() { JavaRef<T>::ResetGlobalRef(); }
386
387 template <typename U,
388 typename = std::enable_if_t<std::is_convertible<U, T>::value>>
389 void Reset(const ScopedJavaGlobalRef<U>& other) {
390 Reset(nullptr, other.obj());
391 }
392
393 void Reset(const JavaRef<T>& other) { Reset(nullptr, other.obj()); }
394
395 // Deprecated. You can just use Reset(const JavaRef&).
torne7588d912016-11-30 10:55:24396 void Reset(JNIEnv* env, const JavaParamRef<T>& other) {
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59397 Reset(env, other.obj());
torne89cc5d92015-09-04 11:16:35398 }
399
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59400 // Deprecated. Don't use bare jobjects; use a JavaRef as the input.
401 void Reset(JNIEnv* env, T obj) { JavaRef<T>::SetNewGlobalRef(env, obj); }
[email protected]f98d7b92011-09-09 10:17:35402
403 // Releases the global reference to the caller. The caller *must* delete the
torneb105fe32015-08-27 16:57:44404 // global reference when it is done with it. Note that calling a Java method
405 // is *not* a transfer of ownership and Release() should not be used.
Torne (Richard Coles)2ac4c6c2018-10-11 16:43:59406 T Release() { return static_cast<T>(JavaRef<T>::ReleaseInternal()); }
[email protected]f98d7b92011-09-09 10:17:35407};
408
Torne (Richard Coles)f73cd9d2019-04-29 20:56:14409// Wrapper for a jobjectArray which supports input iteration, allowing Java
410// arrays to be iterated over with a range-based for loop, or used with
411// <algorithm> functions that accept input iterators.
412//
413// The iterator returns each object in the array in turn, wrapped in a
414// ScopedJavaLocalRef<T>. T will usually be jobject, but if you know that the
415// array contains a more specific type (such as jstring) you can use that
416// instead. This does not check the type at runtime!
417//
418// The wrapper holds a local reference to the array and only queries the size of
419// the array once, so must only be used as a stack-based object from the current
420// thread.
421//
422// Note that this does *not* update the contents of the array if you mutate the
423// returned ScopedJavaLocalRef.
424template <typename T>
425class JavaObjectArrayReader {
426 public:
427 class iterator {
428 public:
429 // We can only be an input iterator, as all richer iterator types must
430 // implement the multipass guarantee (always returning the same object for
431 // the same iterator position), which is not practical when returning
432 // temporary objects.
433 using iterator_category = std::input_iterator_tag;
434
435 using difference_type = ptrdiff_t;
436 using value_type = ScopedJavaLocalRef<T>;
437
438 // It doesn't make sense to return a reference type as the iterator creates
439 // temporary wrapper objects when dereferenced. Fortunately, it's not
440 // required that input iterators actually use references, and defining it
441 // as value_type is valid.
442 using reference = value_type;
443
444 // This exists to make operator-> work as expected: its return value must
445 // resolve to an actual pointer (otherwise the compiler just keeps calling
446 // operator-> on the return value until it does), so we need an extra level
447 // of indirection. This is sometimes called an "arrow proxy" or similar, and
448 // this version is adapted from base/value_iterators.h.
449 class pointer {
450 public:
451 explicit pointer(const reference& ref) : ref_(ref) {}
452 pointer(const pointer& ptr) = default;
453 pointer& operator=(const pointer& ptr) = delete;
454 reference* operator->() { return &ref_; }
455
456 private:
457 reference ref_;
458 };
459
460 iterator(const iterator&) = default;
461 ~iterator() = default;
462
463 iterator& operator=(const iterator&) = default;
464
465 bool operator==(const iterator& other) const {
466 DCHECK(reader_ == other.reader_);
467 return i_ == other.i_;
468 }
469
470 bool operator!=(const iterator& other) const {
471 DCHECK(reader_ == other.reader_);
472 return i_ != other.i_;
473 }
474
475 reference operator*() const {
476 DCHECK(i_ < reader_->size_);
477 // JNIEnv functions return unowned local references; take ownership with
478 // Adopt so that ~ScopedJavaLocalRef will release it automatically later.
479 return value_type::Adopt(
480 reader_->array_.env_,
481 static_cast<T>(reader_->array_.env_->GetObjectArrayElement(
482 reader_->array_.obj(), i_)));
483 }
484
485 pointer operator->() const { return pointer(operator*()); }
486
487 iterator& operator++() {
488 DCHECK(i_ < reader_->size_);
489 ++i_;
490 return *this;
491 }
492
493 iterator operator++(int) {
494 iterator old = *this;
495 ++*this;
496 return old;
497 }
498
499 private:
500 iterator(const JavaObjectArrayReader* reader, jsize i)
501 : reader_(reader), i_(i) {}
502 const JavaObjectArrayReader* reader_;
503 jsize i_;
504
505 friend JavaObjectArrayReader;
506 };
507
508 JavaObjectArrayReader(const JavaRef<jobjectArray>& array) : array_(array) {
509 size_ = array_.env_->GetArrayLength(array_.obj());
510 }
511
512 // Copy constructor to allow returning it from JavaRef::ReadElements().
513 JavaObjectArrayReader(const JavaObjectArrayReader& other) = default;
514
515 // Assignment operator for consistency with copy constructor.
516 JavaObjectArrayReader& operator=(const JavaObjectArrayReader& other) =
517 default;
518
519 // Allow move constructor and assignment since this owns a local ref.
520 JavaObjectArrayReader(JavaObjectArrayReader&& other) = default;
521 JavaObjectArrayReader& operator=(JavaObjectArrayReader&& other) = default;
522
523 bool empty() const { return size_ == 0; }
524
525 jsize size() const { return size_; }
526
527 iterator begin() const { return iterator(this, 0); }
528
529 iterator end() const { return iterator(this, size_); }
530
531 private:
532 ScopedJavaLocalRef<jobjectArray> array_;
533 jsize size_;
534
535 friend iterator;
536};
537
[email protected]f98d7b92011-09-09 10:17:35538} // namespace android
539} // namespace base
540
541#endif // BASE_ANDROID_SCOPED_JAVA_REF_H_