kintrusivelist.h

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