// Copyright (C) 2007 EQ2EMulator Development Team, GPL v3+ #pragma once #include #include "types.hpp" // Safe deletion utility for backwards compatibility template inline void safe_delete(T*& ptr) { delete ptr; ptr = nullptr; } // Direction enumeration for iterator traversal enum direction { FORWARD, BACKWARD }; template class LinkedListIterator; // Individual element in the linked list containing data and navigation pointers template class ListElement { private: TYPE data; // The actual data stored in this element ListElement* next; // Pointer to the next element in the list ListElement* prev; // Pointer to the previous element in the list public: // Default constructor - initializes pointers to null ListElement(); // Constructor with data - creates element with specified data ListElement(const TYPE& d); // Copy constructor - creates element as copy of another ListElement(const ListElement& other); // Destructor - handles cleanup of data and recursive deletion ~ListElement(); // Assignment operator - copies data and pointers from another element ListElement& operator=(const ListElement& other); // Traverses to the last element in the chain starting from this element ListElement* GetLast() { ListElement* tmp = this; while (tmp->GetNext()) { tmp = tmp->GetNext(); } return tmp; } // Returns pointer to the next element ListElement* GetNext() const { return next; } // Returns pointer to the previous element ListElement* GetPrev() const { return prev; } // Returns reference to the data stored in this element inline TYPE& GetData() { return data; } // Returns const reference to the data stored in this element inline const TYPE& GetData() const { return data; } // Sets the data for this element - expected behavior for pointer management void SetData(const TYPE& d) { data = d; } // Sets the next pointer of the last element in the chain void SetLastNext(ListElement* p) { GetLast()->SetNext(p); } // Sets the next element pointer void SetNext(ListElement* n) { next = n; } // Sets the previous element pointer void SetPrev(ListElement* p) { prev = p; } // Replaces the data in this element, properly deleting old data void ReplaceData(const TYPE& new_data); }; // Doubly-linked list container with automatic memory management template class LinkedList { private: int32 count; // Number of elements in the list ListElement* first; // Pointer to the first element bool list_destructor_invoked; // Flag to track destructor state public: bool dont_delete; // Flag to prevent automatic deletion // Default constructor - initializes empty list LinkedList(); // Destructor - cleans up all elements unless dont_delete is set ~LinkedList(); // Assignment operator - copies entire list from another LinkedList& operator=(const LinkedList& other); // Adds element to the end of the list void Append(const TYPE& data); // Inserts element at the beginning of the list void Insert(const TYPE& data); // Removes and returns the first element from the list TYPE Pop(); // Returns the data from the first element without removing it TYPE PeekTop(); // Removes all elements from the list void Clear(); // Decrements the element count void LCount() { count--; } // Resets the element count to zero void ResetCount() { count = 0; } // Returns the current number of elements in the list int32 Count() { return count; } friend class LinkedListIterator; }; // Iterator for traversing and manipulating linked list elements template class LinkedListIterator { private: LinkedList& list; // Reference to the list being iterated ListElement* current_element; // Pointer to current element direction dir; // Direction of iteration public: // Constructor - creates iterator for specified list and direction LinkedListIterator(LinkedList& l, direction d = FORWARD) : list(l), dir(d) {} // Advances the iterator to the next element in the specified direction void Advance(); // Returns reference to the data at the current iterator position const TYPE& GetData(); // Checks if current element is the first in the list bool IsFirst() { if (current_element->GetPrev() == nullptr) return true; else return false; } // Checks if current element is the last in the list bool IsLast() { if (current_element->GetNext() == nullptr) return true; else return false; } // Checks if there are more elements to iterate over bool MoreElements(); // Moves current element to the beginning of the list void MoveFirst(); // Moves current element to the end of the list void MoveLast(); // Removes current element from list with optional data deletion void RemoveCurrent(bool DeleteData = true); // Replaces data in current element with new data void Replace(const TYPE& new_data); // Resets iterator to the beginning or end based on direction void Reset(); // Sets the iteration direction void SetDir(direction d); }; // Implementation of LinkedListIterator methods // Advances iterator to next element, skipping null data during destruction template void LinkedListIterator::Advance() { if (current_element == nullptr) { return; } if (dir == FORWARD) { current_element = current_element->GetNext(); } else { current_element = current_element->GetPrev(); } if (list.list_destructor_invoked) { while (current_element && current_element->GetData() == 0) { if (dir == FORWARD) { current_element = current_element->GetNext(); } else { current_element = current_element->GetPrev(); } } } } // Checks if iterator has more elements to process template bool LinkedListIterator::MoreElements() { if (current_element == nullptr) return false; return true; } // Returns reference to data at current iterator position template const TYPE& LinkedListIterator::GetData() { return current_element->GetData(); } // Moves current element to the front of the list template void LinkedListIterator::MoveFirst() { ListElement* prev = current_element->GetPrev(); ListElement* next = current_element->GetNext(); if (prev == nullptr) { return; } prev->SetNext(next); if (next != nullptr) { next->SetPrev(prev); } current_element->SetPrev(nullptr); current_element->SetNext(list.first); list.first->SetPrev(current_element); list.first = current_element; } // Moves current element to the end of the list template void LinkedListIterator::MoveLast() { ListElement* prev = current_element->GetPrev(); ListElement* next = current_element->GetNext(); if (next == nullptr) { return; } if (prev != nullptr) { prev->SetNext(next); } else { list.first = next; } next->SetPrev(prev); current_element->SetNext(nullptr); current_element->SetPrev(next->GetLast()); next->GetLast()->SetNext(current_element); } // Removes current element from list and optionally deletes its data template void LinkedListIterator::RemoveCurrent(bool DeleteData) { ListElement* save; if (list.first == current_element) { list.first = current_element->GetNext(); } if (current_element->GetPrev() != nullptr) { current_element->GetPrev()->SetNext(current_element->GetNext()); } if (current_element->GetNext() != nullptr) { current_element->GetNext()->SetPrev(current_element->GetPrev()); } if (dir == FORWARD) { save = current_element->GetNext(); } else { save = current_element->GetPrev(); } current_element->SetNext(nullptr); current_element->SetPrev(nullptr); if (!DeleteData) current_element->SetData(0); safe_delete(current_element); current_element = save; list.LCount(); } // Replaces data in current element with new data template void LinkedListIterator::Replace(const TYPE& new_data) { current_element->ReplaceData(new_data); } // Resets iterator to start position based on direction template void LinkedListIterator::Reset() { if (!(&list)) { current_element = nullptr; return; } if (dir == FORWARD) { current_element = list.first; } else { if (list.first == nullptr) { current_element = nullptr; } else { current_element = list.first->GetLast(); } } if (list.list_destructor_invoked) { while (current_element && current_element->GetData() == 0) { if (dir == FORWARD) { current_element = current_element->GetNext(); } else { current_element = current_element->GetPrev(); } } } } // Sets the iteration direction for this iterator template void LinkedListIterator::SetDir(direction d) { dir = d; } // Implementation of ListElement methods // Default constructor initializes all members to safe defaults template ListElement::ListElement() { data = 0; next = nullptr; prev = nullptr; } // Constructor with data initializes element with provided data template ListElement::ListElement(const TYPE& d) { data = d; next = nullptr; prev = nullptr; } // Copy constructor creates identical copy of another element template ListElement::ListElement(const ListElement& other) { data = other.data; next = nullptr; prev = nullptr; } // Destructor handles cleanup of data and recursive deletion of chain template ListElement::~ListElement() { if (data != 0) safe_delete(data); data = 0; if (next != nullptr) { safe_delete(next); next = nullptr; } } // Assignment operator copies data and pointers from another element template ListElement& ListElement::operator=(const ListElement& other) { if (this != &other) { data = other.data; next = other.next; prev = other.prev; } return *this; } // Replaces current data with new data, properly cleaning up old data template void ListElement::ReplaceData(const TYPE& new_data) { if (data != 0) safe_delete(data); data = new_data; } // Implementation of LinkedList methods // Default constructor initializes empty list template LinkedList::LinkedList() { list_destructor_invoked = false; first = nullptr; count = 0; dont_delete = false; } // Destructor cleans up all elements unless dont_delete flag is set template LinkedList::~LinkedList() { list_destructor_invoked = true; if (!dont_delete) Clear(); } // Assignment operator creates deep copy of another list template LinkedList& LinkedList::operator=(const LinkedList& other) { if (this != &other) { Clear(); // Deep copy implementation would go here if needed } return *this; } // Removes all elements from the list and resets count template void LinkedList::Clear() { while (first) { ListElement* tmp = first; first = tmp->GetNext(); tmp->SetNext(nullptr); safe_delete(tmp); } ResetCount(); } // Adds new element to the end of the list template void LinkedList::Append(const TYPE& data) { ListElement* new_element = new ListElement(data); if (first == nullptr) { first = new_element; } else { new_element->SetPrev(first->GetLast()); first->SetLastNext(new_element); } count++; } // Inserts new element at the beginning of the list template void LinkedList::Insert(const TYPE& data) { ListElement* new_element = new ListElement(data); new_element->SetNext(first); if (first != nullptr) { first->SetPrev(new_element); } first = new_element; count++; } // Removes and returns first element from the list template TYPE LinkedList::Pop() { TYPE ret = 0; if (first) { ListElement* tmpdel = first; first = tmpdel->GetNext(); if (first) first->SetPrev(nullptr); ret = tmpdel->GetData(); tmpdel->SetData(0); tmpdel->SetNext(nullptr); safe_delete(tmpdel); count--; } return ret; } // Returns data from first element without removing it template TYPE LinkedList::PeekTop() { if (first) return first->GetData(); return 0; }