#ifndef CORE_LINKED_LIST_HPP #define CORE_LINKED_LIST_HPP #include "core/utils/ArrayString.hpp" namespace Core { template struct LinkedList final { class Node final { friend LinkedList; Node* next; Node* previous; public: T data; template Node(Args&&... args) : next(nullptr), previous(nullptr), data(Core::forward(args)...) { } }; template struct IteratorBase final { NT* current; public: IteratorBase& operator++() { current = current->next; return *this; } bool operator!=(const IteratorBase& other) const { return current != other.current; } R& operator*() const { return current->data; } }; using Iterator = IteratorBase; using ConstIterator = IteratorBase; private: Node* first; Node* last; i64 length; public: LinkedList() : first(nullptr), last(nullptr), length(0) { } LinkedList(const LinkedList& other) = delete; LinkedList(LinkedList&& other) : LinkedList() { swap(other); } ~LinkedList() { clear(); } LinkedList& operator=(const LinkedList& other) = delete; LinkedList& operator=(LinkedList&& other) { swap(other); return *this; } check_return Error copyFrom(const LinkedList& other) { LinkedList copy; for(const T& t : other) { CORE_RETURN_ERROR(copy.add(t)); } swap(copy); return Error::NONE; } template check_return Error put(Node*& n, Args&&... args) { n = new Node(Core::forward(args)...); if(n == nullptr) { return Error::OUT_OF_MEMORY; } length++; if(first == nullptr) { first = n; last = n; return Error::NONE; } last->next = n; n->previous = last; last = n; return Error::NONE; } template check_return Error add(Args&&... args) { Node* n = nullptr; return put(n, Core::forward(args)...); } Iterator begin() { return {first}; } Iterator end() { return {nullptr}; } ConstIterator begin() const { return {first}; } ConstIterator end() const { return {nullptr}; } i64 getLength() const { return length; } void clear() { Node* n = first; while(n != nullptr) { Node* next = n->next; delete n; n = next; } length = 0; first = nullptr; last = nullptr; } template check_return Error toString(String& s) const { return Core::toString(s, *this); } void remove(Node*& n) { if(n == nullptr) { return; } if(n == first) { if(first->next != nullptr) { first->next->previous = nullptr; } first = first->next; } if(n == last) { if(last->previous != nullptr) { last->previous->next = nullptr; } last = last->previous; } if(n->previous != nullptr) { n->previous->next = n->next; } if(n->next != nullptr) { n->next->previous = n->previous; } length--; delete n; n = nullptr; } void removeFirst() { Node* n = first; // prevent first from becoming null remove(n); } void removeLast() { Node* n = last; // prevent last from becoming null remove(n); } void swap(LinkedList& other) { Core::swap(first, other.first); Core::swap(last, other.last); Core::swap(length, other.length); } }; } #endif