#ifndef SLANG_CORE_LINKED_LIST_H #define SLANG_CORE_LINKED_LIST_H #include "slang-allocator.h" #include "slang-list.h" #include "slang.h" #include 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; }; const LinkedNode* getNext() const { 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 removeAndDelete() { 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: template class GenIterator { public: using Node = std::conditional_t, LinkedNode>; Node *current, *next; void setCurrent(Node* cur) { current = cur; if (current) next = current->getNext(); else next = nullptr; } GenIterator() { current = next = nullptr; } GenIterator(Node* cur) { setCurrent(cur); } std::conditional_t operator*() const { return current->value; } GenIterator& operator++() { setCurrent(next); return *this; } GenIterator operator++(int) { GenIterator rs = *this; setCurrent(next); return rs; } bool operator!=(const GenIterator& iter) const { return current != iter.current; } bool operator==(const GenIterator& iter) const { return current == iter.current; } }; using Iterator = GenIterator; Iterator begin() { return Iterator(head); } Iterator end() { return Iterator(0); } using ConstIterator = GenIterator; ConstIterator begin() const { return ConstIterator(head); } ConstIterator end() const { return ConstIterator(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 != nullptr) 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 nullptr; }; LinkedNode* getFirstNode() const { return head; }; T& getFirst() const { if (!head) SLANG_UNEXPECTED("LinkedList: index out of range."); return head->value; } T& getLast() const { if (!tail) SLANG_UNEXPECTED("LinkedList: index out of range."); return tail->value; } LinkedNode* getLastNode() 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; addFirst(n); count++; return n; }; void addFirst(LinkedNode* n) { n->prev = 0; n->next = head; if (head) head->prev = n; head = n; if (!tail) tail = n; } void removeFromList(LinkedNode* n) { LinkedNode*n1, *n2 = 0; n1 = n->prev; n2 = n->next; if (n1) n1->next = n2; else head = n2; if (n2) n2->prev = n1; else tail = n1; n->prev = nullptr; n->next = nullptr; } void removeAndDelete(LinkedNode* n, int Count = 1) { LinkedNode*cur, *next; cur = n; int numDeleted = 0; for (int i = 0; i < Count; i++) { next = cur->next; removeFromList(cur); delete cur; cur = next; numDeleted++; if (cur == 0) break; } 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 getCount() const { return count; } }; } // namespace Slang #endif