00001 /**************************************************************************************** 00002 00003 Copyright (C) 2012 Autodesk, Inc. 00004 All rights reserved. 00005 00006 Use of this software is subject to the terms of the Autodesk license agreement 00007 provided at the time of installation or download, or which otherwise accompanies 00008 this software in either electronic or hard copy form. 00009 00010 ****************************************************************************************/ 00011 00013 #ifndef _FBXSDK_CORE_BASE_INTRUSIVE_LIST_H_ 00014 #define _FBXSDK_CORE_BASE_INTRUSIVE_LIST_H_ 00015 00016 #include <fbxsdk/fbxsdk_def.h> 00017 00018 #include <fbxsdk/fbxsdk_nsbegin.h> 00019 00020 #ifndef DOXYGEN_SHOULD_SKIP_THIS 00021 00022 #define FBXSDK_INTRUSIVE_LIST_NODE(classT, NodeCount)\ 00023 public: inline FbxListNode<classT>& GetListNode(int index = 0){ return this->mNode[index]; }\ 00024 private: FbxListNode<classT> mNode[NodeCount]; 00025 00026 //----------------------------------------------------------------- 00027 template <typename T> class FbxListNode 00028 { 00029 typedef FbxListNode<T> NodeT; 00030 00031 public: 00032 explicit FbxListNode(T* pData = 0):mNext(0),mPrev(0),mData(pData){} 00033 ~FbxListNode() 00034 { 00035 Disconnect(); 00036 } 00037 00038 void Disconnect() 00039 { 00040 if ( mPrev != 0 ) 00041 mPrev->mNext = mNext; 00042 00043 if ( mNext != 0 ) 00044 mNext->mPrev = mPrev; 00045 00046 mPrev = mNext = 0; 00047 } 00048 00049 NodeT* mNext; 00050 NodeT* mPrev; 00051 00052 T* mData; 00053 }; 00054 00055 //----------------------------------------------------------------- 00056 // template arg T: Type listed 00057 // arg NodeIndex: If an object listed has multiple list node, which 00058 // index corresponds to the right node 00059 template <typename T, int NodeIndex=0> 00060 class FbxIntrusiveList 00061 { 00062 public: 00063 typedef T allocator_type; 00064 typedef T value_type; 00065 typedef T& reference; 00066 typedef const T& const_reference; 00067 typedef T* pointer; 00068 typedef const T* const_pointer; 00069 00070 typedef FbxListNode<T> NodeT; 00071 00072 // Construction / Destruction 00073 FbxIntrusiveList():mHead(0) 00074 { 00075 mHead.mNext = mHead.mPrev = &mHead; 00076 } 00077 ~FbxIntrusiveList() 00078 { 00079 while(!Empty()) 00080 Begin().Get()->Disconnect(); // LINUXNote: should be Erase(Begin()); but there's an issue with gcc 4.2 00081 }; 00082 00083 // true if the list's size is 0. 00084 bool Empty() const 00085 { 00086 return ((mHead.mNext==&mHead)&&(mHead.mPrev==&mHead)); 00087 } 00088 00089 // Back Insertion Sequence Inserts a new element at the end. 00090 void PushBack(T& pElement) 00091 { 00092 NodeT* pNode = &pElement.GetListNode(NodeIndex); 00093 pNode->mData = &pElement; 00094 00095 if (Empty()) 00096 { 00097 pNode->mNext = &mHead; 00098 pNode->mPrev = &mHead; 00099 mHead.mNext = pNode; 00100 mHead.mPrev = pNode; 00101 } 00102 else 00103 { 00104 pNode->mNext = &mHead; 00105 pNode->mPrev = mHead.mPrev; 00106 00107 pNode->mPrev->mNext = pNode; 00108 mHead.mPrev = pNode; 00109 } 00110 } 00111 00112 void PushFront(T& pElement) 00113 { 00114 NodeT* pNode = &pElement.GetListNode(NodeIndex); 00115 pNode->mData = &pElement; 00116 00117 if (Empty()) 00118 { 00119 pNode->mNext = &mHead; 00120 pNode->mPrev = &mHead; 00121 mHead.mNext = pNode; 00122 mHead.mPrev = pNode; 00123 } 00124 else 00125 { 00126 pNode->mNext = mHead.mNext; 00127 pNode->mPrev = &mHead; 00128 00129 pNode->mNext->mPrev = pNode; 00130 mHead.mNext = pNode; 00131 } 00132 } 00133 00134 void PopFront() 00135 { 00136 iterator begin = Begin(); 00137 Erase(begin); 00138 } 00139 00140 void PopBack() 00141 { 00142 Erase(--(End())); 00143 } 00144 00145 public: 00146 class IntrusiveListIterator 00147 { 00148 public: 00149 explicit IntrusiveListIterator(NodeT* ptr=0):mPtr(ptr){} 00150 00151 // pre-increment 00152 IntrusiveListIterator& operator++() 00153 { 00154 mPtr = mPtr->mNext;return (*this); 00155 } 00156 // post-increment 00157 const IntrusiveListIterator operator++(int) 00158 { 00159 IntrusiveListIterator temp = *this; 00160 ++*this; 00161 return (temp); 00162 } 00163 // pre-decrement 00164 IntrusiveListIterator& operator--() 00165 { 00166 mPtr = mPtr->mPrev;return *this; 00167 } 00168 // post-decrement 00169 const IntrusiveListIterator operator--(int) 00170 { 00171 IntrusiveListIterator temp = *this; 00172 --*this; 00173 return (temp); 00174 } 00175 IntrusiveListIterator& operator=(const IntrusiveListIterator &other){mPtr = other.mPtr; return *this;} 00176 00177 reference operator*() const { return *(mPtr->mData); } 00178 pointer operator->() const { return (&**this); } 00179 bool operator==(const IntrusiveListIterator& other)const{ return mPtr==other.mPtr; } 00180 bool operator!=(const IntrusiveListIterator& other)const{ return !(*this == other); } 00181 00182 inline NodeT* Get()const { return mPtr; } 00183 00184 private: 00185 NodeT* mPtr; 00186 }; 00187 00188 class IntrusiveListConstIterator 00189 { 00190 public: 00191 explicit IntrusiveListConstIterator(const NodeT* ptr=0):mPtr(ptr){} 00192 00193 // pre-increment 00194 IntrusiveListConstIterator& operator++() 00195 { 00196 mPtr = mPtr->mNext;return (*this); 00197 } 00198 // post-increment 00199 const IntrusiveListConstIterator operator++(int) 00200 { 00201 IntrusiveListConstIterator temp = *this; 00202 ++*this; 00203 return (temp); 00204 } 00205 // pre-decrement 00206 IntrusiveListConstIterator& operator--() 00207 { 00208 mPtr = mPtr->mPrev;return *this; 00209 } 00210 // post-decrement 00211 const IntrusiveListConstIterator operator--(int) 00212 { 00213 IntrusiveListConstIterator temp = *this; 00214 --*this; 00215 return (temp); 00216 } 00217 IntrusiveListConstIterator& operator=(const IntrusiveListConstIterator &other){mPtr = other.mPtr; return *this;} 00218 00219 const_reference operator*() const { return *(mPtr->mData); } 00220 const_pointer operator->() const { return (&**this); } 00221 bool operator==(const IntrusiveListConstIterator& other)const{ return mPtr==other.mPtr; } 00222 bool operator!=(const IntrusiveListConstIterator& other)const{ return !(*this == other); } 00223 00224 inline const NodeT* Get()const { return mPtr; } 00225 00226 private: 00227 mutable const NodeT* mPtr; 00228 }; 00229 00230 // --- Iterator definitions --- 00231 typedef IntrusiveListIterator iterator; 00232 typedef IntrusiveListConstIterator const_iterator; 00233 00234 // iterator support 00235 inline iterator Begin() { return iterator(mHead.mNext); } 00236 inline const_iterator Begin() const { return const_iterator(mHead.mNext); } 00237 inline iterator End() { return iterator(&mHead); } 00238 inline const_iterator End() const { return const_iterator(&mHead); } 00239 00240 // Because there is no real use, for the reverse iterators, 00241 // they have not been implemented. 00242 00243 reference Front(){return (*Begin());} 00244 const_reference Front() const { return (*Begin()); } 00245 reference Back(){ return (*(--End())); } 00246 const_reference Back() const{ return (*(--End())); } 00247 00248 iterator& Erase(iterator& it) 00249 { 00250 it.Get()->Disconnect(); 00251 return (++it); 00252 } 00253 private: 00254 NodeT mHead; 00255 00256 // Not copyable 00257 FbxIntrusiveList(const FbxIntrusiveList&); 00258 FbxIntrusiveList& operator=(const FbxIntrusiveList& Right){return (*this);} 00259 }; 00260 00261 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 00262 00263 #include <fbxsdk/fbxsdk_nsend.h> 00264 00265 #endif /* _FBXSDK_CORE_BASE_INTRUSIVE_LIST_H_ */