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