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 // STL
00046 // VC6Note:  #include <xutility>
00047 
00048 // FBX namespace begin
00049 #include <fbxfilesdk/fbxfilesdk_nsbegin.h>
00050 
00051 #define KFBX_LISTNODE(classT, NodeCount)\
00052     public: inline KListNode<classT>& GetListNode(int index = 0){ return this->mNode[index]; }\
00053     private:  KListNode<classT> mNode[NodeCount];
00054 
00055 //-----------------------------------------------------------------
00056 template <typename T>
00057 class KListNode
00058 {
00059     typedef KListNode<T> NodeT; 
00060 
00061 public:
00062     explicit KListNode(T* pData = 0):mNext(0),mPrev(0),mData(pData){}
00063     ~KListNode()
00064     {
00065         Disconnect();
00066     }
00067 
00068     void Disconnect()
00069     {
00070         if ( mPrev != 0 )
00071             mPrev->mNext = mNext;
00072 
00073         if ( mNext != 0 )
00074             mNext->mPrev = mPrev;
00075 
00076         mPrev = mNext = 0;
00077     }
00078 
00079     NodeT* mNext;
00080     NodeT* mPrev;
00081 
00082     T* mData;
00083 };
00084 
00085 //-----------------------------------------------------------------
00086 // template arg T: Type listed
00087 //          arg NodeIndex: If an object listed has  multiple list node, which
00088 //                         index corresponds to the right node
00089 template <typename T, int NodeIndex=0>
00090 class KIntrusiveList
00091 {
00092 public:
00093     typedef T         allocator_type;
00094     typedef T         value_type;
00095     typedef T&        reference;
00096     typedef const T&  const_reference;
00097     typedef T*        pointer;
00098     typedef const T*  const_pointer;
00099 // VC6Note :  typedef ptrdiff_t difference_type;
00100 
00101     typedef KListNode<T> NodeT;
00102 
00103     // Construction / Destruction
00104     KIntrusiveList():mHead(0)
00105     {
00106         mHead.mNext = mHead.mPrev = &mHead;
00107     }
00108     ~KIntrusiveList()
00109     {
00110         while(!Empty())
00111             Begin().Get()->Disconnect();  // LINUXNote:  should be Erase(Begin()); but there's an issue with gcc 4.2
00112     };
00113 
00114     // true if the list's size is 0.
00115     bool Empty() const
00116     {
00117         return ((mHead.mNext==&mHead)&&(mHead.mPrev==&mHead));
00118     }
00119 
00120     // Back Insertion Sequence  Inserts a new element at the end.  
00121     void PushBack(T& pElement)
00122     {
00123         NodeT* pNode = &pElement.GetListNode(NodeIndex);
00124         pNode->mData = &pElement;
00125 
00126         if (Empty())
00127         {
00128             pNode->mNext = &mHead;
00129             pNode->mPrev = &mHead;
00130             mHead.mNext = pNode;
00131             mHead.mPrev = pNode;
00132         }
00133         else
00134         {
00135             pNode->mNext = &mHead;
00136             pNode->mPrev = mHead.mPrev;
00137 
00138             pNode->mPrev->mNext = pNode;
00139             mHead.mPrev = pNode;
00140         }
00141     }
00142 
00143     void PushFront(T& pElement)
00144     {
00145         NodeT* pNode = &pElement.GetListNode(NodeIndex);
00146         pNode->mData = &pElement;
00147 
00148         if (Empty())
00149         {
00150             pNode->mNext = &mHead;
00151             pNode->mPrev = &mHead;
00152             mHead.mNext = pNode;
00153             mHead.mPrev = pNode;
00154         }
00155         else
00156         {
00157             pNode->mNext = mHead.mNext;
00158             pNode->mPrev = &mHead;
00159 
00160             pNode->mNext->mPrev = pNode;
00161             mHead.mNext = pNode;
00162         }
00163     }
00164 
00165     void PopFront()
00166     {
00167         iterator begin = Begin();
00168         Erase(begin);
00169     }
00170 
00171     void PopBack()
00172     {
00173         Erase(--(End()));
00174     }
00175 
00176 public:
00177     class IntrusiveListIterator
00178     {
00179     public:
00180      /* VC6Note: 
00181         typedef typename std::forward_iterator_tag       iterator_category;
00182         typedef typename KIntrusiveList::value_type      value_type;
00183         typedef typename KIntrusiveList::difference_type difference_type;
00184         typedef typename KIntrusiveList::reference       reference;
00185         typedef typename KIntrusiveList::const_reference const_reference;
00186         typedef typename KIntrusiveList::pointer         pointer;
00187         typedef typename KIntrusiveList::const_pointer   const_pointer;*/
00188 
00189         explicit IntrusiveListIterator(NodeT* ptr=0):mPtr(ptr){}
00190 
00191         // pre-increment
00192         IntrusiveListIterator& operator++()
00193         {
00194             mPtr = mPtr->mNext;return (*this);
00195         }
00196         // post-increment
00197         IntrusiveListIterator operator++(int)
00198         {
00199             IntrusiveListIterator temp = *this;
00200             ++*this;
00201             return (temp);
00202         }
00203         // pre-decrement
00204         IntrusiveListIterator& operator--()
00205         {
00206             mPtr = mPtr->mPrev;return *this;
00207         }
00208         // post-decrement
00209         IntrusiveListIterator operator--(int)
00210         {
00211             IntrusiveListIterator temp = *this;
00212             --*this;
00213             return (temp);
00214         }
00215         IntrusiveListIterator& operator=(const IntrusiveListIterator &other){mPtr = other.mPtr; return *this;}
00216 
00217         reference operator*() const { return *(mPtr->mData); }
00218         pointer operator->() const { return (&**this); }
00219         bool operator==(const IntrusiveListIterator& other)const{ return mPtr==other.mPtr; } 
00220         bool operator!=(const IntrusiveListIterator& other)const{ return !(*this == other); } 
00221 
00222         inline NodeT* Get()const { return mPtr; }
00223 
00224     private:
00225         NodeT* mPtr;
00226     };
00227 
00228     class  IntrusiveListConstIterator
00229     {
00230     public:
00231         /* VC6Note:
00232         typedef typename std::forward_iterator_tag       iterator_category;
00233         typedef typename KIntrusiveList::value_type      value_type;
00234         typedef typename KIntrusiveList::difference_type difference_type;
00235         typedef typename KIntrusiveList::reference       reference;
00236         typedef typename KIntrusiveList::const_reference const_reference;
00237         typedef typename KIntrusiveList::pointer         pointer;
00238         typedef typename KIntrusiveList::const_pointer   const_pointer;*/
00239 
00240         explicit IntrusiveListConstIterator(const NodeT* ptr=0):mPtr(ptr){}
00241 
00242        // pre-increment
00243         IntrusiveListConstIterator& operator++()
00244         {
00245             mPtr = mPtr->mNext;return (*this);
00246         }
00247         // post-increment
00248         IntrusiveListConstIterator& operator++(int)
00249         {
00250             IntrusiveListConstIterator temp = *this;
00251             ++*this;
00252             return (temp);
00253         }
00254         // pre-decrement
00255         IntrusiveListConstIterator& operator--()
00256         {
00257             mPtr = mPtr->mPrev;return *this;
00258         }
00259         // pre-decrement
00260         IntrusiveListConstIterator& operator--(int)
00261         {
00262             IntrusiveListConstIterator temp = *this;
00263             --*this;
00264             return (temp);
00265         }
00266         IntrusiveListConstIterator& operator=(const IntrusiveListConstIterator &other){mPtr = other.mPtr; return *this;}
00267 
00268         const_reference operator*() const { return *(mPtr->mData); }
00269         const_pointer operator->() const { return (&**this); }
00270         bool operator==(const IntrusiveListConstIterator& other)const{ return mPtr==other.mPtr; } 
00271         bool operator!=(const IntrusiveListConstIterator& other)const{ return !(*this == other); } 
00272 
00273         inline const NodeT* Get()const { return mPtr; }
00274 
00275     private:
00276         mutable const NodeT* mPtr;
00277     };
00278 
00279     // --- Iterator definitions ---
00280     typedef IntrusiveListIterator iterator;
00281     typedef IntrusiveListConstIterator const_iterator;
00282 
00283     // iterator support
00284     inline iterator Begin() { return iterator(mHead.mNext); }
00285     inline const_iterator Begin() const { return const_iterator(mHead.mNext); }
00286     inline iterator End() { return iterator(&mHead); }
00287     inline const_iterator End() const { return const_iterator(&mHead); }
00288 
00289     // Because there is no real use, for the reverse iterators, 
00290     // they have not been implemented. 
00291 
00292     reference Front(){return (*Begin());}
00293     const_reference Front() const { return (*Begin()); }
00294     reference Back(){ return (*(--End())); }
00295     const_reference Back() const{ return (*(--End())); }
00296 
00297     iterator& Erase(iterator& it)
00298     {
00299         it.Get()->Disconnect();
00300         return (++it);
00301     }
00302 private:
00303     NodeT mHead;
00304 
00305     // Not copyable
00306     KIntrusiveList(const KIntrusiveList&);
00307     KIntrusiveList& operator=(const KIntrusiveList& Right){return (*this);}
00308 };
00309 
00310 // FBX namespace end
00311 #include <fbxfilesdk/fbxfilesdk_nsend.h>
00312 
00313 
00314 
00315 
00316 #endif // FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KINTRUSIVELIST_H
00317