From 87fb19520268842b09caa5094dca441ffa488769 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 6 Dec 2022 17:37:43 +0100 Subject: [PATCH] Add DoublyLinkedList data structure --- luna/include/luna/LinkedList.h | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 luna/include/luna/LinkedList.h diff --git a/luna/include/luna/LinkedList.h b/luna/include/luna/LinkedList.h new file mode 100644 index 00000000..c4ab8f58 --- /dev/null +++ b/luna/include/luna/LinkedList.h @@ -0,0 +1,118 @@ +#pragma once +#include + +template inline Result nonnull_or_error(T* ptr) +{ + return ptr == nullptr ? err(ENONE) : ptr; +} + +template class DoublyLinkedList; + +template class DoublyLinkedListNode +{ + + private: + DoublyLinkedListNode* m_next_node; + DoublyLinkedListNode* 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* end_node) + { + end_node->m_next_node = this; + this->m_last_node = end_node; + } + + friend class DoublyLinkedList; +}; + +template class DoublyLinkedList +{ + public: + void append(T* ptr) + { + DoublyLinkedListNode* node = (DoublyLinkedListNode*)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* node = (DoublyLinkedListNode*)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 first() + { + return nonnull_or_error((T*)m_start_node); + } + + Result last() + { + return nonnull_or_error((T*)m_end_node); + } + + Result next(T* item) + { + return nonnull_or_error(((DoublyLinkedListNode*)item)->m_next_node); + } + + Result previous(T* item) + { + return nonnull_or_error(((DoublyLinkedListNode*)item)->m_last_node); + } + + template void for_each(Callback callback) + { + for (DoublyLinkedListNode* node = m_start_node; node; node = node->m_next_node) { callback((T*)node); } + } + + template void for_each_reversed(Callback callback) + { + for (DoublyLinkedListNode* node = m_end_node; node; node = node->m_last_node) { callback((T*)node); } + } + + template void for_each_after(T* start, Callback callback) + { + for (DoublyLinkedListNode* node = ((DoublyLinkedListNode*)start)->m_next_node; node; + node = node->m_next_node) + { + callback((T*)node); + } + } + + template void for_each_before(T* end, Callback callback) + { + for (DoublyLinkedListNode* node = ((DoublyLinkedListNode*)end)->m_last_node; node; + node = node->m_last_node) + { + callback((T*)node); + } + } + + usize count() + { + return m_count; + } + + private: + DoublyLinkedListNode* m_start_node = nullptr; + DoublyLinkedListNode* m_end_node = nullptr; + + usize m_count = 0; +}; \ No newline at end of file