Chromium Code Reviews| Index: webrtc/api/java/jni/jni_helpers.h |
| diff --git a/webrtc/api/java/jni/jni_helpers.h b/webrtc/api/java/jni/jni_helpers.h |
| index 87c5ca48f22e1089bd8cf2ad39468cc17c82e8bb..ec5a45f8d2135ba293619135cfe548d2199cc3a2 100644 |
| --- a/webrtc/api/java/jni/jni_helpers.h |
| +++ b/webrtc/api/java/jni/jni_helpers.h |
| @@ -17,6 +17,7 @@ |
| #include <jni.h> |
| #include <string> |
| +#include "webrtc/base/constructormagic.h" |
| #include "webrtc/base/checks.h" |
| // Abort the process if |jni| has a Java exception pending. |
| @@ -122,6 +123,104 @@ class ScopedGlobalRef { |
| T obj_; |
| }; |
| +// Provides a convenient way to iterate over a Java collection using the |
| +// C++ range-for loop. |
| +// E.g. for (jobject value : JavaCollection(jni, j_collection)) { ... } |
| +// Note: Since Java iterators cannot be duplicated, this class is not copyable |
| +// to prevent creating multiple C++ iterators that refer to the same Java |
| +// iterator. |
| +class JavaCollectionIterator { |
|
pthatcher1
2016/03/21 21:57:00
It would actually be JavaIterableIterator.
How ab
skvlad
2016/03/21 22:27:39
Done.
|
| + public: |
| + // Creates an iterator representing the end of any collection. |
| + JavaCollectionIterator() : iterator_(NULL) {} |
| + // Creates an iterator pointing to the beginning of the specified collection. |
| + JavaCollectionIterator(JNIEnv* jni, jobject collection) : jni_(jni) { |
| + jclass j_class = GetObjectClass(jni, collection); |
| + jmethodID iterator_id = |
| + GetMethodID(jni, j_class, "iterator", "()Ljava/util/Iterator;"); |
| + iterator_ = jni->CallObjectMethod(collection, iterator_id); |
| + CHECK_EXCEPTION(jni) << "error during CallObjectMethod"; |
| + |
| + if (iterator_ == NULL) { |
| + // TODO(skvlad): Should this be an exception instead? |
| + return; |
| + } |
| + |
| + jclass iterator_class = GetObjectClass(jni, iterator_); |
| + has_next_id_ = GetMethodID(jni, iterator_class, "hasNext", "()Z"); |
| + next_id_ = GetMethodID(jni, iterator_class, "next", "()Ljava/lang/Object;"); |
| + |
| + // Start at the first element in the collection |
| + ++(*this); |
| + } |
| + |
| + // Move constructor - necessary to be able to return iterator types from |
| + // functions |
| + JavaCollectionIterator(JavaCollectionIterator&& other) |
| + : jni_(std::move(other.jni_)), |
| + iterator_(std::move(other.iterator_)), |
| + value_(std::move(other.value_)), |
| + has_next_id_(std::move(other.has_next_id_)), |
| + next_id_(std::move(other.next_id_)){}; |
| + |
| + // Move assignment should not be used. |
| + JavaCollectionIterator& operator=(JavaCollectionIterator&&) = delete; |
| + |
| + // Advances the iterator one step |
| + JavaCollectionIterator& operator++() { |
| + if (iterator_ == NULL) { |
| + // Can't iterate past the end |
| + return *this; |
| + } |
| + bool have_next = jni_->CallBooleanMethod(iterator_, has_next_id_); |
|
pthatcher1
2016/03/21 21:57:00
have_next => has_next
skvlad
2016/03/21 22:27:39
Done.
|
| + CHECK_EXCEPTION(jni_) << "error during CallBooleanMethod"; |
| + if (!have_next) { |
| + iterator_ = NULL; |
| + return *this; |
| + } |
| + |
| + value_ = jni_->CallObjectMethod(iterator_, next_id_); |
| + CHECK_EXCEPTION(jni_) << "error during CallObjectMethod"; |
| + return *this; |
| + } |
| + |
| + bool operator==(const JavaCollectionIterator& other) { |
| + return (iterator_ == other.iterator_); |
| + } |
| + |
| + bool operator!=(const JavaCollectionIterator& other) { |
| + return !(*this == other); |
| + } |
| + |
| + jobject operator*() { return value_; } |
| + |
| + private: |
| + JNIEnv* jni_ = NULL; |
| + jobject iterator_ = NULL; |
| + jobject value_ = NULL; |
| + jmethodID has_next_id_ = NULL; |
| + jmethodID next_id_ = NULL; |
| + |
| + RTC_DISALLOW_COPY_AND_ASSIGN(JavaCollectionIterator); |
| +}; |
| + |
| +class JavaCollection { |
|
pthatcher1
2016/03/21 21:57:01
webrtc_jni::Iterable?
skvlad
2016/03/21 22:27:39
Done.
|
| + public: |
| + using iterator = JavaCollectionIterator; |
| + explicit JavaCollection(JNIEnv* jni, jobject collection) |
|
pthatcher1
2016/03/21 21:57:01
collection => iterable
skvlad
2016/03/21 22:27:39
Done.
|
| + : jni_(jni), collection_(collection) {} |
| + |
| + iterator begin() { return JavaCollectionIterator(jni_, collection_); } |
| + |
| + iterator end() { return JavaCollectionIterator(); } |
| + |
| + private: |
| + JNIEnv* jni_; |
| + jobject collection_; |
|
pthatcher1
2016/03/21 21:57:00
iterable_
skvlad
2016/03/21 22:27:39
Done.
|
| + |
| + RTC_DISALLOW_COPY_AND_ASSIGN(JavaCollection); |
| +}; |
| + |
| } // namespace webrtc_jni |
| #endif // WEBRTC_API_JAVA_JNI_JNI_HELPERS_H_ |