fbxintrusivelist.h

Go to the documentation of this file.
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_ */