From 0df8378971553a203cc6982a298f342baecae543 Mon Sep 17 00:00:00 2001 From: Gil Date: Thu, 19 Apr 2018 11:30:29 -0700 Subject: Implement iterators for our immutable maps (#1132) * Add a minimal LlrbNodeIterator * Remove fixed_size type parameter from FixedArray The parameter wasn't that useful and caused problems in trying to define dependent iterator types. * Add begin()/end() to SortedMap. --- .../firestore/immutable/sorted_map_iterator.h | 191 +++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 Firestore/core/src/firebase/firestore/immutable/sorted_map_iterator.h (limited to 'Firestore/core/src/firebase/firestore/immutable/sorted_map_iterator.h') diff --git a/Firestore/core/src/firebase/firestore/immutable/sorted_map_iterator.h b/Firestore/core/src/firebase/firestore/immutable/sorted_map_iterator.h new file mode 100644 index 0000000..36f3967 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/immutable/sorted_map_iterator.h @@ -0,0 +1,191 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_SORTED_MAP_ITERATOR_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_SORTED_MAP_ITERATOR_H_ + +#include + +#include "Firestore/core/src/firebase/firestore/immutable/array_sorted_map.h" +#include "Firestore/core/src/firebase/firestore/immutable/tree_sorted_map.h" + +namespace firebase { +namespace firestore { +namespace immutable { +namespace impl { + +template +class SortedMapIterator { + public: + using iterator_category = std::forward_iterator_tag; + using value_type = V; + using pointer = const value_type*; + using reference = const value_type&; + using difference_type = std::ptrdiff_t; + + public: + // Default constructor to conform to the requirements of ForwardIterator + SortedMapIterator() : tag_{Tag::Array}, array_iter_{} { + } + + explicit SortedMapIterator(ArrayIter&& delegate) + : tag_{Tag::Array}, array_iter_{std::move(delegate)} { + } + + explicit SortedMapIterator(TreeIter&& delegate) + : tag_{Tag::Tree}, tree_iter_{std::move(delegate)} { + } + + SortedMapIterator(const SortedMapIterator& other) : tag_(other.tag_) { + switch (tag_) { + case Tag::Array: + new (&array_iter_) ArrayIter{other.array_iter_}; + break; + case Tag::Tree: + new (&tree_iter_) TreeIter{other.tree_iter_}; + break; + } + } + + SortedMapIterator(SortedMapIterator&& other) : tag_(other.tag_) { + switch (tag_) { + case Tag::Array: + new (&array_iter_) ArrayIter{std::move(other.array_iter_)}; + break; + case Tag::Tree: + new (&tree_iter_) TreeIter{std::move(other.tree_iter_)}; + break; + } + } + + ~SortedMapIterator() { + switch (tag_) { + case Tag::Array: + array_iter_.~ArrayIter(); + break; + case Tag::Tree: + tree_iter_.~TreeIter(); + break; + } + } + + SortedMapIterator& operator=(const SortedMapIterator& other) { + if (tag_ == other.tag_) { + switch (tag_) { + case Tag::Array: + array_iter_ = other.array_iter_; + break; + case Tag::Tree: + tree_iter_ = other.tree_iter_; + break; + } + } else { + this->~SortedMapIterator(); + new (this) SortedMapIterator(other); + } + return *this; + } + + SortedMapIterator& operator=(SortedMapIterator&& other) { + if (tag_ == other.tag_) { + switch (tag_) { + case Tag::Array: + array_iter_ = std::move(other.array_iter_); + break; + case Tag::Tree: + tree_iter_ = std::move(other.tree_iter_); + break; + } + } else { + this->~SortedMapIterator(); + new (this) SortedMapIterator(std::move(other)); + } + return *this; + } + + pointer get() const { + switch (tag_) { + case Tag::Array: + return array_iter_; + case Tag::Tree: + return tree_iter_.get(); + } + } + + reference operator*() const { + return *get(); + } + + pointer operator->() const { + return get(); + } + + SortedMapIterator& operator++() { + switch (tag_) { + case Tag::Array: + ++array_iter_; + break; + case Tag::Tree: + ++tree_iter_; + break; + } + return *this; + } + + SortedMapIterator operator++(int /*unused*/) { + SortedMapIterator result = *this; + ++*this; + return result; + } + + friend bool operator==(const SortedMapIterator& a, + const SortedMapIterator& b) { + if (a.tag_ != b.tag_) { + return false; + } + + switch (a.tag_) { + case Tag::Array: + return a.array_iter_ == b.array_iter_; + case Tag::Tree: + return a.tree_iter_ == b.tree_iter_; + } + FIREBASE_UNREACHABLE(); + } + + bool operator!=(const SortedMapIterator& b) const { + return !(*this == b); + } + + private: + enum class Tag { + Array, + Tree, + }; + + Tag tag_; + union { + ArrayIter array_iter_; + TreeIter tree_iter_; + }; +}; + +} // namespace impl +} // namespace immutable +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_IMMUTABLE_SORTED_MAP_ITERATOR_H_ -- cgit v1.2.3