00001 #ifndef FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KMAP_H
00002 #define FBXFILESDK_COMPONENTS_KBASELIB_KLIB_KMAP_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
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
00095 RedBack_IteratorType const& operator++()
00096 {
00097 K_ASSERT( mRecord != NULL );
00098
00099 mRecord = mRecord->Successor();
00100
00101 return *this;
00102 }
00103
00104
00105 RedBack_IteratorType operator++(int)
00106 {
00107 RedBack_IteratorType t(*this);
00108 operator++();
00109 return t;
00110 }
00111
00112
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
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
00184 RedBack_ConstIteratorType const& operator++()
00185 {
00186 K_ASSERT( mRecord != NULL );
00187
00188 mRecord = mRecord->Successor();
00189
00190 return *this;
00191 }
00192
00193
00194 RedBack_ConstIteratorType operator++(int)
00195 {
00196 RedBack_ConstIteratorType t(*this);
00197 operator++();
00198 return t;
00199 }
00200
00201
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
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
00523 if( this == &pTree )
00524 return true;
00525
00526 if( GetSize() != pTree.GetSize() )
00527 return false;
00528
00529
00530
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
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
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
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
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
01355
01356 lSibling = Sibling(lParent, lNode);
01357 }
01358
01359
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
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
01406 lSibling = Sibling(lParent, lNode);
01407 K_ASSERT(lSibling != 0);
01408
01409
01410
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
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
01484
01485
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
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
01636
01637
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
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