#ifndef SLANG_CORE_LINKED_LIST_H #define SLANG_CORE_LINKED_LIST_H #include "../../slang.h" #include "slang-allocator.h" namespace Slang { template class LinkedList; template class LinkedNode { template friend class LinkedList; private: LinkedNode* prev = nullptr; LinkedNode* next = nullptr; LinkedList* list; public: T Value; LinkedNode(LinkedList* lnk) : list(lnk) { }; LinkedNode* GetPrevious() { return prev; }; LinkedNode* GetNext() { return next; }; LinkedNode* InsertAfter(const T& nData) { LinkedNode* n = new LinkedNode(list); n->Value = nData; n->prev = this; n->next = this->next; LinkedNode* npp = n->next; if (npp) { npp->prev = n; } next = n; if (!n->next) list->tail = n; list->count++; return n; }; LinkedNode* InsertBefore(const T& nData) { LinkedNode* n = new LinkedNode(list); n->Value = nData; n->prev = prev; n->next = this; prev = n; LinkedNode* npp = n->prev; if (npp) npp->next = n; if (!n->prev) list->head = n; list->count++; return n; }; void Delete() { if (prev) prev->next = next; if (next) next->prev = prev; list->count--; if (list->head == this) { list->head = next; } if (list->tail == this) { list->tail = prev; } delete this; } }; template class LinkedList { template friend class LinkedNode; private: LinkedNode*head, *tail; int count; public: class Iterator { public: LinkedNode*Current, *Next; void SetCurrent(LinkedNode* cur) { Current = cur; if (Current) Next = Current->GetNext(); else Next = 0; } Iterator() { Current = Next = 0; } Iterator(LinkedNode* cur) { SetCurrent(cur); } T& operator*() const { return Current->Value; } Iterator& operator++() { SetCurrent(Next); return *this; } Iterator operator++(int) { Iterator rs = *this; SetCurrent(Next); return rs; } bool operator!=(const Iterator& iter) const { return Current != iter.Current; } bool operator==(const Iterator& iter) const { return Current == iter.Current; } }; Iterator begin() const { return Iterator(head); } Iterator end() const { return Iterator(0); } public: LinkedList() : head(0) , tail(0) , count(0) {} ~LinkedList() { Clear(); } LinkedList(const LinkedList& link) : head(0) , tail(0) , count(0) { this->operator=(link); } LinkedList(LinkedList&& link) : head(0) , tail(0) , count(0) { this->operator=(_Move(link)); } LinkedList& operator=(LinkedList&& link) { if (head != 0) Clear(); head = link.head; tail = link.tail; count = link.count; link.head = 0; link.tail = 0; link.count = 0; for (auto node = head; node; node = node->GetNext()) node->list = this; return *this; } LinkedList& operator=(const LinkedList& link) { if (head != 0) Clear(); auto p = link.head; while (p) { AddLast(p->Value); p = p->GetNext(); } return *this; } template void ForEach(const IteratorFunc& f) { auto p = head; while (p) { f(p->Value); p = p->GetNext(); } } LinkedNode* GetNode(int x) { LinkedNode* pCur = head; for (int i = 0; i < x; i++) { if (pCur) pCur = pCur->next; else SLANG_UNEXPECTED("Index out of range"); } return pCur; }; LinkedNode* Find(const T& fData) { for (LinkedNode* pCur = head; pCur; pCur = pCur->next) { if (pCur->Value == fData) return pCur; } return 0; }; LinkedNode* FirstNode() const { return head; }; T& First() const { if (!head) SLANG_UNEXPECTED("LinkedList: index out of range."); return head->Value; } T& Last() const { if (!tail) SLANG_UNEXPECTED("LinkedList: index out of range."); return tail->Value; } LinkedNode* LastNode() const { return tail; }; LinkedNode* AddLast(const T& nData) { LinkedNode* n = new LinkedNode(this); n->Value = nData; n->prev = tail; if (tail) tail->next = n; n->next = 0; tail = n; if (!head) head = n; count++; return n; }; // Insert a blank node LinkedNode* AddLast() { LinkedNode* n = new LinkedNode(this); n->prev = tail; if (tail) tail->next = n; n->next = 0; tail = n; if (!head) head = n; count++; return n; }; LinkedNode* AddFirst(const T& nData) { LinkedNode* n = new LinkedNode(this); n->Value = nData; n->prev = 0; n->next = head; if (head) head->prev = n; head = n; if (!tail) tail = n; count++; return n; }; void Delete(LinkedNode* n, int Count = 1) { LinkedNode*n1, *n2 = 0, *tn; n1 = n->prev; tn = n; int numDeleted = 0; for (int i = 0; i < Count; i++) { n2 = tn->next; delete tn; tn = n2; numDeleted++; if (tn == 0) break; } if (n1) n1->next = n2; else head = n2; if (n2) n2->prev = n1; else tail = n1; count -= numDeleted; } void Clear() { for (LinkedNode* n = head; n;) { LinkedNode* tmp = n->next; delete n; n = tmp; } head = 0; tail = 0; count = 0; } List ToList() const { List rs; rs.Reserve(count); for (auto& item : *this) { rs.Add(item); } return rs; } int Count() { return count; } }; } // namespace Slang #endif