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.
This commit is contained in:
parent
12d53ac233
commit
65424a6769
|
@ -30,7 +30,7 @@ namespace BAN
|
|||
using size_type = size_t;
|
||||
using key_type = Key;
|
||||
using value_type = T;
|
||||
using iterator = HashMapIterator<HashMap>;
|
||||
using iterator = IteratorDouble<Entry, Vector, LinkedList, HashMap>;
|
||||
|
||||
public:
|
||||
HashMap() = default;
|
||||
|
@ -46,8 +46,8 @@ namespace BAN
|
|||
template<typename... Args>
|
||||
ErrorOr<void> 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<void> reserve(size_type);
|
||||
|
||||
|
@ -74,99 +74,6 @@ namespace BAN
|
|||
friend iterator;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
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<LinkedList<KeyValue>>& container, Vector<LinkedList<KeyValue>>::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<LinkedList<KeyValue>>& m_container;
|
||||
Vector<LinkedList<KeyValue>>::iterator m_bucket_iterator;
|
||||
LinkedList<KeyValue>::iterator m_entry_iterator;
|
||||
|
||||
friend Container;
|
||||
};
|
||||
|
||||
template<typename Key, typename T, typename HASH>
|
||||
HashMap<Key, T, HASH>::HashMap(const HashMap<Key, T, HASH>& other)
|
||||
{
|
||||
|
@ -348,4 +255,4 @@ namespace BAN
|
|||
return m_buckets[index];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,4 +156,114 @@ namespace BAN
|
|||
|
||||
friend Container;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, template <typename> typename OuterContainer, template <typename> typename InnerContainer, typename Container>
|
||||
class IteratorDouble
|
||||
{
|
||||
public:
|
||||
using Inner = InnerContainer<T>;
|
||||
using Outer = OuterContainer<Inner>;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue