fbxsdk/core/base/fbxhashmap.h Source File
 
 
 
fbxsdk/core/base/fbxhashmap.h
Go to the documentation of this file.
00001 /****************************************************************************************
00002  
00003    Copyright (C) 2013 Autodesk, Inc.
00004    All rights reserved.
00005  
00006    Use of this software is subject to the terms of the Autodesk license agreement
00007    provided at the time of installation or download, or which otherwise accompanies
00008    this software in either electronic or hard copy form.
00009  
00010 ****************************************************************************************/
00011 
00013 #ifndef _FBXSDK_CORE_BASE_HASHMAP_H_
00014 #define _FBXSDK_CORE_BASE_HASHMAP_H_
00015 
00016 #include <fbxsdk/fbxsdk_def.h>
00017 
00018 #include <fbxsdk/core/base/fbxarray.h>
00019 #include <fbxsdk/core/base/fbxmap.h>
00020 
00021 #include <fbxsdk/fbxsdk_nsbegin.h>
00022 
00023 template<class T> class FbxNoOpDestruct { public: static inline void DoIt(T&) {} };
00024 template<class T> class FbxPtrDestruct  { public: static inline void DoIt(T& v) { FbxDelete(v); v = NULL; } };
00025 
00026 //True if equal, false otherwise
00027 template<class T> class FbxDefaultComparator{ public: static inline bool CompareIt( const T& t1, const T& t2 ) { return t1 == t2; } };
00028 
00044 template< typename KEY, typename VALUE, typename HASH, class Destruct = FbxNoOpDestruct<VALUE>, class Comparator = FbxDefaultComparator<KEY> >
00045 class FbxHashMap
00046 {
00047 public:
00048         typedef KEY KeyType;
00049         typedef VALUE ValueType;
00050         typedef HASH HashFunctorType;
00051 
00052 private:
00053 
00054         class ListItem
00055         {
00056         public:
00057                 ListItem* mNext;
00058                 ValueType mValue;
00059                 KeyType mKey;
00060 
00061                 ListItem()
00062                         :
00063                 mNext(NULL)
00064                 {
00065                 }
00066 
00067         ~ListItem()
00068         {
00069             Destruct::DoIt(mValue);        
00070         }
00071         };
00072 
00073 public:
00077         class Iterator
00078         {
00079         public:
00080 
00081                 typedef ListItem ListItemType;
00082                 typedef FbxPair< KeyType, ValueType > KeyValuePair;
00083 
00087                 Iterator( const Iterator& pOther )
00088                         :
00089                         mMap( pOther.mMap ),
00090                         mBucketIndex( pOther.mBucketIndex ),
00091                         mCurrentItem( pOther.mCurrentItem )
00092                 {
00093 
00094                 }
00095 
00099                 ~Iterator(){};
00100 
00105                 KeyValuePair operator*() const
00106                 {
00107                         KeyValuePair lItem;
00108 
00109                         if( mCurrentItem )
00110                         {
00111                                 lItem.mFirst = mCurrentItem->mKey;
00112                                 lItem.mSecond = mCurrentItem->mValue;
00113                                 return lItem;
00114                         }
00115 
00116                         FBX_ASSERT_NOW("Accessing out of bounds iterator");
00117 
00118                         return lItem;
00119                 }
00120 
00125                 void Next()
00126                 {
00127                         if( !mCurrentItem )
00128                                 return;
00129 
00130                         if( mCurrentItem->mNext )
00131                         {
00132                                 mCurrentItem = mCurrentItem->mNext;
00133                                 return;
00134                         }
00135                         else
00136                         {
00137                                 mBucketIndex++;
00138                                 for( ; mBucketIndex < mMap->mBuckets.GetCount(); ++mBucketIndex )
00139                                 {
00140                                         if( mMap->mBuckets[ mBucketIndex ] )
00141                                         {
00142                                                 mCurrentItem = mMap->mBuckets[ mBucketIndex ];
00143                                                 return;
00144                                         }
00145                                 }
00146                                 
00147                                 if( mBucketIndex >= mMap->mBuckets.GetCount() )
00148                                 {
00149                                         *this = mMap->End();
00150                                         return;
00151                                 }
00152                         }
00153                 }
00154 
00162                 bool operator==( const Iterator& pOther ) const
00163                 {
00164                         return  mCurrentItem == pOther.mCurrentItem && 
00165                                         mBucketIndex == pOther.mBucketIndex &&
00166                                         mMap == pOther.mMap;
00167                 }
00168 
00173                 bool operator!=( const Iterator& pOther ) const
00174                 {
00175                         return !(*this == pOther);
00176                 }
00177 
00183                 Iterator& operator=( const Iterator& pOther )
00184                 {
00185                         this->mBucketIndex = pOther.mBucketIndex;
00186                         this->mMap = pOther.mMap;
00187                         this->mCurrentItem = pOther.mCurrentItem;
00188                         return *this;
00189                 }
00190 
00191     private:
00192                 const FbxHashMap* mMap;         
00193 
00194                 int mBucketIndex;
00195                 ListItemType* mCurrentItem;
00196                 
00197                 Iterator(const FbxHashMap* pMap, int pBucketIndex, ListItemType* pCurrentItem)
00198                         :
00199                         mMap( pMap ),
00200                         mBucketIndex(pBucketIndex),
00201                         mCurrentItem(pCurrentItem)
00202                 {
00203 
00204                 }
00205 
00206                 friend class FbxHashMap;
00207         };
00208         
00213         FbxHashMap( int pBucketSize )
00214         {
00215                 mBuckets.Resize( pBucketSize );
00216         }
00217 
00221     FbxHashMap()
00222     {
00223         mBuckets.Resize(30);
00224     }
00225 
00229         ~FbxHashMap()
00230         {
00231                 Clear();
00232                 mBuckets.Clear();
00233         }
00234 
00238         void Clear()
00239         {
00240                 for( int i = 0; i < mBuckets.GetCount(); ++i)
00241                 {
00242                         if( mBuckets[i] )
00243                         {
00244                                 ListItem* lNext = mBuckets[i]->mNext;
00245                                 while( lNext )
00246                                 {
00247                                         ListItem* lNextNext = lNext->mNext;
00248                                         FbxDelete(lNext);
00249                                         lNext = lNextNext;
00250                                 }
00251 
00252                                 FbxDelete(mBuckets[i]);
00253                                 mBuckets[i] = NULL;
00254                         }
00255                 }
00256         }
00257 
00264         const Iterator Find( const KeyType& pKey ) const
00265         {
00266                 unsigned int lIndex = mHashFunctor(pKey);
00267                 lIndex = lIndex % mBuckets.GetCount();
00268                 ListItem* lItem = mBuckets[lIndex];
00269                 while( lItem )
00270                 {
00271             if( Comparator::CompareIt( lItem->mKey, pKey ) )
00272                         {
00273                                 Iterator lIt( this, lIndex, lItem );
00274                                 return lIt;
00275                         }
00276                         lItem = lItem->mNext;
00277                 }
00278                 
00279                 return End();
00280         }
00281         
00287         VALUE Remove( const KEY& pKey )
00288     {
00289                 unsigned int lIndex = mHashFunctor(pKey);
00290                 lIndex = lIndex % mBuckets.GetCount();
00291                 ListItem* lItem = mBuckets.GetAt(lIndex);
00292         ListItem* lLastItem = NULL;
00293                 
00294         while( lItem )
00295                 {
00296                         if( lItem->mKey == pKey )
00297                         {
00298                 if( lLastItem )
00299                     lLastItem->mNext = lItem->mNext;
00300 
00301                 if( mBuckets.GetAt(lIndex) == lItem ) 
00302                     mBuckets.SetAt(lIndex, lItem->mNext );
00303 
00304                 VALUE lValue = lItem->mValue;
00305                 FbxDelete(lItem);
00306                 
00307                 return lValue;
00308                         }
00309 
00310             lLastItem = lItem;
00311                         lItem = lItem->mNext;
00312                 }
00313                 
00314         return VALUE();
00315     }
00316 
00324         ValueType& operator[]( const KeyType& pKey )
00325         {
00326         unsigned int lIndex = 0;
00327                 Iterator lIt = InternalFind( pKey, lIndex);
00328                 if( lIt != End() )
00329                 {
00330                         return lIt.mCurrentItem->mValue;
00331                 }
00332 
00333                 lIndex = lIndex % mBuckets.GetCount();
00334                 ListItem* lItem = FbxNew< ListItem >();
00335                 lItem->mNext = NULL;
00336                 lItem->mKey = pKey;
00337 
00338                 if( !mBuckets.GetAt(lIndex) )
00339                 {
00340                         mBuckets.SetAt(lIndex, lItem);
00341                 }
00342                 else
00343                 {
00344                         lItem->mNext = mBuckets.GetAt(lIndex);
00345                         mBuckets.SetAt(lIndex, lItem);
00346                 }
00347 
00348                 return lItem->mValue;
00349         }
00350 
00354         Iterator Start() const
00355         {
00356                 for( int i = 0; i < mBuckets.GetCount(); ++i )
00357                 {
00358                         if( mBuckets[i] )
00359                         {
00360                                 Iterator lIt( this, i, mBuckets[i] );
00361                                 return lIt;
00362                         }
00363                 }
00364 
00365                 return End();
00366         }
00367 
00372         Iterator End() const
00373         {
00374                 Iterator lIt( this, 0, NULL );
00375                 return lIt;
00376         }
00377 
00378 private:
00379 
00380     // Avoid calculating the hashvalue twice
00381         const Iterator InternalFind( const KeyType& pKey, unsigned int& pOutCalculatedIndex ) const
00382         {
00383                 pOutCalculatedIndex = mHashFunctor(pKey);
00384                 unsigned int lIndex = pOutCalculatedIndex % mBuckets.GetCount();
00385                 ListItem* lItem = mBuckets[lIndex];
00386                 while( lItem )
00387                 {
00388             if( Comparator::CompareIt( lItem->mKey, pKey ) )
00389                         {
00390                                 Iterator lIt( this, lIndex, lItem );
00391                                 return lIt;
00392                         }
00393                         lItem = lItem->mNext;
00394                 }
00395                 
00396                 return End();
00397         }
00398 
00399 
00400         // not implemented yet!
00401         FbxHashMap( const FbxHashMap& pOther ) {};
00402 
00403         FbxArray<ListItem*> mBuckets;
00404         HashFunctorType mHashFunctor;
00405 
00406         friend class Iterator;
00407 };
00408 
00409 #include <fbxsdk/fbxsdk_nsend.h>
00410 
00411 #endif /* _FBXSDK_CORE_BASE_HASHMAP_H_ */