00001 #ifndef FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KINTRUSIVELIST_H 00002 #define FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KINTRUSIVELIST_H 00003 00004 /************************************************************************************** 00005 00006 Copyright (C) 2001 - 2009 Autodesk, Inc. and/or its licensors. 00007 All Rights Reserved. 00008 00009 The coded instructions, statements, computer programs, and/or related material 00010 (collectively the "Data") in these files contain unpublished information 00011 proprietary to Autodesk, Inc. and/or its licensors, which is protected by 00012 Canada and United States of America federal copyright law and by international 00013 treaties. 00014 00015 The Data may not be disclosed or distributed to third parties, in whole or in 00016 part, without the prior written consent of Autodesk, Inc. ("Autodesk"). 00017 00018 THE DATA IS PROVIDED "AS IS" AND WITHOUT WARRANTY. 00019 ALL WARRANTIES ARE EXPRESSLY EXCLUDED AND DISCLAIMED. AUTODESK MAKES NO 00020 WARRANTY OF ANY KIND WITH RESPECT TO THE DATA, EXPRESS, IMPLIED OR ARISING 00021 BY CUSTOM OR TRADE USAGE, AND DISCLAIMS ANY IMPLIED WARRANTIES OF TITLE, 00022 NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR USE. 00023 WITHOUT LIMITING THE FOREGOING, AUTODESK DOES NOT WARRANT THAT THE OPERATION 00024 OF THE DATA WILL BE UNINTERRUPTED OR ERROR FREE. 00025 00026 IN NO EVENT SHALL AUTODESK, ITS AFFILIATES, PARENT COMPANIES, LICENSORS 00027 OR SUPPLIERS ("AUTODESK GROUP") BE LIABLE FOR ANY LOSSES, DAMAGES OR EXPENSES 00028 OF ANY KIND (INCLUDING WITHOUT LIMITATION PUNITIVE OR MULTIPLE DAMAGES OR OTHER 00029 SPECIAL, DIRECT, INDIRECT, EXEMPLARY, INCIDENTAL, LOSS OF PROFITS, REVENUE 00030 OR DATA, COST OF COVER OR CONSEQUENTIAL LOSSES OR DAMAGES OF ANY KIND), 00031 HOWEVER CAUSED, AND REGARDLESS OF THE THEORY OF LIABILITY, WHETHER DERIVED 00032 FROM CONTRACT, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE), OR OTHERWISE, 00033 ARISING OUT OF OR RELATING TO THE DATA OR ITS USE OR ANY OTHER PERFORMANCE, 00034 WHETHER OR NOT AUTODESK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS 00035 OR DAMAGE. 00036 00037 **************************************************************************************/ 00038 00043 00044 #include <fbxfilesdk/fbxfilesdk_def.h> 00045 00046 // FBX namespace begin 00047 #include <fbxfilesdk/fbxfilesdk_nsbegin.h> 00048 00049 #define KFBX_LISTNODE(classT, NodeCount)\ 00050 public: inline KListNode<classT>& GetListNode(int index = 0){ return this->mNode[index]; }\ 00051 private: KListNode<classT> mNode[NodeCount]; 00052 00053 //----------------------------------------------------------------- 00054 template <typename T> 00055 class KListNode 00056 { 00057 typedef KListNode<T> NodeT; 00058 00059 public: 00060 explicit KListNode(T* pData = 0):mNext(0),mPrev(0),mData(pData){} 00061 ~KListNode() 00062 { 00063 Disconnect(); 00064 } 00065 00066 void Disconnect() 00067 { 00068 if ( mPrev != 0 ) 00069 mPrev->mNext = mNext; 00070 00071 if ( mNext != 0 ) 00072 mNext->mPrev = mPrev; 00073 00074 mPrev = mNext = 0; 00075 } 00076 00077 NodeT* mNext; 00078 NodeT* mPrev; 00079 00080 T* mData; 00081 }; 00082 00083 //----------------------------------------------------------------- 00084 // template arg T: Type listed 00085 // arg NodeIndex: If an object listed has multiple list node, which 00086 // index corresponds to the right node 00087 template <typename T, int NodeIndex=0> 00088 class KIntrusiveList 00089 { 00090 public: 00091 typedef T allocator_type; 00092 typedef T value_type; 00093 typedef T& reference; 00094 typedef const T& const_reference; 00095 typedef T* pointer; 00096 typedef const T* const_pointer; 00097 00098 typedef KListNode<T> NodeT; 00099 00100 // Construction / Destruction 00101 KIntrusiveList():mHead(0) 00102 { 00103 mHead.mNext = mHead.mPrev = &mHead; 00104 } 00105 ~KIntrusiveList() 00106 { 00107 while(!Empty()) 00108 Begin().Get()->Disconnect(); // LINUXNote: should be Erase(Begin()); but there's an issue with gcc 4.2 00109 }; 00110 00111 // true if the list's size is 0. 00112 bool Empty() const 00113 { 00114 return ((mHead.mNext==&mHead)&&(mHead.mPrev==&mHead)); 00115 } 00116 00117 // Back Insertion Sequence Inserts a new element at the end. 00118 void PushBack(T& pElement) 00119 { 00120 NodeT* pNode = &pElement.GetListNode(NodeIndex); 00121 pNode->mData = &pElement; 00122 00123 if (Empty()) 00124 { 00125 pNode->mNext = &mHead; 00126 pNode->mPrev = &mHead; 00127 mHead.mNext = pNode; 00128 mHead.mPrev = pNode; 00129 } 00130 else 00131 { 00132 pNode->mNext = &mHead; 00133 pNode->mPrev = mHead.mPrev; 00134 00135 pNode->mPrev->mNext = pNode; 00136 mHead.mPrev = pNode; 00137 } 00138 } 00139 00140 void PushFront(T& pElement) 00141 { 00142 NodeT* pNode = &pElement.GetListNode(NodeIndex); 00143 pNode->mData = &pElement; 00144 00145 if (Empty()) 00146 { 00147 pNode->mNext = &mHead; 00148 pNode->mPrev = &mHead; 00149 mHead.mNext = pNode; 00150 mHead.mPrev = pNode; 00151 } 00152 else 00153 { 00154 pNode->mNext = mHead.mNext; 00155 pNode->mPrev = &mHead; 00156 00157 pNode->mNext->mPrev = pNode; 00158 mHead.mNext = pNode; 00159 } 00160 } 00161 00162 void PopFront() 00163 { 00164 iterator begin = Begin(); 00165 Erase(begin); 00166 } 00167 00168 void PopBack() 00169 { 00170 Erase(--(End())); 00171 } 00172 00173 public: 00174 class IntrusiveListIterator 00175 { 00176 public: 00177 explicit IntrusiveListIterator(NodeT* ptr=0):mPtr(ptr){} 00178 00179 // pre-increment 00180 IntrusiveListIterator& operator++() 00181 { 00182 mPtr = mPtr->mNext;return (*this); 00183 } 00184 // post-increment 00185 const IntrusiveListIterator operator++(int) 00186 { 00187 IntrusiveListIterator temp = *this; 00188 ++*this; 00189 return (temp); 00190 } 00191 // pre-decrement 00192 IntrusiveListIterator& operator--() 00193 { 00194 mPtr = mPtr->mPrev;return *this; 00195 } 00196 // post-decrement 00197 const IntrusiveListIterator operator--(int) 00198 { 00199 IntrusiveListIterator temp = *this; 00200 --*this; 00201 return (temp); 00202 } 00203 IntrusiveListIterator& operator=(const IntrusiveListIterator &other){mPtr = other.mPtr; return *this;} 00204 00205 reference operator*() const { return *(mPtr->mData); } 00206 pointer operator->() const { return (&**this); } 00207 bool operator==(const IntrusiveListIterator& other)const{ return mPtr==other.mPtr; } 00208 bool operator!=(const IntrusiveListIterator& other)const{ return !(*this == other); } 00209 00210 inline NodeT* Get()const { return mPtr; } 00211 00212 private: 00213 NodeT* mPtr; 00214 }; 00215 00216 class IntrusiveListConstIterator 00217 { 00218 public: 00219 explicit IntrusiveListConstIterator(const NodeT* ptr=0):mPtr(ptr){} 00220 00221 // pre-increment 00222 IntrusiveListConstIterator& operator++() 00223 { 00224 mPtr = mPtr->mNext;return (*this); 00225 } 00226 // post-increment 00227 const IntrusiveListConstIterator operator++(int) 00228 { 00229 IntrusiveListConstIterator temp = *this; 00230 ++*this; 00231 return (temp); 00232 } 00233 // pre-decrement 00234 IntrusiveListConstIterator& operator--() 00235 { 00236 mPtr = mPtr->mPrev;return *this; 00237 } 00238 // post-decrement 00239 const IntrusiveListConstIterator operator--(int) 00240 { 00241 IntrusiveListConstIterator temp = *this; 00242 --*this; 00243 return (temp); 00244 } 00245 IntrusiveListConstIterator& operator=(const IntrusiveListConstIterator &other){mPtr = other.mPtr; return *this;} 00246 00247 const_reference operator*() const { return *(mPtr->mData); } 00248 const_pointer operator->() const { return (&**this); } 00249 bool operator==(const IntrusiveListConstIterator& other)const{ return mPtr==other.mPtr; } 00250 bool operator!=(const IntrusiveListConstIterator& other)const{ return !(*this == other); } 00251 00252 inline const NodeT* Get()const { return mPtr; } 00253 00254 private: 00255 mutable const NodeT* mPtr; 00256 }; 00257 00258 // --- Iterator definitions --- 00259 typedef IntrusiveListIterator iterator; 00260 typedef IntrusiveListConstIterator const_iterator; 00261 00262 // iterator support 00263 inline iterator Begin() { return iterator(mHead.mNext); } 00264 inline const_iterator Begin() const { return const_iterator(mHead.mNext); } 00265 inline iterator End() { return iterator(&mHead); } 00266 inline const_iterator End() const { return const_iterator(&mHead); } 00267 00268 // Because there is no real use, for the reverse iterators, 00269 // they have not been implemented. 00270 00271 reference Front(){return (*Begin());} 00272 const_reference Front() const { return (*Begin()); } 00273 reference Back(){ return (*(--End())); } 00274 const_reference Back() const{ return (*(--End())); } 00275 00276 iterator& Erase(iterator& it) 00277 { 00278 it.Get()->Disconnect(); 00279 return (++it); 00280 } 00281 private: 00282 NodeT mHead; 00283 00284 // Not copyable 00285 KIntrusiveList(const KIntrusiveList&); 00286 KIntrusiveList& operator=(const KIntrusiveList& Right){return (*this);} 00287 }; 00288 00289 // FBX namespace end 00290 #include <fbxfilesdk/fbxfilesdk_nsend.h> 00291 00292 00293 00294 00295 #endif // FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KINTRUSIVELIST_H 00296