kmap.h

Go to the documentation of this file.
00001 
00004 #ifndef FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KMAP_H
00005 #define FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KMAP_H
00006 
00007 /**************************************************************************************
00008 
00009  Copyright (C) 2001 - 2009 Autodesk, Inc. and/or its licensors.
00010  All Rights Reserved.
00011 
00012  The coded instructions, statements, computer programs, and/or related material 
00013  (collectively the "Data") in these files contain unpublished information 
00014  proprietary to Autodesk, Inc. and/or its licensors, which is protected by 
00015  Canada and United States of America federal copyright law and by international 
00016  treaties. 
00017  
00018  The Data may not be disclosed or distributed to third parties, in whole or in
00019  part, without the prior written consent of Autodesk, Inc. ("Autodesk").
00020 
00021  THE DATA IS PROVIDED "AS IS" AND WITHOUT WARRANTY.
00022  ALL WARRANTIES ARE EXPRESSLY EXCLUDED AND DISCLAIMED. AUTODESK MAKES NO
00023  WARRANTY OF ANY KIND WITH RESPECT TO THE DATA, EXPRESS, IMPLIED OR ARISING
00024  BY CUSTOM OR TRADE USAGE, AND DISCLAIMS ANY IMPLIED WARRANTIES OF TITLE, 
00025  NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR USE. 
00026  WITHOUT LIMITING THE FOREGOING, AUTODESK DOES NOT WARRANT THAT THE OPERATION
00027  OF THE DATA WILL BE UNINTERRUPTED OR ERROR FREE. 
00028  
00029  IN NO EVENT SHALL AUTODESK, ITS AFFILIATES, PARENT COMPANIES, LICENSORS
00030  OR SUPPLIERS ("AUTODESK GROUP") BE LIABLE FOR ANY LOSSES, DAMAGES OR EXPENSES
00031  OF ANY KIND (INCLUDING WITHOUT LIMITATION PUNITIVE OR MULTIPLE DAMAGES OR OTHER
00032  SPECIAL, DIRECT, INDIRECT, EXEMPLARY, INCIDENTAL, LOSS OF PROFITS, REVENUE
00033  OR DATA, COST OF COVER OR CONSEQUENTIAL LOSSES OR DAMAGES OF ANY KIND),
00034  HOWEVER CAUSED, AND REGARDLESS OF THE THEORY OF LIABILITY, WHETHER DERIVED
00035  FROM CONTRACT, TORT (INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE), OR OTHERWISE,
00036  ARISING OUT OF OR RELATING TO THE DATA OR ITS USE OR ANY OTHER PERFORMANCE,
00037  WHETHER OR NOT AUTODESK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS
00038  OR DAMAGE. 
00039 
00040 **************************************************************************************/
00041 #include <fbxfilesdk/fbxfilesdk_def.h>
00042 
00043 #include <fbxfilesdk/components/kbaselib/klib/kpair.h>
00044 #include <fbxfilesdk/components/kbaselib/klib/kcontainerallocators.h>
00045 #include <fbxfilesdk/components/kbaselib/klib/kdebug.h>
00046 
00047 #include <new>
00048 
00049 #include <fbxfilesdk/fbxfilesdk_nsbegin.h>
00050 
00051 /* Examples of KEY_COMPARE_FUNCTOR class
00052 
00053    with KEY_TYPE = int
00054     class IntCompare {
00055         inline int operator()(int pKeyA, int pKeyB) const
00056         {
00057             return (pKeyA < pKeyB) ? -1 : ((pKeyB < pKeyA) ? 1 : 0);
00058         }
00059     };
00060 
00061    with KEY_TYPE = Class
00062     class ClassCompare {
00063         inline int operator()(Class const& pKeyA, Class const& pKeyB) const
00064         {
00065             return (pKeyA < pKeyB) ? -1 : ((pKeyB < pKeyA) ? 1 : 0);
00066         }
00067     };
00068 
00069    with KEY_TYPE = char*
00070     class StrCompare {
00071         inline int operator()(char const* pKeyA, char const* pKeyB) const
00072         {
00073             return strcmp(pKeyA, pKeyB);
00074         }
00075     };
00076 
00077 */
00078 
00079 template <typename RecordType>    class RedBack_ConstIteratorType;
00080 template <typename RecordType>    class RedBack_IteratorType;
00081 
00082 template <typename RecordType>
00083 
00086 class RedBack_IteratorType
00087 {
00088 public:
00089     RedBack_IteratorType() : mRecord(0) {}
00090     RedBack_IteratorType(RecordType* pRecord) : mRecord(pRecord) {}
00091     RedBack_IteratorType(RedBack_IteratorType<RecordType> const& pV) : mRecord(pV.mRecord) {}
00092 
00093     // prefix ++
00094     RedBack_IteratorType & operator++()
00095     {
00096         K_ASSERT( mRecord != NULL );
00097         mRecord = mRecord->Successor();
00098         return *this;
00099     }
00100 
00101     // postfix ++
00102     const RedBack_IteratorType operator++(int)
00103     {
00104         RedBack_IteratorType t(*this);
00105         operator++();
00106         return t;
00107     }
00108 
00109     // prefix --
00110     RedBack_IteratorType & operator--()
00111     {
00112         K_ASSERT( mRecord );
00113         mRecord = mRecord->Predecessor();
00114         return *this;
00115     }
00116 
00117     // postfix --
00118     const RedBack_IteratorType operator--(int)
00119     {
00120         RedBack_IteratorType t(*this);
00121         operator--();
00122         return t;
00123     }
00124 
00125     RecordType const& operator*() const
00126     {
00127         K_ASSERT( mRecord );
00128 
00129         return *mRecord;
00130     }
00131 
00132     RecordType & operator*()
00133     {
00134         K_ASSERT( mRecord );
00135 
00136         return *mRecord;
00137     }
00138 
00139     RecordType const* operator->() const
00140     {
00141         K_ASSERT( mRecord );
00142 
00143         return mRecord;
00144     }
00145 
00146     RecordType* operator->()
00147     {
00148         K_ASSERT( mRecord );
00149 
00150         return mRecord;
00151     }
00152 
00153     inline bool operator==(const RedBack_IteratorType& pOther) const
00154     {
00155         return mRecord == pOther.mRecord;
00156     }
00157 
00158     inline bool operator !=(const RedBack_IteratorType& pOther) const
00159     {
00160         return mRecord != pOther.mRecord;
00161     }
00162 
00163 protected:
00164     friend class RedBack_ConstIteratorType<RecordType>;
00165 
00166     RecordType* mRecord;
00167 };
00168 
00169 template <typename RecordType>
00170 class RedBack_ConstIteratorType
00171 {
00172 public:
00173     RedBack_ConstIteratorType() : mRecord(0) {}
00174     RedBack_ConstIteratorType(const RecordType* pRecord) : mRecord(pRecord) {}
00175     RedBack_ConstIteratorType(RedBack_IteratorType<RecordType> const& pV) : mRecord(pV.mRecord) {}
00176     RedBack_ConstIteratorType(RedBack_ConstIteratorType<RecordType> const& pV) : mRecord(pV.mRecord) {}
00177 
00178     // prefix ++
00179     RedBack_ConstIteratorType & operator++()
00180     {
00181         K_ASSERT( mRecord != NULL );
00182         mRecord = mRecord->Successor();
00183         return *this;
00184     }
00185 
00186     // postfix ++
00187     const RedBack_ConstIteratorType operator++(int)
00188     {
00189         RedBack_ConstIteratorType t(*this);
00190         operator++();
00191         return t;
00192     }
00193 
00194     // prefix --
00195     RedBack_ConstIteratorType & operator--()
00196     {
00197         K_ASSERT( mRecord );
00198         mRecord = mRecord->Predecessor();
00199         return *this;
00200     }
00201 
00202     // postfix --
00203     const RedBack_ConstIteratorType operator--(int)
00204     {
00205         RedBack_ConstIteratorType t(*this);
00206         operator--();
00207         return t;
00208     }
00209 
00210     RecordType const& operator*() const
00211     {
00212         K_ASSERT( mRecord );
00213 
00214         return *mRecord;
00215     }
00216 
00217     RecordType const& operator*()
00218     {
00219         K_ASSERT( mRecord );
00220 
00221         return *mRecord;
00222     }
00223 
00224     RecordType const* operator->() const
00225     {
00226         K_ASSERT( mRecord );
00227 
00228         return mRecord;
00229     }
00230 
00231     RecordType const* operator->()
00232     {
00233         K_ASSERT( mRecord );
00234 
00235         return mRecord;
00236     }
00237 
00238     inline bool operator==(const RedBack_ConstIteratorType& pOther) const
00239     {
00240         return mRecord == pOther.mRecord;
00241     }
00242 
00243     inline bool operator !=(const RedBack_ConstIteratorType& pOther) const
00244     {
00245         return mRecord != pOther.mRecord;
00246     }
00247 
00248 protected:
00249     friend class RedBack_IteratorType<RecordType>;
00250 
00251     RecordType const* mRecord;
00252 };
00253 
00256 template <typename DATA_TYPE,
00257           typename KEY_COMPARE_FUNCTOR,
00258           typename ALLOCATOR>
00259 class  KRedBlackTree
00260 {
00261 public:
00262     typedef DATA_TYPE DataType;
00263     typedef typename DATA_TYPE::KeyType         KeyType;
00264     typedef typename DATA_TYPE::ConstKeyType    ConstKeyType;
00265     typedef typename DATA_TYPE::ValueType       ValueType;
00266     typedef typename DATA_TYPE::ConstValueType  ConstValueType;
00267     typedef ALLOCATOR AllocatorType;
00268 
00273     class RecordType
00274     {
00275     public:
00276         inline ConstKeyType& GetKey() const { return mData.GetKey(); }
00277         inline ConstValueType& GetValue() const { return mData.GetValue(); }
00278         inline ValueType& GetValue() { return mData.GetValue(); }
00279 
00280         inline RecordType const* Minimum() const
00281         {
00282             RecordType const* lParent = 0;
00283             RecordType const* lNode = this;
00284             while (lNode != 0)
00285             {
00286                 lParent = lNode;
00287                 lNode = lNode->mLeftChild;
00288             }
00289 
00290             return lParent;
00291         }
00292 
00293         inline RecordType* Minimum()
00294         {
00295             RecordType* lParent = 0;
00296             RecordType* lNode = this;
00297             while (lNode != 0)
00298             {
00299                 lParent = lNode;
00300                 lNode = lNode->mLeftChild;
00301             }
00302 
00303             return lParent;
00304         }
00305 
00306         inline RecordType const* Maximum() const
00307         {
00308             RecordType const* lParent = 0;
00309             RecordType const* lNode = this;
00310             while (lNode != 0)
00311             {
00312                 lParent = lNode;
00313                 lNode = lNode->mRightChild;
00314             }
00315 
00316             return lParent;
00317         }
00318 
00319         inline RecordType* Maximum()
00320         {
00321             RecordType* lParent = 0;
00322             RecordType* lNode = this;
00323             while (lNode != 0)
00324             {
00325                 lParent = lNode;
00326                 lNode = lNode->mRightChild;
00327             }
00328 
00329             return lParent;
00330         }
00331 
00332         inline RecordType const* Predecessor() const
00333         {
00334             if (mLeftChild)
00335             {
00336                 return mLeftChild->Maximum();
00337             }
00338             else
00339             {
00340                 RecordType const* lParent = mParent;
00341                 RecordType const* lNode = this;
00342 
00343                 while (lParent && lParent->mLefttChild == lNode)
00344                 {
00345                     lNode = lParent;
00346                     lParent = lParent->mParent;
00347                 }
00348 
00349                 return lParent;
00350             }
00351         }
00352 
00353         inline RecordType* Predecessor()
00354         {
00355             if (mLeftChild)
00356             {
00357                 return mLeftChild->Maximum();
00358             }
00359             else
00360             {
00361                 RecordType* lParent = mParent;
00362                 RecordType* lNode = this;
00363 
00364                 while (lParent && lParent->mLeftChild == lNode)
00365                 {
00366                     lNode = lParent;
00367                     lParent = lParent->mParent;
00368                 }
00369 
00370                 return lParent;
00371             }
00372         }
00373 
00374         inline RecordType const* Successor() const
00375         {
00376             if (mRightChild)
00377             {
00378                 return mRightChild->Minimum();
00379             }
00380             else
00381             {
00382                 RecordType const* lParent = mParent;
00383                 RecordType const* lNode = this;
00384 
00385                 while (lParent && lParent->mRightChild == lNode)
00386                 {
00387                     lNode = lParent;
00388                     lParent = lParent->mParent;
00389                 }
00390 
00391                 return lParent;
00392             }
00393         }
00394 
00395         inline RecordType* Successor()
00396         {
00397             if (mRightChild)
00398             {
00399                 return mRightChild->Minimum();
00400             }
00401             else
00402             {
00403                 RecordType* lParent = mParent;
00404                 RecordType* lNode = this;
00405 
00406                 while (lParent && lParent->mRightChild == lNode)
00407                 {
00408                     lNode = lParent;
00409                     lParent = lParent->mParent;
00410                 }
00411 
00412                 return lParent;
00413             }
00414         }
00415 
00416         inline int GetBlackDepth() const { return mBlackDepth; }
00417 
00418     private:
00419         enum { eRed, eBlack };
00420 
00421         inline RecordType(DataType const& pData)
00422             : mData(pData)
00423             , mParent(0)
00424             , mLeftChild(0)
00425             , mRightChild(0)
00426             , mColor(eRed)
00427             , mBlackDepth(0)
00428         {
00429         }
00430 
00431         inline RecordType(RecordType const& pRecordType)
00432             : mData(pRecordType.mData)
00433             , mParent(0)
00434             , mLeftChild(0)
00435             , mRightChild(0)
00436             , mColor(pRecordType.mColor)
00437             , mBlackDepth(pRecordType.mBlackDepth)
00438         {
00439         }
00440 
00441         DataType mData;
00442 
00443         friend class KRedBlackTree;
00444 
00445         RecordType* mParent;
00446         RecordType* mLeftChild;
00447         RecordType* mRightChild;
00448         unsigned int mColor:2;
00449         unsigned int mBlackDepth:30;
00450     };
00451 
00452 public:
00453     typedef RedBack_ConstIteratorType<RecordType>  ConstIteratorType;
00454     typedef RedBack_IteratorType<RecordType>       IteratorType;
00455 
00456 public:
00457     inline KRedBlackTree() : mRoot(0), mSize(0), mAllocator(sizeof(RecordType)) {}
00458     inline KRedBlackTree(KRedBlackTree const& pTree) : mRoot(0), mSize(0), mAllocator(sizeof(RecordType)) { operator=(pTree); }
00459     inline ~KRedBlackTree() { Clear(); }
00460 
00464     inline KRedBlackTree& operator=(KRedBlackTree const& pTree)
00465     {
00466         if( this != &pTree )
00467         {
00468             Clear();
00469 
00470             mAllocator = pTree.mAllocator;
00471 
00472             if( pTree.mRoot )
00473             {
00474                 void* lBuffer = mAllocator.AllocateRecords();
00475                 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00476                     #pragma push_macro("new")
00477                     #undef new
00478                 #endif
00479                 mRoot = new(lBuffer) RecordType(*(pTree.mRoot));
00480                 #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00481                     #pragma pop_macro("new")
00482                 #endif
00483                 mRoot->mLeftChild = DuplicateSubTree(pTree.mRoot->mLeftChild);
00484                 mRoot->mRightChild = DuplicateSubTree(pTree.mRoot->mRightChild);
00485 
00486                 if (mRoot->mLeftChild)
00487                 {
00488                     mRoot->mLeftChild->mParent = mRoot;
00489                 }
00490 
00491                 if (mRoot->mRightChild)
00492                 {
00493                     mRoot->mRightChild->mParent = mRoot;
00494                 }
00495             }
00496             else
00497             {
00498                 K_ASSERT( pTree.mSize == 0 );
00499                 K_ASSERT( mRoot == 0 );
00500             }
00501 
00502             mSize = pTree.mSize;
00503         }
00504 
00505         return *this;
00506     }
00507 
00508     inline bool operator==(KRedBlackTree const& pTree) const
00509     {
00510         // Check a few quick shortcuts
00511         if( this == &pTree )
00512             return true;
00513 
00514         if( GetSize() != pTree.GetSize() )
00515             return false;
00516 
00517         // Iterator through all nodes; if we reach the end of both iterators at the same
00518         // time then we have two iterators that match.
00519         ConstIteratorType End;
00520         ConstIteratorType Iter1(Minimum());
00521         ConstIteratorType Iter2(pTree.Minimum());
00522 
00523         while( (Iter1 != End) && (Iter2 != End) &&
00524                (Iter1->GetKey() == Iter2->GetKey()) &&
00525                (Iter1->GetValue() == Iter2->GetValue()) )
00526         {
00527             ++Iter1;
00528             ++Iter2;
00529         }
00530 
00531         return Iter1 == End && Iter2 == End;
00532     }
00533 
00537     inline void Reserve(unsigned int pRecordCount)
00538     {
00539         mAllocator.Reserve(pRecordCount);
00540     }
00541 
00545     inline int GetSize() const { return mSize; }
00546 
00547     inline bool Empty() const { return mSize == 0; }
00548 
00554     inline KPair<RecordType*, bool> Insert(DataType const& pData)
00555     {
00556         KEY_COMPARE_FUNCTOR lCompareKeys;
00557         bool lResult = false;
00558         RecordType* lParent = 0;
00559         RecordType* lNode = mRoot;
00560         while (lNode != 0)
00561         {
00562             KeyType const& lNodeKey = lNode->GetKey();
00563             KeyType const& lDataKey = pData.GetKey();
00564 
00565             if (lCompareKeys(lNodeKey, lDataKey) < 0)
00566             {
00567                 lParent = lNode;
00568                 lNode = lNode->mRightChild;
00569             }
00570             else if (lCompareKeys(lNodeKey, lDataKey) > 0)
00571             {
00572                 lParent = lNode;
00573                 lNode = lNode->mLeftChild;
00574             }
00575             else
00576             {
00577                 break;
00578             }
00579         }
00580 
00581         if (lNode == 0)
00582         {
00583             void* lBuffer = mAllocator.AllocateRecords();
00584             #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00585                 #pragma push_macro("new")
00586                 #undef new
00587             #endif
00588             lNode = new(lBuffer) RecordType(pData);
00589             #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00590                 #pragma pop_macro("new")
00591             #endif
00592             mSize++;
00593 
00594             #if ( !defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00595                 K_ASSERT(lNode == lBuffer);
00596             #endif
00597 
00598             if (lParent)
00599             {
00600                 if (lCompareKeys(lParent->GetKey(), pData.GetKey()) < 0)
00601                 {
00602                     K_ASSERT(lParent->mRightChild == 0);
00603                     lParent->mRightChild = lNode;
00604                     lNode->mParent = lParent;
00605                 }
00606                 else
00607                 {
00608                     K_ASSERT(lParent->mLeftChild == 0);
00609                     lParent->mLeftChild = lNode;
00610                     lNode->mParent = lParent;
00611                 }
00612             }
00613             else
00614             {
00615                 mRoot = lNode;
00616             }
00617 
00618             // Fix red black tree property
00619             FixNodesAfterInsertion(lNode);
00620 
00621             lResult = true;
00622         }
00623 
00624 #ifdef SANITY_CHECK
00625         IsSane();
00626 #endif
00627 
00628         return KPair<RecordType*, bool>(lNode, lResult);
00629     }
00630 
00634     inline bool Remove(KeyType const& pKey)
00635     {
00636         KEY_COMPARE_FUNCTOR lCompareKeys;
00637         bool lResult = false;
00638         RecordType* lNode = mRoot;
00639         while (lNode != 0)
00640         {
00641             if (lCompareKeys(lNode->GetKey(), pKey) < 0)
00642             {
00643                 lNode = lNode->mRightChild;
00644             }
00645             else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
00646             {
00647                 lNode = lNode->mLeftChild;
00648             }
00649             else
00650             {
00651                 break;
00652             }
00653         }
00654 
00655         if (lNode)
00656         {
00657             RemoveNode(lNode);
00658             mSize--;
00659             lNode->~RecordType();
00660             mAllocator.FreeMemory(lNode);
00661 
00662             lResult = true;
00663         }
00664 
00665 #ifdef SANITY_CHECK
00666         IsSane();
00667 #endif
00668 
00669         return lResult;
00670     }
00671 
00674     inline void Clear()
00675     {
00676         if (mRoot)
00677         {
00678             ClearSubTree(mRoot->mLeftChild);
00679             ClearSubTree(mRoot->mRightChild);
00680             mRoot->~RecordType();
00681             mAllocator.FreeMemory(mRoot);
00682             mRoot = 0;
00683             mSize = 0;
00684         }
00685     }
00686 
00690     inline RecordType const* Minimum() const
00691     {
00692         if (0 != mRoot)
00693         {
00694             return mRoot->Minimum();
00695         }
00696         else
00697         {
00698             return 0;
00699         }
00700     }
00701 
00705     inline RecordType* Minimum()
00706     {
00707         if (0 != mRoot)
00708         {
00709             return mRoot->Minimum();
00710         }
00711         else
00712         {
00713             return 0;
00714         }
00715     }
00716 
00720     inline RecordType const* Maximum() const
00721     {
00722         if (0 != mRoot)
00723         {
00724             return mRoot->Maximum();
00725         }
00726         else
00727         {
00728             return 0;
00729         }
00730     }
00731 
00735     inline RecordType* Maximum()
00736     {
00737         if (0 != mRoot)
00738         {
00739             return mRoot->Maximum();
00740         }
00741         else
00742         {
00743             return 0;
00744         }
00745     }
00746 
00751     inline RecordType const* Find(KeyType const& pKey) const
00752     {
00753         KEY_COMPARE_FUNCTOR lCompareKeys;
00754         RecordType const* lNode = mRoot;
00755         while (lNode != 0)
00756         {
00757             if (lCompareKeys(lNode->GetKey(), pKey) < 0)
00758             {
00759                 lNode = lNode->mRightChild;
00760             }
00761             else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
00762             {
00763                 lNode = lNode->mLeftChild;
00764             }
00765             else
00766             {
00767                 break;
00768             }
00769         }
00770 
00771         return lNode;
00772     }
00773 
00778     inline RecordType* Find(KeyType const& pKey)
00779     {
00780         KEY_COMPARE_FUNCTOR lCompareKeys;
00781         RecordType* lNode = mRoot;
00782         while (lNode != 0)
00783         {
00784             if (lCompareKeys(lNode->GetKey(), pKey) < 0)
00785             {
00786                 lNode = lNode->mRightChild;
00787             }
00788             else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
00789             {
00790                 lNode = lNode->mLeftChild;
00791             }
00792             else
00793             {
00794                 break;
00795             }
00796         }
00797 
00798         return lNode;
00799     }
00800 
00805     inline RecordType const* UpperBound(KeyType const& pKey) const
00806     {
00807         KEY_COMPARE_FUNCTOR lCompareKeys;
00808         RecordType const* lNode = mRoot;
00809         RecordType const* lCandidate = 0;
00810         while (lNode != 0)
00811         {
00812             if (lCompareKeys(lNode->GetKey(), pKey) <= 0)
00813             {
00814                 lNode = lNode->mRightChild;
00815             }
00816             else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
00817             {
00818                 lCandidate = lNode;
00819                 lNode = lNode->mLeftChild;
00820             }
00821         }
00822         
00823         return lCandidate;
00824     }
00825 
00830     inline RecordType* UpperBound(KeyType const& pKey)
00831     {
00832         KEY_COMPARE_FUNCTOR lCompareKeys;
00833         RecordType* lNode = mRoot;
00834         RecordType* lCandidate = 0;
00835         while (lNode != 0)
00836         {
00837             if (lCompareKeys(lNode->GetKey(), pKey) <= 0)
00838             {
00839                 lNode = lNode->mRightChild;
00840             }
00841             else if (lCompareKeys(lNode->GetKey(), pKey) > 0)
00842             {
00843                 lCandidate = lNode;
00844                 lNode = lNode->mLeftChild;
00845             }
00846         }
00847         
00848         return lCandidate;
00849     }
00850 
00851 protected:
00852     RecordType* mRoot;
00853     int mSize;
00854 
00855     AllocatorType mAllocator;
00856 
00861     inline void IsSane()
00862     {
00863         K_ASSERT((mRoot == 0) || (mRoot->mColor == RecordType::eBlack));
00864         K_ASSERT(((mRoot == 0) && (mSize == 0)) || (mRoot != 0) && (mSize != 0));
00865         IsSubTreeSane(mRoot);
00866 
00867         ComputeBlackDepth(mRoot, 0);
00868 
00869         RecordType* lNode = mRoot;
00870         unsigned int lLeafBlackDepth = 0;
00871         while (lNode)
00872         {
00873             if (lNode->mLeftChild == 0)
00874             {
00875                 lLeafBlackDepth = lNode->mBlackDepth + ((lNode->mColor == RecordType::eBlack) ? 1 : 0);
00876             }
00877 
00878             lNode = lNode->mLeftChild;
00879         }
00880 
00881         CheckLeavesBlackDepth(mRoot, lLeafBlackDepth);
00882     }
00883 
00884     inline void IsSubTreeSane(RecordType const* pNode) const
00885     {
00886         KEY_COMPARE_FUNCTOR lCompareKeys;
00887 
00888         if (pNode)
00889         {
00890             K_ASSERT(pNode != pNode->mParent);
00891             K_ASSERT(pNode != pNode->mLeftChild);
00892             K_ASSERT(pNode != pNode->mRightChild);
00893 
00894             // Check for two consecutive red nodes
00895             K_ASSERT((pNode->mColor == RecordType::eBlack) ||
00896                      (pNode->mLeftChild == NULL) ||
00897                      (pNode->mLeftChild->mColor == RecordType::eBlack));
00898 
00899             K_ASSERT((pNode->mColor == RecordType::eBlack) ||
00900                      (pNode->mRightChild == NULL) ||
00901                      (pNode->mRightChild->mColor == RecordType::eBlack));
00902 
00903             // Check key ordering
00904             K_ASSERT((pNode->mLeftChild == 0 ||
00905                       lCompareKeys(pNode->GetKey(), pNode->mLeftChild->GetKey()) > 0));
00906 
00907             K_ASSERT((pNode->mRightChild == 0 ||
00908                       lCompareKeys(pNode->GetKey(), pNode->mRightChild->GetKey()) < 0));
00909 
00910             IsSubTreeSane(pNode->mLeftChild);
00911             IsSubTreeSane(pNode->mRightChild);
00912         }
00913     }
00914 
00915     inline void ComputeBlackDepth(RecordType* pNode, unsigned int pDepth)
00916     {
00917         if (pNode)
00918         {
00919             pNode->mBlackDepth = pDepth;
00920             if (pNode->mColor == RecordType::eBlack)
00921             {
00922                 pDepth++;
00923             }
00924 
00925             ComputeBlackDepth(pNode->mLeftChild, pDepth);
00926             ComputeBlackDepth(pNode->mRightChild, pDepth);
00927         }
00928     }
00929 
00930     inline void CheckLeavesBlackDepth(RecordType* pNode, unsigned int pBlackDepth)
00931     {
00932         if (pNode)
00933         {
00934             if ((pNode->mLeftChild == 0) || pNode->mRightChild == 0)
00935             {
00936                 int lBlackDepth = pNode->mBlackDepth + ((pNode->mColor == RecordType::eBlack) ? 1 : 0);
00937                 K_ASSERT(lBlackDepth == pBlackDepth);
00938             }
00939 
00940             CheckLeavesBlackDepth(pNode->mLeftChild, pBlackDepth);
00941             CheckLeavesBlackDepth(pNode->mRightChild, pBlackDepth);
00942         }
00943     }
00944 
00945     inline RecordType* DuplicateSubTree(RecordType const* pNode)
00946     {
00947         RecordType* lNewSubTree = 0;
00948 
00949         if (pNode)
00950         {
00951             void* lBuffer = mAllocator.AllocateRecords();
00952             #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00953                 #pragma push_macro("new")
00954                 #undef new
00955             #endif
00956             lNewSubTree = new(lBuffer) RecordType(*pNode);
00957             #if ( defined(MEMORY_DEBUG) && defined(_DEBUG) && defined(KARCH_ENV_WIN32))
00958                 #pragma pop_macro("new")
00959             #endif
00960             lNewSubTree->mLeftChild = DuplicateSubTree(pNode->mLeftChild);
00961             lNewSubTree->mRightChild = DuplicateSubTree(pNode->mRightChild);
00962 
00963             if (lNewSubTree->mLeftChild)
00964             {
00965                 lNewSubTree->mLeftChild->mParent = lNewSubTree;
00966             }
00967 
00968             if (lNewSubTree->mRightChild)
00969             {
00970                 lNewSubTree->mRightChild->mParent = lNewSubTree;
00971             }
00972         }
00973 
00974         return lNewSubTree;
00975     }
00976 
00977     inline void FixNodesAfterInsertion(RecordType* pNode)
00978     {
00979         RecordType* lNode = pNode;
00980         bool lDone = false;
00981 
00982         while (!lDone)
00983         {
00984             lDone = true;
00985 
00986             if (lNode->mParent == 0)
00987             {
00988                 lNode->mColor = RecordType::eBlack;
00989             }
00990             else if (lNode->mParent->mColor == RecordType::eRed)
00991             {
00992                 RecordType* lUncle = 0;
00993                 if (lNode->mParent == lNode->mParent->mParent->mLeftChild)
00994                 {
00995                     lUncle = lNode->mParent->mParent->mRightChild;
00996                 }
00997                 else if (lNode->mParent == lNode->mParent->mParent->mRightChild)
00998                 {
00999                     lUncle = lNode->mParent->mParent->mLeftChild;
01000                 }
01001 
01002                 // since lNode->mParent is red, lNode->mParent->mParent exists
01003 
01004                 if (lUncle && lUncle->mColor == RecordType::eRed)
01005                 {
01006                     lNode->mParent->mColor = RecordType::eBlack;
01007                     lUncle->mColor = RecordType::eBlack;
01008                     lNode->mParent->mParent->mColor = RecordType::eRed;
01009                     lNode = lNode->mParent->mParent;
01010 
01011                     lDone = false;
01012                 }
01013                 else
01014                 {
01015                     if ((lNode == lNode->mParent->mRightChild) &&
01016                         (lNode->mParent == lNode->mParent->mParent->mLeftChild))
01017                     {
01018                         LeftRotate(lNode->mParent);
01019                         lNode = lNode->mLeftChild;
01020                     }
01021                     else if ((lNode == lNode->mParent->mLeftChild) &&
01022                             (lNode->mParent == lNode->mParent->mParent->mRightChild))
01023                     {
01024                         RightRotate(lNode->mParent);
01025                         lNode = lNode->mRightChild;
01026                     }
01027 
01028                     lNode->mParent->mColor = RecordType::eBlack;
01029                     lNode->mParent->mParent->mColor = RecordType::eRed;
01030                     if ((lNode == lNode->mParent->mLeftChild) &&
01031                         (lNode->mParent == lNode->mParent->mParent->mLeftChild))
01032                     {
01033                         RightRotate(lNode->mParent->mParent);
01034                     }
01035                     else
01036                     {
01037                         LeftRotate(lNode->mParent->mParent);
01038                     }
01039                 }
01040             }
01041         }
01042 
01043         mRoot->mColor = RecordType::eBlack;
01044     }
01045 
01046     inline void LeftRotate(RecordType* pNode)
01047     {
01048         RecordType* lNode = pNode->mRightChild;
01049 
01050 #ifdef _DEBUG
01051         RecordType* A = pNode->mLeftChild;
01052         RecordType* B = lNode->mLeftChild;
01053         RecordType* C = lNode->mRightChild;
01054         RecordType* Z = pNode->mParent;
01055 #endif
01056 
01057         pNode->mRightChild = lNode->mLeftChild;
01058         if (pNode->mRightChild)
01059         {
01060             pNode->mRightChild->mParent = pNode;
01061         }
01062 
01063         lNode->mParent = pNode->mParent;
01064         if (pNode->mParent == 0)
01065         {
01066             K_ASSERT(mRoot == pNode);
01067             mRoot = lNode;
01068         }
01069         else if (pNode == pNode->mParent->mLeftChild)
01070         {
01071             pNode->mParent->mLeftChild = lNode;
01072         }
01073         else
01074         {
01075             pNode->mParent->mRightChild = lNode;
01076         }
01077         pNode->mParent = lNode;
01078         lNode->mLeftChild = pNode;
01079 
01080         K_ASSERT(pNode->mLeftChild == A);
01081         K_ASSERT(pNode->mRightChild == B);
01082         K_ASSERT(pNode->mParent == lNode);
01083 
01084         K_ASSERT(lNode->mLeftChild == pNode);
01085         K_ASSERT(lNode->mRightChild == C);
01086         K_ASSERT(lNode->mParent == Z);
01087 
01088         K_ASSERT(A == 0 || A->mParent == pNode);
01089         K_ASSERT(B == 0 || B->mParent == pNode);
01090         K_ASSERT(C == 0 || C->mParent == lNode);
01091         K_ASSERT(Z == 0 || Z->mLeftChild == lNode || Z->mRightChild == lNode);
01092     }
01093 
01094 
01095     inline void RightRotate(RecordType* pNode)
01096     {
01097         RecordType* lNode = pNode->mLeftChild;
01098 
01099 #ifdef _DEBUG
01100         RecordType* A = lNode->mLeftChild;
01101         RecordType* B = lNode->mRightChild;
01102         RecordType* C = pNode->mRightChild;
01103         RecordType* Z = pNode->mParent;
01104 #endif
01105 
01106         pNode->mLeftChild = lNode->mRightChild;
01107         if (pNode->mLeftChild)
01108         {
01109             pNode->mLeftChild->mParent = pNode;
01110         }
01111 
01112         lNode->mParent = pNode->mParent;
01113         if (pNode->mParent == 0)
01114         {
01115             K_ASSERT(mRoot == pNode);
01116             mRoot = lNode;
01117         }
01118         else if (pNode == pNode->mParent->mRightChild)
01119         {
01120             pNode->mParent->mRightChild = lNode;
01121         }
01122         else
01123         {
01124             pNode->mParent->mLeftChild = lNode;
01125         }
01126         pNode->mParent = lNode;
01127         lNode->mRightChild = pNode;
01128 
01129         K_ASSERT(lNode->mLeftChild == A);
01130         K_ASSERT(lNode->mRightChild == pNode);
01131         K_ASSERT(lNode->mParent == Z);
01132 
01133         K_ASSERT(pNode->mLeftChild == B);
01134         K_ASSERT(pNode->mRightChild == C);
01135         K_ASSERT(pNode->mParent == lNode);
01136 
01137         K_ASSERT(A == 0 || A->mParent == lNode);
01138         K_ASSERT(B == 0 || B->mParent == pNode);
01139         K_ASSERT(C == 0 || C->mParent == pNode);
01140         K_ASSERT(Z == 0 || Z->mLeftChild == lNode || Z->mRightChild == lNode);
01141     }
01142 
01143 
01144     inline void RemoveNode(RecordType* pNode)
01145     {
01146         if (pNode->mLeftChild == 0)
01147         {
01148             if (pNode->mRightChild == 0)
01149             {
01150                 if (pNode->mParent)
01151                 {
01152                     if (pNode->mParent->mLeftChild == pNode)
01153                     {
01154                         pNode->mParent->mLeftChild = 0;
01155                     }
01156                     else if (pNode->mParent->mRightChild == pNode)
01157                     {
01158                         pNode->mParent->mRightChild = 0;
01159                     }
01160                     else
01161                     {
01162                         K_ASSERT_MSG_NOW("Node not found in KRedBlackTree");
01163                     }
01164                 }
01165                 else
01166                 {
01167                     K_ASSERT(mRoot == pNode);
01168                     mRoot = 0;
01169                 }
01170 
01171                 if (pNode->mColor == RecordType::eBlack)
01172                 {
01173                     FixNodesAfterRemoval(pNode->mParent, 0);
01174                 }
01175             }
01176             else
01177             {
01178                 if (pNode->mParent)
01179                 {
01180                     if (pNode->mParent->mLeftChild == pNode)
01181                     {
01182                         pNode->mParent->mLeftChild = pNode->mRightChild;
01183                         pNode->mRightChild->mParent = pNode->mParent;
01184                     }
01185                     else if (pNode->mParent->mRightChild == pNode)
01186                     {
01187                         pNode->mParent->mRightChild = pNode->mRightChild;
01188                         pNode->mRightChild->mParent = pNode->mParent;
01189                     }
01190                     else
01191                     {
01192                         K_ASSERT_MSG_NOW("Node not found in KRedBlackTree");
01193                     }
01194                 }
01195                 else
01196                 {
01197                     K_ASSERT(mRoot == pNode);
01198                     mRoot = pNode->mRightChild;
01199                     pNode->mRightChild->mParent = 0;
01200                 }
01201 
01202                 if (pNode->mColor == RecordType::eBlack)
01203                 {
01204                     FixNodesAfterRemoval(pNode->mRightChild->mParent, pNode->mRightChild);
01205                 }
01206             }
01207         }
01208         else
01209         {
01210             if (pNode->mRightChild == 0)
01211             {
01212                 if (pNode->mParent)
01213                 {
01214                     if (pNode->mParent->mLeftChild == pNode)
01215                     {
01216                         pNode->mParent->mLeftChild = pNode->mLeftChild;
01217                         pNode->mLeftChild->mParent = pNode->mParent;
01218                     }
01219                     else if (pNode->mParent->mRightChild == pNode)
01220                     {
01221                         pNode->mParent->mRightChild = pNode->mLeftChild;
01222                         pNode->mLeftChild->mParent = pNode->mParent;
01223                     }
01224                     else
01225                     {
01226                         K_ASSERT_MSG_NOW("Node not found in KRedBlackTree");
01227                     }
01228                 }
01229                 else
01230                 {
01231                     K_ASSERT(mRoot == pNode);
01232                     mRoot = pNode->mLeftChild;
01233                     pNode->mLeftChild->mParent = 0;
01234                 }
01235 
01236                 if (pNode->mColor == RecordType::eBlack)
01237                 {
01238                     FixNodesAfterRemoval(pNode->mLeftChild->mParent, pNode->mLeftChild);
01239                 }
01240             }
01241             else
01242             {
01243                 RecordType* lMinRightNode = pNode->mRightChild->Minimum();
01244                 RemoveNode(lMinRightNode);
01245 
01246                 lMinRightNode->mColor = pNode->mColor;
01247                 ReplaceNode(pNode, lMinRightNode);
01248             }
01249         }
01250 
01251         pNode->mParent = 0;
01252         pNode->mLeftChild = 0;
01253         pNode->mRightChild = 0;
01254     }
01255 
01256 
01257     inline void ReplaceNode(RecordType* pNodeToReplace, RecordType* pReplacement)
01258     {
01259         pReplacement->mParent = pNodeToReplace->mParent;
01260         if (pNodeToReplace->mParent)
01261         {
01262             if (pNodeToReplace->mParent->mLeftChild == pNodeToReplace)
01263             {
01264                 pNodeToReplace->mParent->mLeftChild = pReplacement;
01265             }
01266             else if (pNodeToReplace->mParent->mRightChild == pNodeToReplace)
01267             {
01268                 pNodeToReplace->mParent->mRightChild = pReplacement;
01269             }
01270         }
01271         else
01272         {
01273             K_ASSERT(mRoot == pNodeToReplace);
01274             mRoot = pReplacement;
01275         }
01276 
01277         pReplacement->mLeftChild = pNodeToReplace->mLeftChild;
01278         if (pReplacement->mLeftChild)
01279         {
01280             pReplacement->mLeftChild->mParent = pReplacement;
01281         }
01282 
01283         pReplacement->mRightChild = pNodeToReplace->mRightChild;
01284         if (pReplacement->mRightChild)
01285         {
01286             pReplacement->mRightChild->mParent = pReplacement;
01287         }
01288     }
01289 
01290     inline RecordType* Sibling(RecordType const* pParent, RecordType const* pNode) const
01291     {
01292         if (pParent)
01293         {
01294             if (pParent->mLeftChild == pNode)
01295             {
01296                 return pParent->mRightChild;
01297             }
01298             else if (pParent->mRightChild == pNode)
01299             {
01300                 return pParent->mLeftChild;
01301             }
01302         }
01303 
01304         return 0;
01305     }
01306 
01307     inline bool IsBlack(RecordType const* pNode)
01308     {
01309         return ((pNode == 0) || (pNode->mColor == RecordType::eBlack));
01310     }
01311 
01312     inline void FixNodesAfterRemoval(RecordType* pParent, RecordType* pNode)
01313     {
01314         RecordType* lParent = pParent;
01315         RecordType* lNode = pNode;
01316         bool lDone = false;
01317 
01318         while (!lDone)
01319         {
01320             lDone = true;
01321 
01322             if (!IsBlack(lNode))
01323             {
01324                 lNode->mColor = RecordType::eBlack;
01325             }
01326             else if (lParent != NULL)
01327             {
01328                 RecordType* lSibling = Sibling(lParent, lNode);
01329 
01330                 if (!IsBlack(lSibling))
01331                 {
01332                     lParent->mColor = RecordType::eRed;
01333                     lSibling->mColor = RecordType::eBlack;
01334                     if (lNode == lParent->mLeftChild)
01335                     {
01336                         LeftRotate(lParent);
01337                     }
01338                     else
01339                     {
01340                         RightRotate(lParent);
01341                     }
01342 
01343                     // update sibling: it may have change after rotation
01344                     // parent was not affected by this rotation
01345                     lSibling = Sibling(lParent, lNode);
01346                 }
01347 
01348                 /* check this for null sibling */
01349                 if (lSibling &&
01350                     IsBlack(lParent) &&
01351                     IsBlack(lSibling) &&
01352                     IsBlack(lSibling->mLeftChild) &&
01353                     IsBlack(lSibling->mRightChild))
01354                 {
01355                     lSibling->mColor = RecordType::eRed;
01356                     lNode = lParent;
01357                     lParent = lParent->mParent;
01358                     lDone = false;
01359                 }
01360                 else
01361                 {
01362                     if (!IsBlack(lParent) &&
01363                         IsBlack(lSibling) &&
01364                         ((lSibling == 0) || IsBlack(lSibling->mLeftChild)) &&
01365                         ((lSibling == 0) || IsBlack(lSibling->mRightChild)))
01366                     {
01367                         if (lSibling)
01368                         {
01369                             lSibling->mColor = RecordType::eRed;
01370                         }
01371                         lParent->mColor = RecordType::eBlack;
01372                     }
01373                     else // lSibling != 0
01374                     {
01375                         if ((lNode == lParent->mLeftChild) &&
01376                             IsBlack(lSibling) &&
01377                             !IsBlack(lSibling->mLeftChild) &&
01378                             IsBlack(lSibling->mRightChild))
01379                         {
01380                             lSibling->mColor = RecordType::eRed;
01381                             lSibling->mLeftChild->mColor = RecordType::eBlack;
01382                             RightRotate(lSibling);
01383                         }
01384                         else if ((lNode == lParent->mRightChild) &&
01385                                  IsBlack(lSibling) &&
01386                                  IsBlack(lSibling->mLeftChild) &&
01387                                  !IsBlack(lSibling->mRightChild))
01388                         {
01389                             lSibling->mColor = RecordType::eRed;
01390                             lSibling->mRightChild->mColor = RecordType::eBlack;
01391                             LeftRotate(lSibling);
01392                         }
01393 
01394                         // update sibling: it may have change after rotation
01395                         lSibling = Sibling(lParent, lNode);
01396                         K_ASSERT(lSibling != 0); // lSibling is now
01397                                                  // the former red
01398                                                  // child of the
01399                                                  // former sibling
01400 
01401                         lSibling->mColor = lParent->mColor;
01402                         lParent->mColor = RecordType::eBlack;
01403                         if (lNode == lParent->mLeftChild)
01404                         {
01405                             if (lSibling->mRightChild)
01406                             {
01407                                 lSibling->mRightChild->mColor = RecordType::eBlack;
01408                             }
01409                             LeftRotate(lParent);
01410                         }
01411                         else
01412                         {
01413                             if (lSibling->mLeftChild)
01414                             {
01415                                 lSibling->mLeftChild->mColor = RecordType::eBlack;
01416                             }
01417                             RightRotate(lParent);
01418                         }
01419                     }
01420                 }
01421             }
01422         }
01423 
01424         if (mRoot)
01425         {
01426             mRoot->mColor = RecordType::eBlack;
01427         }
01428     }
01429 
01430 
01431     inline void ClearSubTree(RecordType* pNode)
01432     {
01433         if (pNode)
01434         {
01435             ClearSubTree(pNode->mLeftChild);
01436             ClearSubTree(pNode->mRightChild);
01437             pNode->~RecordType();
01438             mAllocator.FreeMemory(pNode);
01439         }
01440     }
01441 
01442     inline int GetSubTreeSize(RecordType* pNode) const
01443     {
01444         if (pNode)
01445         {
01446             return GetSubTreeSize(pNode->mLeftChild) + GetSubTreeSize(pNode->mRightChild) + 1;
01447         }
01448         else
01449         {
01450             return 0;
01451         }
01452     }
01453 
01454 };
01455 
01456 /*************************************************************************
01457  *
01458  * Default comparator for maps.  Assumes operator < is defined.
01459  *
01460  *************************************************************************/
01461 
01462 template <typename T>
01463 struct KFbxLessCompare
01464 {
01465     inline int operator()(const T& left, const T& right) const
01466     {
01467         return (left < right) ? -1 : ((right < left) ? 1 : 0);
01468     }
01469 };
01470 
01471 /*************************************************************************
01472  * class KMap
01473  *
01474  * Implements an efficient dictionnary.
01475  *
01476  *************************************************************************/
01477 
01478 
01479 template <typename KEY_TYPE,
01480           typename VALUE_TYPE,
01481           typename KEY_COMPARE_FUNCTOR = KFbxLessCompare<KEY_TYPE>,
01482           typename ALLOCATOR = KBaseAllocator>
01483 class KMap
01484 {
01485 protected:
01486     class KKeyValuePair : private KPair<const KEY_TYPE, VALUE_TYPE>
01487     {
01488     public:
01489         KKeyValuePair(KEY_TYPE const& pFirst, VALUE_TYPE const& pSecond)
01490             : KPair<const KEY_TYPE, VALUE_TYPE>(pFirst, pSecond) {}
01491 
01492         // Key is always const.
01493         typedef const KEY_TYPE      KeyType;
01494         typedef const KEY_TYPE      ConstKeyType;
01495         typedef VALUE_TYPE          ValueType;
01496         typedef const VALUE_TYPE    ConstValueType;
01497 
01498         ConstKeyType & GetKey() const       { return this->mFirst; }
01499         KeyType & GetKey()                  { return this->mFirst; }
01500 
01501         ConstValueType& GetValue() const    { return this->mSecond; }
01502         ValueType& GetValue()               { return this->mSecond; }
01503     };
01504 
01505     typedef KRedBlackTree<KKeyValuePair, KEY_COMPARE_FUNCTOR, ALLOCATOR> StorageType;
01506     StorageType mTree;
01507 
01508 
01509 public:
01510     typedef VALUE_TYPE ValueType;
01511     typedef KEY_TYPE KeyType;
01512     typedef typename StorageType::RecordType         RecordType;
01513     typedef typename StorageType::IteratorType       Iterator;
01514     typedef typename StorageType::ConstIteratorType  ConstIterator;
01515 
01516     inline KMap() {}
01517     inline KMap(KMap const& pMap) : mTree(pMap.mTree) {}
01518     inline ~KMap() {Clear();}
01519 
01520     inline void Reserve(unsigned int pRecordCount)
01521     {
01522         mTree.Reserve(pRecordCount);
01523     }
01524 
01525     inline int GetSize() const
01526     {
01527         return mTree.GetSize();
01528     }
01529 
01530     inline KPair<RecordType*, bool> Insert(KeyType const& pKey, ValueType const& pValue)
01531     {
01532         return mTree.Insert(KKeyValuePair(pKey, pValue));
01533     }
01534 
01535     inline int Remove(KeyType const& pKey)
01536     {
01537         return mTree.Remove(pKey);
01538     }
01539 
01540     inline void Clear()
01541     {
01542         mTree.Clear();
01543     }
01544 
01545     inline bool Empty() const
01546     {
01547         return mTree.Empty();
01548     }
01549 
01550     Iterator Begin()
01551     {
01552         return Iterator(Minimum());
01553     }
01554 
01555     Iterator End()
01556     {
01557         return Iterator();
01558     }
01559 
01560     ConstIterator Begin() const
01561     {
01562         return ConstIterator(Minimum());
01563     }
01564 
01565     ConstIterator End() const
01566     {
01567         return ConstIterator();
01568     }
01569 
01570     inline RecordType const* Find(KeyType const& pKey) const
01571     {
01572         return mTree.Find(pKey);
01573     }
01574 
01575     inline RecordType* Find(KeyType const& pKey)
01576     {
01577         return mTree.Find(pKey);
01578     }
01579 
01580     inline RecordType const* UpperBound(KeyType const& pKey) const
01581     {
01582         return mTree.UpperBound(pKey);
01583     }
01584 
01585     inline RecordType* UpperBound(KeyType const& pKey)
01586     {
01587         return mTree.UpperBound(pKey);
01588     }
01589 
01590     inline ValueType& operator[](KeyType const& pKey)
01591     {
01592         RecordType* lRecord = Find(pKey);
01593 
01594         if( !lRecord )
01595         {
01596             lRecord = Insert(pKey, ValueType()).mFirst;
01597         }
01598 
01599         return lRecord->GetValue();
01600     }
01601 
01602     inline RecordType const* Minimum() const
01603     {
01604         return mTree.Minimum();
01605     }
01606 
01607     inline RecordType* Minimum()
01608     {
01609         return mTree.Minimum();
01610     }
01611 
01612     inline RecordType const* Maximum() const
01613     {
01614         return mTree.Maximum();
01615     }
01616 
01617     inline RecordType* Maximum()
01618     {
01619         return mTree.Maximum();
01620     }
01621 };
01622 
01623 /*************************************************************************
01624  * class KSet2
01625  *
01626  * Implements a data storage with efficient Find.
01627  *
01628  *************************************************************************/
01629 
01630 
01631 template <typename VALUE_TYPE,
01632           typename KEY_COMPARE_FUNCTOR = KFbxLessCompare<VALUE_TYPE>,
01633           typename ALLOCATOR = KBaseAllocator>
01634 class KSet2
01635 {
01636 protected:
01637     class KValue
01638     {
01639     public:
01640         inline KValue(VALUE_TYPE const& pValue)
01641             : mValue(pValue) {}
01642 
01643         // Cannot modify the value in a set, which would change its ordering in the tree
01644         typedef const VALUE_TYPE KeyType;
01645         typedef const VALUE_TYPE ConstKeyType;
01646         typedef const VALUE_TYPE ValueType;
01647         typedef const VALUE_TYPE ConstValueType;
01648 
01649         inline KeyType& GetKey() const      { return mValue; }
01650         inline ConstKeyType& GetKey()       { return mValue; }
01651 
01652         inline ValueType& GetValue() const  { return mValue; }
01653         inline ConstValueType& GetValue()   { return mValue; }
01654 
01655     protected:
01656         ValueType mValue;
01657     };
01658 
01659     typedef KRedBlackTree<KValue, KEY_COMPARE_FUNCTOR, ALLOCATOR> StorageType;
01660     StorageType mTree;
01661 
01662 
01663 public:
01664     typedef VALUE_TYPE ValueType;
01665     typedef typename StorageType::RecordType        RecordType;
01666     typedef typename StorageType::IteratorType      Iterator;
01667     typedef typename StorageType::ConstIteratorType ConstIterator;
01668 
01669     inline KSet2() {}
01670     inline KSet2(KSet2 const& pSet) : mTree(pSet.mTree) {}
01671     inline ~KSet2() {Clear();}
01672 
01673     inline void Reserve(unsigned int pRecordCount)
01674     {
01675         mTree.Reserve(pRecordCount);
01676     }
01677 
01678     inline int GetSize() const
01679     {
01680         return mTree.GetSize();
01681     }
01682 
01683     inline KPair<RecordType*, bool> Insert(ValueType const& pValue)
01684     {
01685         return mTree.Insert(KValue(pValue));
01686     }
01687 
01688     inline int Remove(ValueType const& pValue)
01689     {
01690         return mTree.Remove(pValue);
01691     }
01692 
01693     inline void Clear()
01694     {
01695         mTree.Clear();
01696     }
01697 
01698     inline bool Empty() const
01699     {
01700         return mTree.Empty();
01701     }
01702 
01703     Iterator Begin()
01704     {
01705         return Iterator(Minimum());
01706     }
01707 
01708     Iterator End()
01709     {
01710         return Iterator();
01711     }
01712 
01713     ConstIterator Begin() const
01714     {
01715         return ConstIterator(Minimum());
01716     }
01717 
01718     ConstIterator End() const
01719     {
01720         return ConstIterator();
01721     }
01722 
01723     inline RecordType const* Find(ValueType const& pValue) const
01724     {
01725         return mTree.Find(pValue);
01726     }
01727 
01728     inline RecordType* Find(ValueType const& pValue)
01729     {
01730         return mTree.Find(pValue);
01731     }
01732 
01733     inline RecordType const* Minimum() const
01734     {
01735         return mTree.Minimum();
01736     }
01737 
01738     inline RecordType* Minimum()
01739     {
01740         return mTree.Minimum();
01741     }
01742 
01743     inline RecordType const* Maximum() const
01744     {
01745         return mTree.Maximum();
01746     }
01747 
01748     inline RecordType* Maximum()
01749     {
01750         return mTree.Maximum();
01751     }
01752 
01753     inline bool operator==(const KSet2<VALUE_TYPE, KEY_COMPARE_FUNCTOR, ALLOCATOR>& pOther) const
01754     {
01755         return (this == &pOther) || (mTree == pOther.mTree);
01756     }
01757 
01758     inline bool operator != (const KSet2<VALUE_TYPE, KEY_COMPARE_FUNCTOR, ALLOCATOR>& pOther) const
01759     {
01760         return !(*this == pOther);
01761     }
01762 
01763     inline KSet2 Union(const KSet2 & pOther) const
01764     {
01765         KSet2 lReturn;
01766         ConstIterator lBegin = Begin();
01767         for (; lBegin != End(); ++lBegin)
01768         {
01769             if (pOther.Find(lBegin->GetValue()) != NULL)
01770                 lReturn.Insert(lBegin->GetValue());
01771         }
01772         return lReturn;
01773     }
01774 };
01775 #include <fbxfilesdk/fbxfilesdk_nsend.h>
01776 
01777 #endif // FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KMAP_H
01778