From 4285729d5c7557fbf226b8ed9908f97dbbc48ad3 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 12 Jul 2023 09:29:05 +0300 Subject: [PATCH] BAN: Generalize HashMapIterator to IteratorDouble This iterator should be able to iterate any container within container with type iterator defined. This also fixed bug if first entry in outer container is empty container. --- BAN/include/BAN/HashMap.h | 101 ++------------------------------ BAN/include/BAN/Iterators.h | 112 +++++++++++++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 98 deletions(-) diff --git a/BAN/include/BAN/HashMap.h b/BAN/include/BAN/HashMap.h index c1ad9d672f..e9715c92fe 100644 --- a/BAN/include/BAN/HashMap.h +++ b/BAN/include/BAN/HashMap.h @@ -30,7 +30,7 @@ namespace BAN using size_type = size_t; using key_type = Key; using value_type = T; - using iterator = HashMapIterator; + using iterator = IteratorDouble; public: HashMap() = default; @@ -46,8 +46,8 @@ namespace BAN template ErrorOr emplace(const Key&, Args&&...); - iterator begin() { return iterator(m_buckets, m_buckets.begin()); } - iterator end() { return iterator(m_buckets, m_buckets.end()); } + iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); } + iterator end() { return iterator(m_buckets.end(), m_buckets.end()); } ErrorOr reserve(size_type); @@ -74,99 +74,6 @@ namespace BAN friend iterator; }; - template - class HashMapIterator - { - public: - using KeyValue = typename Container::Entry; - - public: - HashMapIterator() = default; - - const KeyValue& operator*() const - { - ASSERT(*this); - ASSERT(!at_end()); - return *m_entry_iterator; - } - KeyValue& operator*() - { - ASSERT(*this); - ASSERT(!at_end()); - return *m_entry_iterator; - } - - HashMapIterator& operator++() - { - ASSERT(*this); - ASSERT(!at_end()); - ++m_entry_iterator; - while (m_entry_iterator == m_bucket_iterator->end()) - { - ++m_bucket_iterator; - if (m_bucket_iterator == m_container.end()) - { - m_entry_iterator = {}; - break; - } - m_entry_iterator = m_bucket_iterator->begin(); - } - return *this; - } - - HashMapIterator operator++(int) - { - auto temp = *this; - ++(*this); - return temp; - } - - bool operator==(const HashMapIterator& other) const - { - if (&m_container != &other.m_container) - return false; - if (m_bucket_iterator != other.m_bucket_iterator) - return false; - if (m_bucket_iterator == m_container.end()) - return true; - if (m_entry_iterator && other.m_entry_iterator) - return m_entry_iterator == other.m_entry_iterator; - if (!m_entry_iterator && !other.m_entry_iterator) - return true; - return false; - } - bool operator!=(const HashMapIterator& other) const - { - return !(*this == other); - } - - operator bool() const - { - return m_bucket_iterator && m_entry_iterator; - } - - private: - HashMapIterator(Vector>& container, Vector>::iterator current) - : m_container(container) - , m_bucket_iterator(current) - { - if (current != container.end()) - m_entry_iterator = current->begin(); - } - - bool at_end() const - { - return m_bucket_iterator == m_container.end(); - } - - private: - Vector>& m_container; - Vector>::iterator m_bucket_iterator; - LinkedList::iterator m_entry_iterator; - - friend Container; - }; - template HashMap::HashMap(const HashMap& other) { @@ -348,4 +255,4 @@ namespace BAN return m_buckets[index]; } -} \ No newline at end of file +} diff --git a/BAN/include/BAN/Iterators.h b/BAN/include/BAN/Iterators.h index 37ea338605..421d33a802 100644 --- a/BAN/include/BAN/Iterators.h +++ b/BAN/include/BAN/Iterators.h @@ -156,4 +156,114 @@ namespace BAN friend Container; }; -} \ No newline at end of file + + template typename OuterContainer, template typename InnerContainer, typename Container> + class IteratorDouble + { + public: + using Inner = InnerContainer; + using Outer = OuterContainer; + + public: + IteratorDouble() = default; + + const T& operator*() const + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + return m_inner_current.operator*(); + } + T& operator*() + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + return m_inner_current.operator*(); + } + + const T* operator->() const + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + return m_inner_current.operator->(); + } + T* operator->() + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + return m_inner_current.operator->(); + } + + IteratorDouble& operator++() + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + m_inner_current++; + find_valid_or_end(); + return *this; + } + IteratorDouble operator++(int) + { + auto temp = *this; + ++(*this); + return temp; + } + + bool operator==(const IteratorDouble& other) const + { + if (!*this || !other) + return false; + if (m_outer_end != other.m_outer_end) + return false; + if (m_outer_current != other.m_outer_current) + return false; + if (m_outer_current == m_outer_end) + return true; + return m_inner_current == other.m_inner_current; + } + bool operator!=(const IteratorDouble& other) const + { + return !(*this == other); + } + + operator bool() const + { + return m_outer_end && m_outer_current; + } + + private: + IteratorDouble(Outer::iterator outer_end, Outer::iterator outer_current) + : m_outer_end(outer_end) + , m_outer_current(outer_current) + { + if (outer_current != outer_end) + { + m_inner_current = m_outer_current->begin(); + find_valid_or_end(); + } + } + + void find_valid_or_end() + { + while (m_inner_current == m_outer_current->end()) + { + m_outer_current++; + if (m_outer_current == m_outer_end) + break; + m_inner_current = m_outer_current->begin(); + } + } + + private: + Outer::iterator m_outer_end; + Outer::iterator m_outer_current; + Inner::iterator m_inner_current; + + friend Container; + }; + +}