Skip to content

Commit

Permalink
AK: Add reverse iterator support to AK::IntrusiveList
Browse files Browse the repository at this point in the history
In order for IntrusiveList to be capable of replacing InlineLinkedList,
it needs to support reverse iteration. InlineLinkedList currently
supports manual reverse iteration by calling list->last() followed by
node->prev().
  • Loading branch information
bgianfo authored and awesomekling committed Jun 3, 2021
1 parent e37f39d commit ef4fdcf
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions AK/IntrusiveList.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,34 @@ class IntrusiveList {
Iterator begin();
Iterator end() { return Iterator {}; }

class ReverseIterator {
public:
ReverseIterator() = default;
ReverseIterator(T* value)
: m_value(move(value))
{
}

const T& operator*() const { return *m_value; }
auto operator->() const { return m_value; }
T& operator*() { return *m_value; }
auto operator->() { return m_value; }
bool operator==(const ReverseIterator& other) const { return other.m_value == m_value; }
bool operator!=(const ReverseIterator& other) const { return !(*this == other); }
ReverseIterator& operator++()
{
m_value = IntrusiveList<T, Container, member>::prev(m_value);
return *this;
}
ReverseIterator& erase();

private:
T* m_value { nullptr };
};

ReverseIterator rbegin();
ReverseIterator rend() { return ReverseIterator {}; }

class ConstIterator {
public:
ConstIterator() = default;
Expand Down Expand Up @@ -116,7 +144,9 @@ class IntrusiveList {

private:
static T* next(T* current);
static T* prev(T* current);
static const T* next(const T* current);
static const T* prev(const T* current);
static T* node_to_value(IntrusiveListNode<T, Container>& node);
IntrusiveListStorage<T, Container> m_storage;
};
Expand Down Expand Up @@ -278,6 +308,14 @@ inline const T* IntrusiveList<T, Container, member>::next(const T* current)
return nextstruct;
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline const T* IntrusiveList<T, Container, member>::prev(const T* current)
{
auto& prevnode = (current->*member).m_prev;
const T* prevstruct = prevnode ? node_to_value(*prevnode) : nullptr;
return prevstruct;
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline T* IntrusiveList<T, Container, member>::next(T* current)
{
Expand All @@ -286,12 +324,26 @@ inline T* IntrusiveList<T, Container, member>::next(T* current)
return nextstruct;
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline T* IntrusiveList<T, Container, member>::prev(T* current)
{
auto& prevnode = (current->*member).m_prev;
T* prevstruct = prevnode ? node_to_value(*prevnode) : nullptr;
return prevstruct;
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline typename IntrusiveList<T, Container, member>::Iterator IntrusiveList<T, Container, member>::begin()
{
return m_storage.m_first ? Iterator(node_to_value(*m_storage.m_first)) : Iterator();
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline typename IntrusiveList<T, Container, member>::ReverseIterator IntrusiveList<T, Container, member>::rbegin()
{
return m_storage.m_last ? ReverseIterator(node_to_value(*m_storage.m_last)) : ReverseIterator();
}

template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline typename IntrusiveList<T, Container, member>::ConstIterator IntrusiveList<T, Container, member>::begin() const
{
Expand Down

0 comments on commit ef4fdcf

Please sign in to comment.