Add DoublyLinkedList data structure
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2022-12-06 17:37:43 +01:00
parent dd29156c85
commit 87fb195202
Signed by: apio
GPG Key ID: B8A7D06E42258954

View File

@ -0,0 +1,118 @@
#pragma once
#include <luna/Result.h>
template <typename T> inline Result<T*> nonnull_or_error(T* ptr)
{
return ptr == nullptr ? err(ENONE) : ptr;
}
template <typename T> class DoublyLinkedList;
template <typename T> class DoublyLinkedListNode
{
private:
DoublyLinkedListNode<T>* m_next_node;
DoublyLinkedListNode<T>* m_last_node;
void detach_from_list()
{
m_next_node->m_last_node = m_last_node;
m_last_node->m_next_node = m_next_node;
}
void add_to_list(DoublyLinkedListNode<T>* end_node)
{
end_node->m_next_node = this;
this->m_last_node = end_node;
}
friend class DoublyLinkedList<T>;
};
template <typename T> class DoublyLinkedList
{
public:
void append(T* ptr)
{
DoublyLinkedListNode<T>* node = (DoublyLinkedListNode<T>*)ptr;
if (!m_start_node) m_start_node = node;
if (m_end_node) node->add_to_list(m_end_node);
m_end_node = node;
m_count++;
}
T* remove(T* ptr)
{
DoublyLinkedListNode<T>* node = (DoublyLinkedListNode<T>*)ptr;
if (node == m_end_node) m_end_node = node->m_last_node;
if (node == m_start_node) m_start_node = node->m_next_node;
node->detach_from_list();
m_count--;
return ptr;
}
Result<T*> first()
{
return nonnull_or_error((T*)m_start_node);
}
Result<T*> last()
{
return nonnull_or_error((T*)m_end_node);
}
Result<T*> next(T* item)
{
return nonnull_or_error(((DoublyLinkedListNode<T>*)item)->m_next_node);
}
Result<T*> previous(T* item)
{
return nonnull_or_error(((DoublyLinkedListNode<T>*)item)->m_last_node);
}
template <typename Callback> void for_each(Callback callback)
{
for (DoublyLinkedListNode<T>* node = m_start_node; node; node = node->m_next_node) { callback((T*)node); }
}
template <typename Callback> void for_each_reversed(Callback callback)
{
for (DoublyLinkedListNode<T>* node = m_end_node; node; node = node->m_last_node) { callback((T*)node); }
}
template <typename Callback> void for_each_after(T* start, Callback callback)
{
for (DoublyLinkedListNode<T>* node = ((DoublyLinkedListNode<T>*)start)->m_next_node; node;
node = node->m_next_node)
{
callback((T*)node);
}
}
template <typename Callback> void for_each_before(T* end, Callback callback)
{
for (DoublyLinkedListNode<T>* node = ((DoublyLinkedListNode<T>*)end)->m_last_node; node;
node = node->m_last_node)
{
callback((T*)node);
}
}
usize count()
{
return m_count;
}
private:
DoublyLinkedListNode<T>* m_start_node = nullptr;
DoublyLinkedListNode<T>* m_end_node = nullptr;
usize m_count = 0;
};