#pragma once #include #include "prelude/string.hpp" template struct ListNode { T value; ListNode* prev = nullptr; ListNode* next = nullptr; }; template class DoubleLinkedList { public: DoubleLinkedList() = default; public: static DoubleLinkedList FromView(const View &view) { auto list = DoubleLinkedList(); for (size_t i = 0; i < view.size; ++i) { list.Append(new ListNode(view.data[i])); } return list; } public: View ToView() { Builder b; for(ListNode* cur = Begin(); cur != nullptr; cur = cur->next) { b.Push(cur->value); } return b.view(); } public: void Append(ListNode* node) { if (IsEmpty()) { node->next = nullptr; node->prev = nullptr; tail = node; head = node; } else { head->next = node; node->prev = head; node->next = nullptr; head = node; } m_size++; } void Prepend(ListNode* node) { if (IsEmpty()) { Append(node); } else { tail->prev = node; node->next = tail; node->prev = nullptr; tail = node; m_size++; } } void SpliceFront(ListNode* node) { if (m_size == 1 && tail == node && head == node) return; assert((node->next || node->prev) && "node should be inside of the linked list"); if (node == tail) return; if (node == head) { node->prev->next = nullptr; head = node->prev; } else { node->prev->next = node->next; node->next->prev = node->prev; } m_size--; Prepend(node); } bool IsEmpty() const { return m_size == 0; } ListNode* Begin() const { return tail; } ListNode* End() const { return head; } private: ListNode* head = nullptr; ListNode* tail = nullptr; size_t m_size = 0; };