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