123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- // Copyright (C) 2002-2012 Nikolaus Gebhardt
- // This file is part of the "Irrlicht Engine".
- // For conditions of distribution and use, see copyright notice in irrlicht.h
- #ifndef __IRR_LIST_H_INCLUDED__
- #define __IRR_LIST_H_INCLUDED__
- #include "irrTypes.h"
- #include "irrAllocator.h"
- #include "irrMath.h"
- namespace irr
- {
- namespace core
- {
- //! Doubly linked list template.
- template <class T>
- class list
- {
- private:
- //! List element node with pointer to previous and next element in the list.
- struct SKListNode
- {
- SKListNode(const T& e) : Next(0), Prev(0), Element(e) {}
- SKListNode* Next;
- SKListNode* Prev;
- T Element;
- };
- public:
- class ConstIterator;
- //! List iterator.
- class Iterator
- {
- public:
- Iterator() : Current(0) {}
- Iterator& operator ++() { Current = Current->Next; return *this; }
- Iterator& operator --() { Current = Current->Prev; return *this; }
- Iterator operator ++(s32) { Iterator tmp = *this; Current = Current->Next; return tmp; }
- Iterator operator --(s32) { Iterator tmp = *this; Current = Current->Prev; return tmp; }
- Iterator& operator +=(s32 num)
- {
- if(num > 0)
- {
- while (num-- && this->Current != 0) ++(*this);
- }
- else
- {
- while(num++ && this->Current != 0) --(*this);
- }
- return *this;
- }
- Iterator operator + (s32 num) const { Iterator tmp = *this; return tmp += num; }
- Iterator& operator -=(s32 num) { return (*this)+=(-num); }
- Iterator operator - (s32 num) const { return (*this)+ (-num); }
- bool operator ==(const Iterator& other) const { return Current == other.Current; }
- bool operator !=(const Iterator& other) const { return Current != other.Current; }
- bool operator ==(const ConstIterator& other) const { return Current == other.Current; }
- bool operator !=(const ConstIterator& other) const { return Current != other.Current; }
- T & operator * () { return Current->Element; }
- T * operator ->() { return &Current->Element; }
- private:
- explicit Iterator(SKListNode* begin) : Current(begin) {}
- SKListNode* Current;
- friend class list<T>;
- friend class ConstIterator;
- };
- //! List iterator for const access.
- class ConstIterator
- {
- public:
- ConstIterator() : Current(0) {}
- ConstIterator(const Iterator& iter) : Current(iter.Current) {}
- ConstIterator& operator ++() { Current = Current->Next; return *this; }
- ConstIterator& operator --() { Current = Current->Prev; return *this; }
- ConstIterator operator ++(s32) { ConstIterator tmp = *this; Current = Current->Next; return tmp; }
- ConstIterator operator --(s32) { ConstIterator tmp = *this; Current = Current->Prev; return tmp; }
- ConstIterator& operator +=(s32 num)
- {
- if(num > 0)
- {
- while(num-- && this->Current != 0) ++(*this);
- }
- else
- {
- while(num++ && this->Current != 0) --(*this);
- }
- return *this;
- }
- ConstIterator operator + (s32 num) const { ConstIterator tmp = *this; return tmp += num; }
- ConstIterator& operator -=(s32 num) { return (*this)+=(-num); }
- ConstIterator operator - (s32 num) const { return (*this)+ (-num); }
- bool operator ==(const ConstIterator& other) const { return Current == other.Current; }
- bool operator !=(const ConstIterator& other) const { return Current != other.Current; }
- bool operator ==(const Iterator& other) const { return Current == other.Current; }
- bool operator !=(const Iterator& other) const { return Current != other.Current; }
- const T & operator * () { return Current->Element; }
- const T * operator ->() { return &Current->Element; }
- ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; }
- private:
- explicit ConstIterator(SKListNode* begin) : Current(begin) {}
- SKListNode* Current;
- friend class Iterator;
- friend class list<T>;
- };
- //! Default constructor for empty list.
- list()
- : First(0), Last(0), Size(0) {}
- //! Copy constructor.
- list(const list<T>& other) : First(0), Last(0), Size(0)
- {
- *this = other;
- }
- //! Destructor
- ~list()
- {
- clear();
- }
- //! Assignment operator
- void operator=(const list<T>& other)
- {
- if(&other == this)
- {
- return;
- }
- clear();
- SKListNode* node = other.First;
- while(node)
- {
- push_back(node->Element);
- node = node->Next;
- }
- }
- //! Returns amount of elements in list.
- /** \return Amount of elements in the list. */
- u32 size() const
- {
- return Size;
- }
- u32 getSize() const
- {
- return Size;
- }
- //! Clears the list, deletes all elements in the list.
- /** All existing iterators of this list will be invalid. */
- void clear()
- {
- while(First)
- {
- SKListNode * next = First->Next;
- allocator.destruct(First);
- allocator.deallocate(First);
- First = next;
- }
- //First = 0; handled by loop
- Last = 0;
- Size = 0;
- }
- //! Checks for empty list.
- /** \return True if the list is empty and false if not. */
- bool empty() const
- {
- return (First == 0);
- }
- //! Adds an element at the end of the list.
- /** \param element Element to add to the list. */
- void push_back(const T& element)
- {
- SKListNode* node = allocator.allocate(1);
- allocator.construct(node, element);
- ++Size;
- if (First == 0)
- First = node;
- node->Prev = Last;
- if (Last != 0)
- Last->Next = node;
- Last = node;
- }
- //! Adds an element at the begin of the list.
- /** \param element: Element to add to the list. */
- void push_front(const T& element)
- {
- SKListNode* node = allocator.allocate(1);
- allocator.construct(node, element);
- ++Size;
- if (First == 0)
- {
- Last = node;
- First = node;
- }
- else
- {
- node->Next = First;
- First->Prev = node;
- First = node;
- }
- }
- //! Gets first node.
- /** \return A list iterator pointing to the beginning of the list. */
- Iterator begin()
- {
- return Iterator(First);
- }
- //! Gets first node.
- /** \return A const list iterator pointing to the beginning of the list. */
- ConstIterator begin() const
- {
- return ConstIterator(First);
- }
- //! Gets end node.
- /** \return List iterator pointing to null. */
- Iterator end()
- {
- return Iterator(0);
- }
- //! Gets end node.
- /** \return Const list iterator pointing to null. */
- ConstIterator end() const
- {
- return ConstIterator(0);
- }
- //! Gets last element.
- /** \return List iterator pointing to the last element of the list. */
- Iterator getLast()
- {
- return Iterator(Last);
- }
- //! Gets last element.
- /** \return Const list iterator pointing to the last element of the list. */
- ConstIterator getLast() const
- {
- return ConstIterator(Last);
- }
- //! Inserts an element after an element.
- /** \param it Iterator pointing to element after which the new element
- should be inserted.
- \param element The new element to be inserted into the list.
- */
- void insert_after(const Iterator& it, const T& element)
- {
- SKListNode* node = allocator.allocate(1);
- allocator.construct(node, element);
- node->Next = it.Current->Next;
- if (it.Current->Next)
- it.Current->Next->Prev = node;
- node->Prev = it.Current;
- it.Current->Next = node;
- ++Size;
- if (it.Current == Last)
- Last = node;
- }
- //! Inserts an element before an element.
- /** \param it Iterator pointing to element before which the new element
- should be inserted.
- \param element The new element to be inserted into the list.
- */
- void insert_before(const Iterator& it, const T& element)
- {
- SKListNode* node = allocator.allocate(1);
- allocator.construct(node, element);
- node->Prev = it.Current->Prev;
- if (it.Current->Prev)
- it.Current->Prev->Next = node;
- node->Next = it.Current;
- it.Current->Prev = node;
- ++Size;
- if (it.Current == First)
- First = node;
- }
- //! Erases an element.
- /** \param it Iterator pointing to the element which shall be erased.
- \return Iterator pointing to next element. */
- Iterator erase(Iterator& it)
- {
- // suggest changing this to a const Iterator& and
- // working around line: it.Current = 0 (possibly with a mutable, or just let it be garbage?)
- Iterator returnIterator(it);
- ++returnIterator;
- if(it.Current == First)
- {
- First = it.Current->Next;
- }
- else
- {
- it.Current->Prev->Next = it.Current->Next;
- }
- if(it.Current == Last)
- {
- Last = it.Current->Prev;
- }
- else
- {
- it.Current->Next->Prev = it.Current->Prev;
- }
- allocator.destruct(it.Current);
- allocator.deallocate(it.Current);
- it.Current = 0;
- --Size;
- return returnIterator;
- }
- //! Swap the content of this list container with the content of another list
- /** Afterward this object will contain the content of the other object and the other
- object will contain the content of this object. Iterators will afterward be valid for
- the swapped object.
- \param other Swap content with this object */
- void swap(list<T>& other)
- {
- core::swap(First, other.First);
- core::swap(Last, other.Last);
- core::swap(Size, other.Size);
- core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation
- }
- typedef T value_type;
- typedef u32 size_type;
- private:
- SKListNode* First;
- SKListNode* Last;
- u32 Size;
- irrAllocator<SKListNode> allocator;
- };
- } // end namespace core
- }// end namespace irr
- #endif
|