cxx/fbjni/detail/Iterator-inl.h (183 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once namespace facebook { namespace jni { namespace detail { template <typename E> struct IteratorHelper : public JavaClass<IteratorHelper<E>> { constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/IteratorHelper;"; typedef local_ref<E> value_type; typedef ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; typedef std::forward_iterator_tag iterator_category; typedef JavaClass<IteratorHelper<E>> JavaBase_; bool hasNext() const { static auto hasNextMethod = JavaBase_::javaClassStatic()->template getMethod<jboolean()>("hasNext"); return hasNextMethod(JavaBase_::self()); } value_type next() { static auto elementField = JavaBase_::javaClassStatic()->template getField<jobject>("mElement"); return dynamic_ref_cast<E>(JavaBase_::getFieldValue(elementField)); } static void reset(value_type& v) { v.reset(); } }; template <typename K, typename V> struct MapIteratorHelper : public JavaClass<MapIteratorHelper<K,V>> { constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/MapIteratorHelper;"; typedef std::pair<local_ref<K>, local_ref<V>> value_type; typedef JavaClass<MapIteratorHelper<K,V>> JavaBase_; bool hasNext() const { static auto hasNextMethod = JavaBase_::javaClassStatic()->template getMethod<jboolean()>("hasNext"); return hasNextMethod(JavaBase_::self()); } value_type next() { static auto keyField = JavaBase_::javaClassStatic()->template getField<jobject>("mKey"); static auto valueField = JavaBase_::javaClassStatic()->template getField<jobject>("mValue"); return std::make_pair(dynamic_ref_cast<K>(JavaBase_::getFieldValue(keyField)), dynamic_ref_cast<V>(JavaBase_::getFieldValue(valueField))); } static void reset(value_type& v) { v.first.reset(); v.second.reset(); } }; template <typename T> class Iterator { public: typedef typename T::value_type value_type; typedef ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type& reference; typedef std::input_iterator_tag iterator_category; // begin ctor Iterator(global_ref<typename T::javaobject>&& helper) : helper_(std::move(helper)) , i_(-1) { ++(*this); } // end ctor Iterator() : i_(-1) {} bool operator==(const Iterator& it) const { return i_ == it.i_; } bool operator!=(const Iterator& it) const { return !(*this == it); } const value_type& operator*() const { assert(i_ != -1); return entry_; } const value_type* operator->() const { assert(i_ != -1); return &entry_; } Iterator& operator++() { // preincrement bool hasNext = helper_->hasNext(); if (hasNext) { ++i_; entry_ = helper_->next(); } else { i_ = -1; helper_->reset(entry_); } return *this; } Iterator operator++(int) { // postincrement Iterator ret; ret.i_ = i_; ret.entry_ = std::move(entry_); ++(*this); return ret; } global_ref<T> helper_; // set to -1 at end std::ptrdiff_t i_; value_type entry_; }; } template <typename E> struct JIterator<E>::Iterator : public detail::Iterator<detail::IteratorHelper<E>> { using detail::Iterator<detail::IteratorHelper<E>>::Iterator; }; template <typename E> typename JIterator<E>::Iterator JIterator<E>::begin() const { static auto ctor = detail::IteratorHelper<E>::javaClassStatic()-> template getConstructor<typename detail::IteratorHelper<E>::javaobject( typename JIterator<E>::javaobject)>(); return Iterator( make_global( detail::IteratorHelper<E>::javaClassStatic()->newObject(ctor, this->self()))); } template <typename E> typename JIterator<E>::Iterator JIterator<E>::end() const { return Iterator(); } template <typename E> struct JIterable<E>::Iterator : public detail::Iterator<detail::IteratorHelper<E>> { using detail::Iterator<detail::IteratorHelper<E>>::Iterator; }; template <typename E> typename JIterable<E>::Iterator JIterable<E>::begin() const { static auto ctor = detail::IteratorHelper<E>::javaClassStatic()-> template getConstructor<typename detail::IteratorHelper<E>::javaobject( typename JIterable<E>::javaobject)>(); return Iterator( make_global( detail::IteratorHelper<E>::javaClassStatic()->newObject(ctor, this->self()))); } template <typename E> typename JIterable<E>::Iterator JIterable<E>::end() const { return Iterator(); } template <typename E> size_t JCollection<E>::size() const { static auto sizeMethod = JCollection<E>::javaClassStatic()->template getMethod<jint()>("size"); return sizeMethod(this->self()); } template <typename E> bool JCollection<E>::add(alias_ref<E> elem) { static auto addMethod = JCollection<E>::javaClassStatic()-> template getMethod<jboolean(alias_ref<JObject>)>("add"); return addMethod(this->self(), elem); } template <typename K, typename V> struct JMap<K,V>::Iterator : public detail::Iterator<detail::MapIteratorHelper<K,V>> { using detail::Iterator<detail::MapIteratorHelper<K,V>>::Iterator; }; template <typename K, typename V> size_t JMap<K,V>::size() const { static auto sizeMethod = JMap<K,V>::javaClassStatic()->template getMethod<jint()>("size"); return sizeMethod(this->self()); } template <typename K, typename V> typename JMap<K,V>::Iterator JMap<K,V>::begin() const { static auto ctor = detail::MapIteratorHelper<K,V>::javaClassStatic()-> template getConstructor<typename detail::MapIteratorHelper<K,V>::javaobject( typename JMap<K,V>::javaobject)>(); return Iterator( make_global( detail::MapIteratorHelper<K,V>::javaClassStatic()->newObject(ctor, this->self()))); } template <typename K, typename V> typename JMap<K,V>::Iterator JMap<K,V>::end() const { return Iterator(); } template <typename K, typename V> local_ref<JObject> JMap<K,V>::put(alias_ref<K> key, alias_ref<V> val) { static auto putMethod = JMap<K,V>::javaClassStatic()-> template getMethod<JObject(alias_ref<JObject>, alias_ref<JObject>)>("put"); return putMethod(this->self(), key, val); } template <typename E> local_ref<JArrayList<E>> JArrayList<E>::create() { return JArrayList<E>::newInstance(); } template <typename E> local_ref<JArrayList<E>> JArrayList<E>::create(int initialCapacity) { return JArrayList<E>::newInstance(initialCapacity); } template <typename K, typename V> local_ref<JHashMap<K, V>> JHashMap<K,V>::create() { return JHashMap<K,V>::newInstance(); } template <typename K, typename V> local_ref<JHashMap<K, V>> JHashMap<K,V>::create(int initialCapacity) { return JHashMap<K,V>::newInstance(initialCapacity); } } }