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