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);
}
}
}