LCOV - code coverage report
Current view: top level - usr/include/irrlicht - irrList.h (source / functions) Hit Total Coverage
Test: report Lines: 73 87 83.9 %
Date: 2015-07-11 18:23:49 Functions: 43 51 84.3 %

          Line data    Source code
       1             : // Copyright (C) 2002-2012 Nikolaus Gebhardt
       2             : // This file is part of the "Irrlicht Engine".
       3             : // For conditions of distribution and use, see copyright notice in irrlicht.h
       4             : 
       5             : #ifndef __IRR_LIST_H_INCLUDED__
       6             : #define __IRR_LIST_H_INCLUDED__
       7             : 
       8             : #include "irrTypes.h"
       9             : #include "irrAllocator.h"
      10             : #include "irrMath.h"
      11             : 
      12             : namespace irr
      13             : {
      14             : namespace core
      15             : {
      16             : 
      17             : 
      18             : //! Doubly linked list template.
      19             : template <class T>
      20             : class list
      21             : {
      22             : private:
      23             : 
      24             :         //! List element node with pointer to previous and next element in the list.
      25             :         struct SKListNode
      26             :         {
      27         861 :                 SKListNode(const T& e) : Next(0), Prev(0), Element(e) {}
      28             : 
      29             :                 SKListNode* Next;
      30             :                 SKListNode* Prev;
      31             :                 T Element;
      32             :         };
      33             : 
      34             : public:
      35             :         class ConstIterator;
      36             : 
      37             :         //! List iterator.
      38             :         class Iterator
      39             :         {
      40             :         public:
      41             :                 Iterator() : Current(0) {}
      42             : 
      43      254346 :                 Iterator& operator ++()    { Current = Current->Next; return *this; }
      44       23122 :                 Iterator& operator --()    { Current = Current->Prev; return *this; }
      45           0 :                 Iterator  operator ++(s32) { Iterator tmp = *this; Current = Current->Next; return tmp; }
      46             :                 Iterator  operator --(s32) { Iterator tmp = *this; Current = Current->Prev; return tmp; }
      47             : 
      48             :                 Iterator& operator +=(s32 num)
      49             :                 {
      50             :                         if(num > 0)
      51             :                         {
      52             :                                 while (num-- && this->Current != 0) ++(*this);
      53             :                         }
      54             :                         else
      55             :                         {
      56             :                                 while(num++ && this->Current != 0) --(*this);
      57             :                         }
      58             :                         return *this;
      59             :                 }
      60             : 
      61             :                 Iterator  operator + (s32 num) const { Iterator tmp = *this; return tmp += num; }
      62             :                 Iterator& operator -=(s32 num) { return (*this)+=(-num); }
      63             :                 Iterator  operator - (s32 num) const { return (*this)+ (-num); }
      64             : 
      65             :                 bool operator ==(const Iterator&      other) const { return Current == other.Current; }
      66      562473 :                 bool operator !=(const Iterator&      other) const { return Current != other.Current; }
      67             :                 bool operator ==(const ConstIterator& other) const { return Current == other.Current; }
      68             :                 bool operator !=(const ConstIterator& other) const { return Current != other.Current; }
      69             : 
      70             :                 #if defined (_MSC_VER) && (_MSC_VER < 1300)
      71             :                         #pragma warning(disable:4284) // infix notation problem when using iterator operator ->
      72             :                 #endif
      73             : 
      74      282306 :                 T & operator * () { return Current->Element; }
      75             :                 T * operator ->() { return &Current->Element; }
      76             : 
      77             :         private:
      78      856848 :                 explicit Iterator(SKListNode* begin) : Current(begin) {}
      79             : 
      80             :                 SKListNode* Current;
      81             : 
      82             :                 friend class list<T>;
      83             :                 friend class ConstIterator;
      84             :         };
      85             : 
      86             :         //! List iterator for const access.
      87             :         class ConstIterator
      88             :         {
      89             :         public:
      90             : 
      91             :                 ConstIterator() : Current(0) {}
      92             :                 ConstIterator(const Iterator& iter) : Current(iter.Current)  {}
      93             : 
      94         238 :                 ConstIterator& operator ++()    { Current = Current->Next; return *this; }
      95             :                 ConstIterator& operator --()    { Current = Current->Prev; return *this; }
      96           0 :                 ConstIterator  operator ++(s32) { ConstIterator tmp = *this; Current = Current->Next; return tmp; }
      97             :                 ConstIterator  operator --(s32) { ConstIterator tmp = *this; Current = Current->Prev; return tmp; }
      98             : 
      99             :                 ConstIterator& operator +=(s32 num)
     100             :                 {
     101             :                         if(num > 0)
     102             :                         {
     103             :                                 while(num-- && this->Current != 0) ++(*this);
     104             :                         }
     105             :                         else
     106             :                         {
     107             :                                 while(num++ && this->Current != 0) --(*this);
     108             :                         }
     109             :                         return *this;
     110             :                 }
     111             : 
     112             :                 ConstIterator  operator + (s32 num) const { ConstIterator tmp = *this; return tmp += num; }
     113             :                 ConstIterator& operator -=(s32 num) { return (*this)+=(-num); }
     114             :                 ConstIterator  operator - (s32 num) const { return (*this)+ (-num); }
     115             : 
     116             :                 bool operator ==(const ConstIterator& other) const { return Current == other.Current; }
     117         358 :                 bool operator !=(const ConstIterator& other) const { return Current != other.Current; }
     118             :                 bool operator ==(const Iterator&      other) const { return Current == other.Current; }
     119             :                 bool operator !=(const Iterator&      other) const { return Current != other.Current; }
     120             : 
     121         690 :                 const T & operator * () { return Current->Element; }
     122             :                 const T * operator ->() { return &Current->Element; }
     123             : 
     124             :                 ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; }
     125             : 
     126             :         private:
     127         510 :                 explicit ConstIterator(SKListNode* begin) : Current(begin) {}
     128             : 
     129             :                 SKListNode* Current;
     130             : 
     131             :                 friend class Iterator;
     132             :                 friend class list<T>;
     133             :         };
     134             : 
     135             :         //! Default constructor for empty list.
     136         523 :         list()
     137         523 :                 : First(0), Last(0), Size(0) {}
     138             : 
     139             : 
     140             :         //! Copy constructor.
     141           3 :         list(const list<T>& other) : First(0), Last(0), Size(0)
     142             :         {
     143           3 :                 *this = other;
     144           3 :         }
     145             : 
     146             : 
     147             :         //! Destructor
     148         529 :         ~list()
     149             :         {
     150         529 :                 clear();
     151         529 :         }
     152             : 
     153             : 
     154             :         //! Assignment operator
     155           3 :         void operator=(const list<T>& other)
     156             :         {
     157           3 :                 if(&other == this)
     158             :                 {
     159           0 :                         return;
     160             :                 }
     161             : 
     162           3 :                 clear();
     163             : 
     164           3 :                 SKListNode* node = other.First;
     165          27 :                 while(node)
     166             :                 {
     167          12 :                         push_back(node->Element);
     168          12 :                         node = node->Next;
     169             :                 }
     170             :         }
     171             : 
     172             : 
     173             :         //! Returns amount of elements in list.
     174             :         /** \return Amount of elements in the list. */
     175             :         u32 size() const
     176             :         {
     177             :                 return Size;
     178             :         }
     179             :         u32 getSize() const
     180             :         {
     181             :                 return Size;
     182             :         }
     183             : 
     184             : 
     185             :         //! Clears the list, deletes all elements in the list.
     186             :         /** All existing iterators of this list will be invalid. */
     187         837 :         void clear()
     188             :         {
     189         878 :                 while(First)
     190             :                 {
     191          41 :                         SKListNode * next = First->Next;
     192          41 :                         allocator.destruct(First);
     193          41 :                         allocator.deallocate(First);
     194          41 :                         First = next;
     195             :                 }
     196             : 
     197             :                 //First = 0; handled by loop
     198         796 :                 Last = 0;
     199         796 :                 Size = 0;
     200         796 :         }
     201             : 
     202             : 
     203             :         //! Checks for empty list.
     204             :         /** \return True if the list is empty and false if not. */
     205          41 :         bool empty() const
     206             :         {
     207          41 :                 return (First == 0);
     208             :         }
     209             : 
     210             : 
     211             :         //! Adds an element at the end of the list.
     212             :         /** \param element Element to add to the list. */
     213         861 :         void push_back(const T& element)
     214             :         {
     215         861 :                 SKListNode* node = allocator.allocate(1);
     216         861 :                 allocator.construct(node, element);
     217             : 
     218         861 :                 ++Size;
     219             : 
     220         861 :                 if (First == 0)
     221         179 :                         First = node;
     222             : 
     223         861 :                 node->Prev = Last;
     224             : 
     225         861 :                 if (Last != 0)
     226         682 :                         Last->Next = node;
     227             : 
     228         861 :                 Last = node;
     229         861 :         }
     230             : 
     231             : 
     232             :         //! Adds an element at the begin of the list.
     233             :         /** \param element: Element to add to the list. */
     234           0 :         void push_front(const T& element)
     235             :         {
     236           0 :                 SKListNode* node = allocator.allocate(1);
     237           0 :                 allocator.construct(node, element);
     238             : 
     239           0 :                 ++Size;
     240             : 
     241           0 :                 if (First == 0)
     242             :                 {
     243           0 :                         Last = node;
     244           0 :                         First = node;
     245             :                 }
     246             :                 else
     247             :                 {
     248           0 :                         node->Next = First;
     249           0 :                         First->Prev = node;
     250           0 :                         First = node;
     251             :                 }
     252           0 :         }
     253             : 
     254             : 
     255             :         //! Gets first node.
     256             :         /** \return A list iterator pointing to the beginning of the list. */
     257      264757 :         Iterator begin()
     258             :         {
     259      264757 :                 return Iterator(First);
     260             :         }
     261             : 
     262             : 
     263             :         //! Gets first node.
     264             :         /** \return A const list iterator pointing to the beginning of the list. */
     265         120 :         ConstIterator begin() const
     266             :         {
     267         120 :                 return ConstIterator(First);
     268             :         }
     269             : 
     270             : 
     271             :         //! Gets end node.
     272             :         /** \return List iterator pointing to null. */
     273      562473 :         Iterator end()
     274             :         {
     275      562473 :                 return Iterator(0);
     276             :         }
     277             : 
     278             : 
     279             :         //! Gets end node.
     280             :         /** \return Const list iterator pointing to null. */
     281         358 :         ConstIterator end() const
     282             :         {
     283         358 :                 return ConstIterator(0);
     284             :         }
     285             : 
     286             : 
     287             :         //! Gets last element.
     288             :         /** \return List iterator pointing to the last element of the list. */
     289       29618 :         Iterator getLast()
     290             :         {
     291       29618 :                 return Iterator(Last);
     292             :         }
     293             : 
     294             : 
     295             :         //! Gets last element.
     296             :         /** \return Const list iterator pointing to the last element of the list. */
     297          32 :         ConstIterator getLast() const
     298             :         {
     299          32 :                 return ConstIterator(Last);
     300             :         }
     301             : 
     302             : 
     303             :         //! Inserts an element after an element.
     304             :         /** \param it Iterator pointing to element after which the new element
     305             :         should be inserted.
     306             :         \param element The new element to be inserted into the list.
     307             :         */
     308             :         void insert_after(const Iterator& it, const T& element)
     309             :         {
     310             :                 SKListNode* node = allocator.allocate(1);
     311             :                 allocator.construct(node, element);
     312             : 
     313             :                 node->Next = it.Current->Next;
     314             : 
     315             :                 if (it.Current->Next)
     316             :                         it.Current->Next->Prev = node;
     317             : 
     318             :                 node->Prev = it.Current;
     319             :                 it.Current->Next = node;
     320             :                 ++Size;
     321             : 
     322             :                 if (it.Current == Last)
     323             :                         Last = node;
     324             :         }
     325             : 
     326             : 
     327             :         //! Inserts an element before an element.
     328             :         /** \param it Iterator pointing to element before which the new element
     329             :         should be inserted.
     330             :         \param element The new element to be inserted into the list.
     331             :         */
     332             :         void insert_before(const Iterator& it, const T& element)
     333             :         {
     334             :                 SKListNode* node = allocator.allocate(1);
     335             :                 allocator.construct(node, element);
     336             : 
     337             :                 node->Prev = it.Current->Prev;
     338             : 
     339             :                 if (it.Current->Prev)
     340             :                         it.Current->Prev->Next = node;
     341             : 
     342             :                 node->Next = it.Current;
     343             :                 it.Current->Prev = node;
     344             :                 ++Size;
     345             : 
     346             :                 if (it.Current == First)
     347             :                         First = node;
     348             :         }
     349             : 
     350             : 
     351             :         //! Erases an element.
     352             :         /** \param it Iterator pointing to the element which shall be erased.
     353             :         \return Iterator pointing to next element. */
     354         673 :         Iterator erase(Iterator& it)
     355             :         {
     356             :                 // suggest changing this to a const Iterator& and
     357             :                 // working around line: it.Current = 0 (possibly with a mutable, or just let it be garbage?)
     358             : 
     359         673 :                 Iterator returnIterator(it);
     360         673 :                 ++returnIterator;
     361             : 
     362         673 :                 if(it.Current == First)
     363             :                 {
     364          22 :                         First = it.Current->Next;
     365             :                 }
     366             :                 else
     367             :                 {
     368         651 :                         it.Current->Prev->Next = it.Current->Next;
     369             :                 }
     370             : 
     371         673 :                 if(it.Current == Last)
     372             :                 {
     373         283 :                         Last = it.Current->Prev;
     374             :                 }
     375             :                 else
     376             :                 {
     377         390 :                         it.Current->Next->Prev = it.Current->Prev;
     378             :                 }
     379             : 
     380         673 :                 allocator.destruct(it.Current);
     381         673 :                 allocator.deallocate(it.Current);
     382         673 :                 it.Current = 0;
     383         673 :                 --Size;
     384             : 
     385         673 :                 return returnIterator;
     386             :         }
     387             : 
     388             :         //! Swap the content of this list container with the content of another list
     389             :         /** Afterwards this object will contain the content of the other object and the other
     390             :         object will contain the content of this object. Iterators will afterwards be valid for
     391             :         the swapped object.
     392             :         \param other Swap content with this object      */
     393             :         void swap(list<T>& other)
     394             :         {
     395             :                 core::swap(First, other.First);
     396             :                 core::swap(Last, other.Last);
     397             :                 core::swap(Size, other.Size);
     398             :                 core::swap(allocator, other.allocator); // memory is still released by the same allocator used for allocation
     399             :         }
     400             : 
     401             : 
     402             : private:
     403             : 
     404             :         SKListNode* First;
     405             :         SKListNode* Last;
     406             :         u32 Size;
     407             :         irrAllocator<SKListNode> allocator;
     408             : 
     409             : };
     410             : 
     411             : 
     412             : } // end namespace core
     413             : }// end namespace irr
     414             : 
     415             : #endif
     416             : 

Generated by: LCOV version 1.11