/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#ifndef TRINITYCORE_LINKED_LIST_H
#define TRINITYCORE_LINKED_LIST_H
#include "Define.h"
#include
//============================================
class LinkedListHead;
class LinkedListElement
{
private:
friend class LinkedListHead;
LinkedListElement* iNext;
LinkedListElement* iPrev;
public:
LinkedListElement() : iNext(nullptr), iPrev(nullptr) { }
bool isInList() const
{
return iNext != nullptr /*unlinked element*/
&& iNext != this /*list head*/;
}
LinkedListElement * next() { return iNext; }
LinkedListElement const* next() const { return iNext; }
LinkedListElement * prev() { return iPrev; }
LinkedListElement const* prev() const { return iPrev; }
void delink()
{
if (iNext)
iNext->iPrev = iPrev;
if (iPrev)
iPrev->iNext = iNext;
iNext = nullptr;
iPrev = nullptr;
}
void insertBefore(LinkedListElement* pElem)
{
pElem->iNext = this;
pElem->iPrev = iPrev;
iPrev->iNext = pElem;
iPrev = pElem;
}
void insertAfter(LinkedListElement* pElem)
{
pElem->iPrev = this;
pElem->iNext = iNext;
iNext->iPrev = pElem;
iNext = pElem;
}
private:
LinkedListElement(LinkedListElement const&) = delete;
LinkedListElement(LinkedListElement&&) = delete;
LinkedListElement& operator=(LinkedListElement const&) = delete;
LinkedListElement& operator=(LinkedListElement&&) = delete;
protected:
~LinkedListElement()
{
delink();
}
};
//============================================
class LinkedListHead
{
private:
LinkedListElement iHeader;
uint32 iSize;
public:
LinkedListHead(): iSize(0)
{
// create empty list
iHeader.iNext = &iHeader;
iHeader.iPrev = &iHeader;
}
bool empty() const { return iHeader.iNext == &iHeader; }
void push_front(LinkedListElement* pElem)
{
iHeader.iNext->insertBefore(pElem);
}
void push_back(LinkedListElement* pElem)
{
iHeader.insertBefore(pElem);
}
void pop_front()
{
front_impl()->delink();
}
void pop_back()
{
back_impl()->delink();
}
uint32 size() const
{
if (!iSize)
{
uint32 result = 0;
for (auto itr = begin_impl(); itr != end_impl(); ++itr)
++result;
return result;
}
else
return iSize;
}
void incSize() { ++iSize; }
void decSize() { --iSize; }
template
class Iterator
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = _Ty;
using difference_type = ptrdiff_t;
using base_pointer = std::conditional_t, LinkedListElement const, LinkedListElement>*;
using pointer = _Ty*;
using reference = _Ty&;
Iterator() : _Ptr(nullptr)
{ // construct with null node pointer
}
explicit Iterator(base_pointer _Pnode) : _Ptr(_Pnode)
{ // construct with node pointer _Pnode
}
reference operator*() const
{ // return designated value
return static_cast(*_Ptr);
}
pointer operator->() const
{ // return pointer to class object
return static_cast(_Ptr);
}
base_pointer node() const
{
return _Ptr;
}
Iterator& operator++()
{ // preincrement
_Ptr = _Ptr->next();
return (*this);
}
Iterator operator++(int)
{ // postincrement
Iterator _Tmp = *this;
++*this;
return (_Tmp);
}
Iterator& operator--()
{ // predecrement
_Ptr = _Ptr->prev();
return (*this);
}
Iterator operator--(int)
{ // postdecrement
Iterator _Tmp = *this;
--*this;
return (_Tmp);
}
bool operator==(Iterator const& _Right) const = default;
// test for iterator equality
protected:
base_pointer _Ptr; // pointer to node
};
protected:
template
T* front_impl() { return static_cast(iHeader.iNext); }
template
T const* front_impl() const { return static_cast(iHeader.iNext); }
template
T* back_impl() { return static_cast(iHeader.iPrev); }
template
T const* back_impl() const { return static_cast(iHeader.iPrev); }
template
Iterator begin_impl() { return Iterator(iHeader.iNext); }
template
Iterator begin_impl() const { return Iterator(iHeader.iNext); }
template
Iterator end_impl() { return Iterator(&iHeader); }
template
Iterator end_impl() const { return Iterator(&iHeader); }
void splice_impl(LinkedListElement* where, LinkedListElement* first, LinkedListElement* last)
{
LinkedListElement* wherePrev = where->iPrev;
LinkedListElement* firstPrev = first->iPrev;
LinkedListElement* lastPrev = last->iPrev;
lastPrev->iNext = where;
where->iPrev = lastPrev;
firstPrev->iNext = last;
last->iPrev = firstPrev;
wherePrev->iNext = first;
first->iPrev = wherePrev;
}
template
void splice_impl(Iterator where, Iterator first, Iterator last)
{
splice_impl(where.node(), first.node(), last.node());
}
private:
LinkedListHead(LinkedListHead const&) = delete;
LinkedListHead(LinkedListHead&&) = delete;
LinkedListHead& operator=(LinkedListHead const&) = delete;
LinkedListHead& operator=(LinkedListHead&&) = delete;
protected:
~LinkedListHead() { }
};
//============================================
#endif