diff --git a/BAN/include/BAN/HashMap.h b/BAN/include/BAN/HashMap.h index c1ad9d67..e9715c92 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 37ea3386..421d33a8 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; + }; + +}