00001
00002
00003 #ifndef MuscleHashtable_h
00004 #define MuscleHashtable_h
00005
00006 #include "support/MuscleSupport.h"
00007
00008 #ifdef _MSC_VER
00009 # pragma warning(disable: 4786)
00010 #endif
00011
00012 #ifndef MUSCLE_HASHTABLE_DEFAULT_CAPACITY
00013 # define MUSCLE_HASHTABLE_DEFAULT_CAPACITY 7
00014 #endif
00015
00016 BEGIN_NAMESPACE(muscle);
00017
00018
00019 static const uint32 MUSCLE_HASHTABLE_INVALID_HASH_CODE = (uint32)-1;
00020
00026 template <class T> class HashFunctor
00027 {
00028 public:
00030 uint32 operator()(const T x) const {return (uint32)((unsigned long)x);}
00031 };
00032
00033 template <class KeyType, class ValueType, class HashFunctorType> class Hashtable;
00034
00038 enum {
00039 HTIT_FLAG_BACKWARDS = (1<<0),
00040 HTIT_FLAG_NOREGISTER = (1<<1),
00041 NUM_HTIT_FLAGS = 2
00042 };
00043
00080 template <class KeyType, class ValueType, class HashFunctorType = HashFunctor<KeyType> > class HashtableIterator
00081 {
00082 public:
00089 HashtableIterator();
00090
00092 HashtableIterator(const HashtableIterator<KeyType, ValueType, HashFunctorType> & rhs);
00093
00098 HashtableIterator(const Hashtable<KeyType, ValueType, HashFunctorType> & table, uint32 flags = 0);
00099
00106 HashtableIterator(const Hashtable<KeyType, ValueType, HashFunctorType> & table, const KeyType & startAt, uint32 flags);
00107
00109 ~HashtableIterator();
00110
00112 HashtableIterator<KeyType, ValueType, HashFunctorType> & operator=(const HashtableIterator<KeyType, ValueType, HashFunctorType> & rhs);
00113
00115 void operator++(int) {(void) GetNextKey(); (void) GetNextValue();}
00116
00118 void operator--(int) {bool b = IsBackwards(); SetBackwards(!b); (void) GetNextKey(); (void) GetNextValue(); SetBackwards(b);}
00119
00121 bool HasMoreKeys() const {return ((_nextKeyCookie != NULL)||((_owner)&&(_owner->HasItems())&&(_flags&HTIT_INTERNAL_FLAG_RESTARTKEY)));}
00122
00131 const KeyType & GetKey() const {return *PeekNextKey();}
00132
00141 ValueType & GetValue() const {return *PeekNextValue();}
00142
00148 status_t GetNextKey(KeyType & setNextKey);
00149
00155 status_t GetNextKey(const KeyType * & setNextKeyPtr);
00156
00162 const KeyType * GetNextKey();
00163
00169 status_t PeekNextKey(KeyType & setKey) const;
00170
00176 status_t PeekNextKey(const KeyType * & setKey) const;
00177
00183 const KeyType * PeekNextKey() const;
00184
00186 bool HasMoreValues() const {return ((_nextValueCookie != NULL)||((_owner)&&(_owner->HasItems())&&(_flags & HTIT_INTERNAL_FLAG_RESTARTVALUE)));}
00187
00193 status_t GetNextValue(ValueType & setNextValue);
00194
00200 status_t GetNextValue(ValueType * & setValuePtr);
00201
00207 status_t GetNextValue(const ValueType * & setValuePtr);
00208
00214 ValueType * GetNextValue();
00215
00221 status_t PeekNextValue(ValueType & setValue) const;
00222
00228 status_t PeekNextValue(const ValueType * & setValue) const;
00229
00235 status_t PeekNextValue(ValueType * & setValue) const;
00236
00242 ValueType * PeekNextValue() const;
00243
00249 status_t GetNextKeyAndValue(KeyType & setKey, ValueType & setValue);
00250
00256 status_t GetNextKeyAndValue(KeyType & setKey, ValueType * & setValuePtr);
00257
00263 status_t GetNextKeyAndValue(KeyType & setKey, const ValueType * & setValuePtr);
00264
00270 status_t GetNextKeyAndValue(const KeyType * & setKeyPtr, ValueType & setValue);
00271
00277 status_t GetNextKeyAndValue(const KeyType * & setKeyPtr, ValueType * & setValuePtr);
00278
00284 status_t GetNextKeyAndValue(const KeyType * & setKeyPtr, const ValueType * & setValuePtr);
00285
00287 uint32 GetFlags() const {return _flags;}
00288
00293 void SetBackwards(bool backwards) {if (backwards) _flags |= HTIT_FLAG_BACKWARDS; else _flags &= ~HTIT_FLAG_BACKWARDS;}
00294
00298 bool IsBackwards() const {return ((_flags & HTIT_FLAG_BACKWARDS) != 0);}
00299
00300 private:
00301 enum {
00302 HTIT_INTERNAL_FLAG_RESTARTKEY = (1<<31),
00303 HTIT_INTERNAL_FLAG_RESTARTVALUE = (1<<30)
00304 };
00305
00307 friend class Hashtable<KeyType, ValueType, HashFunctorType>;
00308
00309 void * _scratchSpace[2];
00310
00311 void * _nextKeyCookie;
00312 void * _nextValueCookie;
00313 uint32 _flags;
00314
00315 HashtableIterator<KeyType, ValueType, HashFunctorType> * _prevIter;
00316 HashtableIterator<KeyType, ValueType, HashFunctorType> * _nextIter;
00317 const Hashtable<KeyType, ValueType, HashFunctorType> * _owner;
00318 };
00319
00334 template <class KeyType, class ValueType, class HashFunctorType = HashFunctor<KeyType> > class Hashtable
00335 {
00336 public:
00346 typedef int (*KeyCompareFunc)(const KeyType& key1, const KeyType& key2, void * cookie);
00347
00357 typedef int (*ValueCompareFunc)(const ValueType& key1, const ValueType& key2, void * cookie);
00358
00360 enum {
00361 AUTOSORT_DISABLED = 0,
00362 AUTOSORT_BY_KEY,
00363 AUTOSORT_BY_VALUE
00364 };
00365
00367 Hashtable();
00368
00373 explicit Hashtable(uint32 initialCapacity);
00374
00376 Hashtable(const Hashtable<KeyType,ValueType,HashFunctorType> & rhs);
00377
00379 ~Hashtable();
00380
00384 Hashtable<KeyType,ValueType,HashFunctorType> & operator= (const Hashtable<KeyType,ValueType,HashFunctorType> & rhs);
00385
00389 bool operator== (const Hashtable<KeyType,ValueType,HashFunctorType> & rhs) const;
00390
00392 bool operator!= (const Hashtable<KeyType,ValueType,HashFunctorType> & rhs) const {return !(*this == rhs);}
00393
00399 status_t CopyFrom(const Hashtable<KeyType,ValueType,HashFunctorType> & rhs);
00400
00402 uint32 GetNumItems() const {return _count;}
00403
00405 bool IsEmpty() const {return (_count == 0);}
00406
00408 bool HasItems() const {return (_count > 0);}
00409
00411 bool ContainsKey(const KeyType& key) const {return (GetEntry(ComputeHash(key), key) != NULL);}
00412
00414 bool ContainsValue(const ValueType& value) const;
00415
00417 int32 IndexOfKey(const KeyType& key) const;
00418
00427 int32 IndexOfValue(const ValueType& value, bool searchBackwards = false) const;
00428
00434 status_t GetValue(const KeyType& key, ValueType& setValue) const;
00435
00442 ValueType * GetValue(const KeyType & key) const;
00443
00451 status_t GetKey(const KeyType & lookupKey, KeyType & setKey) const;
00452
00460 const KeyType * GetKey(const KeyType & lookupKey) const;
00461
00467 HashtableIterator<KeyType,ValueType,HashFunctorType> GetIterator(uint32 flags = 0) const
00468 {
00469 return HashtableIterator<KeyType,ValueType,HashFunctorType>(*this, flags);
00470 }
00471
00478 HashtableIterator<KeyType,ValueType,HashFunctorType> GetIteratorAt(const KeyType & startAt, uint32 flags = 0) const
00479 {
00480 return HashtableIterator<KeyType,ValueType,HashFunctorType>(*this, startAt, flags);
00481 }
00482
00489 const KeyType * GetKeyAt(uint32 index) const;
00490
00498 status_t GetKeyAt(uint32 index, KeyType & retKey) const;
00499
00509 status_t Put(const KeyType& key, const ValueType& value, ValueType & setPreviousValue, bool * optSetReplaced = NULL) {return (PutAux(ComputeHash(key), key, value, &setPreviousValue, optSetReplaced) != NULL) ? B_NO_ERROR : B_ERROR;}
00510
00518 status_t Put(const KeyType& key, const ValueType& value) {return (PutAux(ComputeHash(key), key, value, NULL, NULL) != NULL) ? B_NO_ERROR : B_ERROR;}
00519
00526 status_t Put(const Hashtable<KeyType, ValueType, HashFunctorType> & pairs);
00527
00532 status_t Remove(const KeyType& key) {return RemoveAux(key, NULL);}
00533
00539 status_t Remove(const KeyType& key, ValueType & setRemovedValue) {return RemoveAux(key, &setRemovedValue);}
00540
00545 uint32 Remove(const Hashtable<KeyType, ValueType, HashFunctorType> & pairs);
00546
00550 status_t RemoveFirst() {return _iterHead ? RemoveEntry(_iterHead, NULL) : B_ERROR;}
00551
00557 status_t RemoveFirst(KeyType & setRemovedKey)
00558 {
00559 if (_iterHead == NULL) return B_ERROR;
00560 setRemovedKey = _iterHead->_key;
00561 return RemoveEntry(_iterHead, NULL);
00562 }
00563
00570 status_t RemoveFirst(KeyType & setRemovedKey, ValueType & setRemovedValue)
00571 {
00572 if (_iterHead == NULL) return B_ERROR;
00573 setRemovedKey = _iterHead->_key;
00574 return RemoveEntry(_iterHead, &setRemovedValue);
00575 }
00576
00580 status_t RemoveLast() {return _iterTail ? RemoveEntry(_iterTail, NULL) : B_ERROR;}
00581
00587 status_t RemoveLast(KeyType & setRemovedKey)
00588 {
00589 if (_iterTail == NULL) return B_ERROR;
00590 setRemovedKey = _iterTail->_key;
00591 return RemoveEntry(_iterTail, NULL);
00592 }
00593
00600 status_t RemoveLast(KeyType & setRemovedKey, ValueType & setRemovedValue)
00601 {
00602 if (_iterTail == NULL) return B_ERROR;
00603 setRemovedKey = _iterTail->_key;
00604 return RemoveEntry(_iterTail, &setRemovedValue);
00605 }
00606
00611 void Clear(bool releaseCachedData = false);
00612
00625 status_t Reposition(const KeyType & key);
00626
00639 void SetAutoSortMode(int mode, bool sortNow = true) {_autoSortMode = mode; if (sortNow) (void) Sort();}
00640
00642 int GetAutoSortMode() const {return _autoSortMode;}
00643
00649 void SetCompareCookie(void * cookie) {_compareCookie = cookie;}
00650
00652 void * GetCompareCookie() const {return _compareCookie;}
00653
00661 void SetKeyCompareFunction(KeyCompareFunc func) {_userKeyCompareFunc = func;}
00662
00664 KeyCompareFunc GetKeyCompareFunction() const {return _userKeyCompareFunc;}
00665
00671 void SetValueCompareFunction(ValueCompareFunc func) {_userValueCompareFunc = func;}
00672
00674 ValueCompareFunc GetValueCompareFunction() const {return _userValueCompareFunc;}
00675
00682 void SwapContents(Hashtable<KeyType,ValueType,HashFunctorType> & swapMe);
00683
00691 status_t MoveToFront(const KeyType & moveMe);
00692
00700 status_t MoveToBack(const KeyType & moveMe);
00701
00712 status_t MoveToBefore(const KeyType & moveMe, const KeyType & toBeforeMe);
00713
00724 status_t MoveToBehind(const KeyType & moveMe, const KeyType & toBehindMe);
00725
00733 status_t MoveToTable(const KeyType & moveMe, Hashtable<KeyType, ValueType> & toTable);
00734
00742 status_t CopyToTable(const KeyType & copyMe, Hashtable<KeyType, ValueType> & toTable) const;
00743
00755 status_t Sort() {return SortByAux((_autoSortMode != AUTOSORT_BY_VALUE) ? _userKeyCompareFunc : NULL, (_autoSortMode != AUTOSORT_BY_KEY) ? _userValueCompareFunc : NULL, _compareCookie);}
00756
00762 void SortByKey(KeyCompareFunc func, void * optCompareCookie = NULL) {(void) SortByAux(func, NULL, optCompareCookie);}
00763
00769 void SortByValue(ValueCompareFunc func, void * optCompareCookie = NULL) {(void) SortByAux(NULL, func, optCompareCookie);}
00770
00772 status_t Get(const KeyType& key, ValueType& setValue) const {return GetValue(key, setValue);}
00773
00775 ValueType * Get(const KeyType & key) const {return GetValue(key);}
00776
00785 ValueType * GetOrPut(const KeyType & key, const ValueType & defValue)
00786 {
00787 uint32 hash = ComputeHash(key);
00788 HashtableEntry * e = GetEntry(hash, key);
00789 if (e == NULL) e = PutAux(hash, key, defValue, NULL, NULL);
00790 return e ? &e->_value : NULL;
00791 }
00792
00801 ValueType * GetOrPut(const KeyType & key)
00802 {
00803 uint32 hash = ComputeHash(key);
00804 HashtableEntry * e = GetEntry(hash, key);
00805 if (e == NULL) e = PutAux(hash, key, ValueType(), NULL, NULL);
00806 return e ? &e->_value : NULL;
00807 }
00808
00815 ValueType GetWithDefault(const KeyType & key) const
00816 {
00817 const ValueType * v = Get(key);
00818 return v ? *v : ValueType();
00819 }
00820
00831 ValueType GetWithDefault(const KeyType & key, const ValueType & defaultValue) const
00832 {
00833 const ValueType * v = Get(key);
00834 return v ? *v : defaultValue;
00835 }
00836
00845 ValueType * PutAndGet(const KeyType & key, const ValueType & value = ValueType())
00846 {
00847 HashtableEntry * e = PutAux(ComputeHash(key), key, value, NULL, NULL);
00848 return e ? &e->_value : NULL;
00849 }
00850
00859 ValueType * PutIfNotAlreadyPresent(const KeyType & key, const ValueType & value)
00860 {
00861 uint32 hash = ComputeHash(key);
00862 HashtableEntry * e = GetEntry(hash, key);
00863 if (e) return NULL;
00864 else
00865 {
00866 e = PutAux(hash, key, value, NULL, NULL);
00867 return e ? &e->_value : NULL;
00868 }
00869 }
00870
00879 ValueType * PutIfNotAlreadyPresent(const KeyType & key)
00880 {
00881 uint32 hash = ComputeHash(key);
00882 HashtableEntry * e = GetEntry(hash, key);
00883 if (e) return NULL;
00884 else
00885 {
00886 e = PutAux(hash, key, ValueType(), NULL, NULL);
00887 return e ? &e->_value : NULL;
00888 }
00889 }
00890
00892 const KeyType * GetFirstKey() const {return _iterHead ? &_iterHead->_key : NULL;}
00893
00895 const KeyType * GetLastKey() const {return _iterTail ? &_iterTail->_key : NULL;}
00896
00898 ValueType * GetFirstValue() const {return _iterHead ? &_iterHead->_value : NULL;}
00899
00901 ValueType * GetLastValue() const {return _iterTail ? &_iterTail->_value : NULL;}
00902
00912 status_t EnsureSize(uint32 newTableSize);
00913
00918 uint32 GetNumAllocatedSlots() const {return _tableSize;}
00919
00920 private:
00922 friend class HashtableIterator<KeyType, ValueType, HashFunctorType>;
00923
00924 void InitializeIterator(HashtableIterator<KeyType,ValueType,HashFunctorType> & iter) const
00925 {
00926 RegisterIterator(&iter);
00927 iter._nextKeyCookie = iter._nextValueCookie = (iter._flags & HTIT_FLAG_BACKWARDS) ? _iterTail : _iterHead;
00928 }
00929
00930 void InitializeIteratorAt(HashtableIterator<KeyType,ValueType,HashFunctorType> & iter, const KeyType & startAt) const
00931 {
00932 RegisterIterator(&iter);
00933 iter._nextKeyCookie = iter._nextValueCookie = GetEntry(ComputeHash(startAt), startAt);
00934 }
00935
00936 class HashtableEntry
00937 {
00938 public:
00939
00940 HashtableEntry() : _hash(MUSCLE_HASHTABLE_INVALID_HASH_CODE), _iterPrev(NULL), _iterNext(NULL)
00941 #ifndef _MSC_VER
00942 , _mapTo(this), _mappedFrom(this)
00943 #endif
00944 {
00945 #ifdef _MSC_VER
00946 _mapTo = this;
00947 _mappedFrom = this;
00948 #endif
00949 }
00950
00951 ~HashtableEntry() {}
00952
00953
00954 void ReturnToFreeList(const KeyType & defaultKey, const ValueType & defaultValue, HashtableEntry ** freeHead)
00955 {
00956 _hash = MUSCLE_HASHTABLE_INVALID_HASH_CODE;
00957 _key = defaultKey;
00958 _value = defaultValue;
00959
00960 _iterPrev = _iterNext = _bucketPrev = NULL;
00961 _bucketNext = *freeHead;
00962 if (_bucketNext) _bucketNext->_bucketPrev = this;
00963 *freeHead = this;
00964 }
00965
00970 HashtableEntry * RemoveFromFreeList(HashtableEntry * freeHead)
00971 {
00972 if (_bucketNext) _bucketNext->_bucketPrev = _bucketPrev;
00973 if (_bucketPrev) _bucketPrev->_bucketNext = _bucketNext;
00974 HashtableEntry * ret = (freeHead == this) ? _bucketNext : freeHead;
00975 _bucketPrev = _bucketNext = NULL;
00976 return ret;
00977 }
00978
00979 void SwapMaps(HashtableEntry * e)
00980 {
00981 muscleSwap(e->_mapTo, _mapTo);
00982 _mapTo->_mappedFrom = this;
00983 e->_mapTo->_mappedFrom = e;
00984 }
00985
00986 inline HashtableEntry * GetMapTo() const {return _mapTo;}
00987 inline HashtableEntry * GetMappedFrom() const {return _mappedFrom;}
00988
00989 static HashtableEntry * CreateEntriesArray(uint32 size)
00990 {
00991 HashtableEntry * ret = newnothrow_array(HashtableEntry,size);
00992 if (ret)
00993 {
00994 HashtableEntry * prev = NULL;
00995 for (uint32 i=0; i<size; i++)
00996 {
00997 HashtableEntry * cur = &ret[i];
00998 cur->_bucketPrev = prev;
00999 if (prev) prev->_bucketNext = cur;
01000 prev = cur;
01001 }
01002 ret[size-1]._bucketNext = NULL;
01003 }
01004 else WARN_OUT_OF_MEMORY;
01005 return ret;
01006 }
01007
01008 uint32 _hash;
01009 KeyType _key;
01010 ValueType _value;
01011 HashtableEntry* _bucketPrev;
01012 HashtableEntry* _bucketNext;
01013 HashtableEntry* _iterPrev;
01014 HashtableEntry* _iterNext;
01015
01016 private:
01017 HashtableEntry* _mapTo;
01018 HashtableEntry* _mappedFrom;
01019 };
01020
01021 private:
01022
01023 HashtableEntry * PutAux(uint32 hash, const KeyType& key, const ValueType& value, ValueType * optSetPreviousValue, bool * optReplacedFlag);
01024 status_t RemoveAux(uint32 hash, const KeyType& key, ValueType * optSetValue)
01025 {
01026 HashtableEntry * e = GetEntry(hash, key);
01027 return e ? RemoveEntry(e, optSetValue) : B_ERROR;
01028 }
01029 status_t RemoveAux(const KeyType& key, ValueType * optSetValue)
01030 {
01031 HashtableEntry * e = GetEntry(ComputeHash(key), key);
01032 return e ? RemoveEntry(e, optSetValue) : B_ERROR;
01033 }
01034 status_t RemoveEntry(HashtableEntry * e, ValueType * optSetValue);
01035
01036 status_t SortByAux(KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie);
01037 void RepositionAux(HashtableEntry * e);
01038
01039 inline uint32 ComputeHash(const KeyType & key) const
01040 {
01041 uint32 ret = _functor(key);
01042 if (ret == MUSCLE_HASHTABLE_INVALID_HASH_CODE) ret++;
01043 return ret;
01044 }
01045
01046
01047 void InsertSortedIterationEntry(HashtableEntry * e, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueCompareFunc, void * cookie);
01048 void InsertIterationEntry(HashtableEntry * e, HashtableEntry * optBehindThisOne);
01049 void RemoveIterationEntry(HashtableEntry * e);
01050 HashtableEntry * GetEntry(uint32 hash, const KeyType& key) const;
01051 HashtableEntry * GetEntryAt(uint32 idx) const;
01052 bool IsBucketHead(const HashtableEntry * e) const {return ((e->_hash != MUSCLE_HASHTABLE_INVALID_HASH_CODE)&&(_table[e->_hash%_tableSize].GetMapTo() == e));}
01053
01054 int CompareEntries(const HashtableEntry & left, const HashtableEntry & right, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie) const;
01055
01056
01057 void RegisterIterator(HashtableIterator<KeyType,ValueType,HashFunctorType> * iter) const
01058 {
01059 if (iter->_flags & HTIT_FLAG_NOREGISTER) iter->_prevIter = iter->_nextIter = NULL;
01060 else
01061 {
01062
01063 iter->_prevIter = NULL;
01064 iter->_nextIter = _iterList;
01065 if (_iterList) _iterList->_prevIter = iter;
01066 _iterList = iter;
01067 }
01068 }
01069
01070 void UnregisterIterator(HashtableIterator<KeyType,ValueType,HashFunctorType> * iter) const
01071 {
01072 if (iter->_flags & HTIT_FLAG_NOREGISTER) iter->_prevIter = iter->_nextIter = NULL;
01073 else
01074 {
01075 if (iter->_prevIter) iter->_prevIter->_nextIter = iter->_nextIter;
01076 if (iter->_nextIter) iter->_nextIter->_prevIter = iter->_prevIter;
01077 if (iter == _iterList) _iterList = iter->_nextIter;
01078 iter->_prevIter = iter->_nextIter = NULL;
01079 }
01080 }
01081
01082 KeyType * GetKeyFromCookie(void * c) const {return c ? &(((HashtableEntry *)c)->_key) : NULL;}
01083 ValueType * GetValueFromCookie(void * c) const {return c ? &(((HashtableEntry *)c)->_value) : NULL;}
01084
01085 HashtableEntry * GetInitialEntry(uint32 flags) const {return (flags & HTIT_FLAG_BACKWARDS) ? _iterTail : _iterHead;}
01086 HashtableEntry * GetSubsequentEntry(void * entryPtr, uint32 flags) const
01087 {
01088 HashtableEntry * ep = static_cast<HashtableEntry *>(entryPtr);
01089 return ep ? ((flags & HTIT_FLAG_BACKWARDS) ? ep->_iterPrev : ep->_iterNext) : NULL;
01090 }
01091
01092 void MoveToBackAux(HashtableEntry * moveMe)
01093 {
01094 if (moveMe->_iterNext)
01095 {
01096 RemoveIterationEntry(moveMe);
01097 InsertIterationEntry(moveMe, _iterTail);
01098 }
01099 }
01100
01101 void MoveToFrontAux(HashtableEntry * moveMe)
01102 {
01103 if (moveMe->_iterPrev)
01104 {
01105 RemoveIterationEntry(moveMe);
01106 InsertIterationEntry(moveMe, NULL);
01107 }
01108 }
01109
01110 void MoveToBeforeAux(HashtableEntry * moveMe, HashtableEntry * toBeforeMe)
01111 {
01112 if (moveMe->_iterNext != toBeforeMe)
01113 {
01114 RemoveIterationEntry(moveMe);
01115 InsertIterationEntry(moveMe, toBeforeMe->_iterPrev);
01116 }
01117 }
01118
01119 void MoveToBehindAux(HashtableEntry * moveMe, HashtableEntry * toBehindMe)
01120 {
01121 if (moveMe->_iterPrev != toBehindMe)
01122 {
01123 RemoveIterationEntry(moveMe);
01124 InsertIterationEntry(moveMe, toBehindMe);
01125 }
01126 }
01127
01128 uint32 NextPrime(uint32 start) const;
01129
01130 const uint32 _initialCapacity;
01131 uint32 _count;
01132 uint32 _tableSize;
01133
01134 HashtableEntry * _table;
01135 HashtableEntry * _iterHead;
01136 HashtableEntry * _iterTail;
01137
01138 HashtableEntry * _freeHead;
01139
01140 KeyCompareFunc _userKeyCompareFunc;
01141 ValueCompareFunc _userValueCompareFunc;
01142 int _autoSortMode;
01143 void * _compareCookie;
01144
01145 HashFunctorType _functor;
01146
01147 mutable HashtableIterator<KeyType, ValueType, HashFunctorType> * _iterList;
01148 };
01149
01150
01151
01152
01153
01154
01155 template <class KeyType, class ValueType, class HashFunctorType>
01156 Hashtable<KeyType,ValueType,HashFunctorType>::Hashtable()
01157 : _initialCapacity(MUSCLE_HASHTABLE_DEFAULT_CAPACITY), _count(0), _tableSize(MUSCLE_HASHTABLE_DEFAULT_CAPACITY), _table(NULL), _iterHead(NULL), _iterTail(NULL), _freeHead(NULL), _userKeyCompareFunc(NULL), _userValueCompareFunc(NULL), _autoSortMode(AUTOSORT_DISABLED), _compareCookie(NULL), _iterList(NULL)
01158 {
01159
01160 }
01161
01162 template <class KeyType, class ValueType, class HashFunctorType>
01163 Hashtable<KeyType,ValueType,HashFunctorType>::Hashtable(uint32 initialCapacity)
01164 : _initialCapacity(initialCapacity), _count(0), _tableSize(initialCapacity), _table(NULL), _iterHead(NULL), _iterTail(NULL), _freeHead(NULL), _userKeyCompareFunc(NULL), _userValueCompareFunc(NULL), _autoSortMode(AUTOSORT_DISABLED), _compareCookie(NULL), _iterList(NULL)
01165 {
01166
01167 }
01168
01169 template <class KeyType, class ValueType, class HashFunctorType>
01170 Hashtable<KeyType,ValueType,HashFunctorType>::
01171 Hashtable(const Hashtable<KeyType,ValueType,HashFunctorType> & rhs)
01172 : _initialCapacity(rhs._initialCapacity), _count(0), _tableSize(rhs._tableSize), _table(NULL), _iterHead(NULL), _iterTail(NULL), _freeHead(NULL), _userKeyCompareFunc(rhs._userKeyCompareFunc), _userValueCompareFunc(rhs._userValueCompareFunc), _autoSortMode(rhs._autoSortMode), _compareCookie(rhs._compareCookie), _iterList(NULL)
01173 {
01174 *this = rhs;
01175 }
01176
01177 template <class KeyType, class ValueType, class HashFunctorType>
01178 Hashtable<KeyType, ValueType, HashFunctorType> &
01179 Hashtable<KeyType, ValueType, HashFunctorType> ::
01180 operator=(const Hashtable<KeyType, ValueType, HashFunctorType> & rhs)
01181 {
01182 if (this != &rhs)
01183 {
01184 Clear();
01185 if (EnsureSize(rhs.GetNumItems()) == B_NO_ERROR)
01186 {
01187 const HashtableEntry * e = rhs._iterHead;
01188 while(e)
01189 {
01190 (void) PutAux(e->_hash, e->_key, e->_value, NULL, NULL);
01191 e = e->_iterNext;
01192 }
01193 }
01194 }
01195 return *this;
01196 }
01197
01198 template <class KeyType, class ValueType, class HashFunctorType>
01199 status_t
01200 Hashtable<KeyType, ValueType, HashFunctorType> ::
01201 CopyFrom(const Hashtable<KeyType, ValueType, HashFunctorType> & rhs)
01202 {
01203 if (this == &rhs) return B_NO_ERROR;
01204
01205 Clear();
01206 if (EnsureSize(rhs.GetNumItems()) != B_NO_ERROR) return B_ERROR;
01207
01208 const HashtableEntry * e = rhs._iterHead;
01209 while(e)
01210 {
01211 (void) PutAux(e->_hash, e->_key, e->_value, NULL, NULL);
01212 e = e->_iterNext;
01213 }
01214 return B_NO_ERROR;
01215 }
01216
01217 template <class KeyType, class ValueType, class HashFunctorType>
01218 bool
01219 Hashtable<KeyType, ValueType, HashFunctorType> ::
01220 operator==(const Hashtable<KeyType, ValueType, HashFunctorType> & rhs) const
01221 {
01222 if (this == &rhs) return true;
01223 if (GetNumItems() != rhs.GetNumItems()) return false;
01224
01225 const HashtableEntry * e = _iterHead;
01226 while(e)
01227 {
01228 const HashtableEntry * hisE = rhs.GetEntry(e->_hash, e->_key);
01229 if ((hisE == NULL)||(hisE->_value != e->_value)) return false;
01230 e = e->_iterNext;
01231 }
01232 return true;
01233 }
01234
01235 template <class KeyType, class ValueType, class HashFunctorType>
01236 Hashtable<KeyType,ValueType,HashFunctorType>::~Hashtable()
01237 {
01238 Clear(true);
01239 }
01240
01241 template <class KeyType, class ValueType, class HashFunctorType>
01242 bool
01243 Hashtable<KeyType,ValueType,HashFunctorType>::ContainsValue(const ValueType & value) const
01244 {
01245 const HashtableEntry * e = _iterHead;
01246 while(e)
01247 {
01248 if (e->_value == value) return true;
01249 e = e->_iterNext;
01250 }
01251 return false;
01252 }
01253
01254 template <class KeyType, class ValueType, class HashFunctorType>
01255 int32
01256 Hashtable<KeyType,ValueType,HashFunctorType>::IndexOfKey(const KeyType& key) const
01257 {
01258 const HashtableEntry * entry = GetEntry(ComputeHash(key), key);
01259 int32 count = -1;
01260 if (entry)
01261 {
01262 if (entry == _iterTail) count = GetNumItems()-1;
01263 else
01264 {
01265 while(entry)
01266 {
01267 entry = entry->_iterPrev;
01268 count++;
01269 }
01270 }
01271 }
01272 return count;
01273 }
01274
01275 template <class KeyType, class ValueType, class HashFunctorType>
01276 int32
01277 Hashtable<KeyType,ValueType,HashFunctorType>::IndexOfValue(const ValueType& value, bool searchBackwards) const
01278 {
01279 if (searchBackwards)
01280 {
01281 int32 idx = GetNumItems();
01282 const HashtableEntry * entry = _iterTail;
01283 while(entry)
01284 {
01285 --idx;
01286 if (entry->_value == value) return idx;
01287 entry = entry->_iterPrev;
01288 }
01289 }
01290 else
01291 {
01292 int32 idx = 0;
01293 const HashtableEntry * entry = _iterHead;
01294 while(entry)
01295 {
01296 if (entry->_value == value) return idx;
01297 entry = entry->_iterNext;
01298 idx++;
01299 }
01300 }
01301 return -1;
01302 }
01303
01304 template <class KeyType, class ValueType, class HashFunctorType>
01305 const KeyType *
01306 Hashtable<KeyType,ValueType,HashFunctorType>::GetKeyAt(uint32 index) const
01307 {
01308 HashtableEntry * e = GetEntryAt(index);
01309 return e ? &e->_key : NULL;
01310 }
01311
01312 template <class KeyType, class ValueType, class HashFunctorType>
01313 status_t
01314 Hashtable<KeyType,ValueType,HashFunctorType>::GetKeyAt(uint32 index, KeyType & retKey) const
01315 {
01316 HashtableEntry * e = GetEntryAt(index);
01317 if (e)
01318 {
01319 retKey = e->_key;
01320 return B_NO_ERROR;
01321 }
01322 return B_ERROR;
01323 }
01324
01325 template <class KeyType, class ValueType, class HashFunctorType>
01326 status_t
01327 Hashtable<KeyType,ValueType,HashFunctorType>::GetValue(const KeyType& key, ValueType & setValue) const
01328 {
01329 ValueType * ptr = GetValue(key);
01330 if (ptr)
01331 {
01332 setValue = *ptr;
01333 return B_NO_ERROR;
01334 }
01335 else return B_ERROR;
01336 }
01337
01338 template <class KeyType, class ValueType, class HashFunctorType>
01339 ValueType *
01340 Hashtable<KeyType,ValueType,HashFunctorType>::GetValue(const KeyType& key) const
01341 {
01342 HashtableEntry * e = GetEntry(ComputeHash(key), key);
01343 return e ? &e->_value : NULL;
01344 }
01345
01346 template <class KeyType, class ValueType, class HashFunctorType>
01347 const KeyType *
01348 Hashtable<KeyType,ValueType,HashFunctorType>::GetKey(const KeyType& lookupKey) const
01349 {
01350 HashtableEntry * e = GetEntry(ComputeHash(lookupKey), lookupKey);
01351 return e ? &e->_key : NULL;
01352 }
01353
01354 template <class KeyType, class ValueType, class HashFunctorType>
01355 status_t
01356 Hashtable<KeyType,ValueType,HashFunctorType>::GetKey(const KeyType& lookupKey, KeyType & setKey) const
01357 {
01358 const KeyType * ptr = GetKey(lookupKey);
01359 if (ptr)
01360 {
01361 setKey = *ptr;
01362 return B_NO_ERROR;
01363 }
01364 else return B_ERROR;
01365 }
01366
01367 template <class KeyType, class ValueType, class HashFunctorType>
01368 typename Hashtable<KeyType,ValueType,HashFunctorType>::HashtableEntry *
01369 Hashtable<KeyType,ValueType,HashFunctorType>::GetEntry(uint32 hash, const KeyType& key) const
01370 {
01371 if (HasItems())
01372 {
01373 HashtableEntry * e = _table[hash%_tableSize].GetMapTo();
01374 if (IsBucketHead(e))
01375 {
01376
01377 if (_userKeyCompareFunc)
01378 {
01379 while(e)
01380 {
01381 if ((e->_hash == hash)&&(_userKeyCompareFunc(e->_key, key, _compareCookie) == 0)) return e;
01382 e = e->_bucketNext;
01383 }
01384 }
01385 else
01386 {
01387 while(e)
01388 {
01389 if ((e->_hash == hash)&&(e->_key == key)) return e;
01390 e = e->_bucketNext;
01391 }
01392 }
01393 }
01394 }
01395 return NULL;
01396 }
01397
01398 template <class KeyType, class ValueType, class HashFunctorType>
01399 typename Hashtable<KeyType,ValueType,HashFunctorType>::HashtableEntry *
01400 Hashtable<KeyType,ValueType,HashFunctorType>::GetEntryAt(uint32 idx) const
01401 {
01402 HashtableEntry * e = NULL;
01403 if (idx < _count)
01404 {
01405 if (idx < _count/2)
01406 {
01407 e = _iterHead;
01408 while((e)&&(idx--)) e = e->_iterNext;
01409 }
01410 else
01411 {
01412 idx = _count-(idx+1);
01413 e = _iterTail;
01414 while((e)&&(idx--)) e = e->_iterPrev;
01415 }
01416 }
01417 return e;
01418 }
01419
01420 template <class KeyType, class ValueType, class HashFunctorType>
01421 int
01422 Hashtable<KeyType,ValueType,HashFunctorType>::CompareEntries(const HashtableEntry & left, const HashtableEntry & right, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie) const
01423 {
01424 return optValueFunc ? optValueFunc(left._value, right._value, cookie) : (optKeyFunc ? optKeyFunc(left._key, right._key, cookie) : 0);
01425 }
01426
01427
01428 template <class KeyType, class ValueType, class HashFunctorType>
01429 status_t
01430 Hashtable<KeyType,ValueType,HashFunctorType>::SortByAux(KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie)
01431 {
01432 if ((optKeyFunc)||(optValueFunc))
01433 {
01434 if (_iterHead)
01435 {
01436 for (uint32 mergeSize = 1; ; mergeSize *= 2)
01437 {
01438 HashtableEntry * p = _iterHead;
01439 _iterHead = _iterTail = NULL;
01440
01441 uint32 numMerges = 0;
01442 while(p)
01443 {
01444 numMerges++;
01445
01446
01447 HashtableEntry * q = p;
01448 uint32 psize = 0;
01449 for (uint32 i=0; i<mergeSize; i++)
01450 {
01451 psize++;
01452 q = q->_iterNext;
01453 if (!q) break;
01454 }
01455
01456
01457 for (uint32 qsize=mergeSize; ((psize > 0)||((qsize > 0)&&(q))); )
01458 {
01459 HashtableEntry * e;
01460
01461
01462 if (psize == 0) {e = q; q = q->_iterNext; qsize--;}
01463 else if ((qsize == 0)||(!q)) {e = p; p = p->_iterNext; psize--;}
01464 else if (CompareEntries(*p,*q,optKeyFunc,optValueFunc,cookie) <= 0) {e = p; p = p->_iterNext; psize--;}
01465 else {e = q; q = q->_iterNext; qsize--;}
01466
01467
01468 if (_iterTail) _iterTail->_iterNext = e;
01469 else _iterHead = e;
01470 e->_iterPrev = _iterTail;
01471 _iterTail = e;
01472 }
01473
01474 p = q;
01475 }
01476 _iterTail->_iterNext = NULL;
01477 if (numMerges <= 1) return B_NO_ERROR;
01478 }
01479 }
01480 return B_NO_ERROR;
01481 }
01482 return B_ERROR;
01483 }
01484
01485 template <class KeyType, class ValueType, class HashFunctorType>
01486 status_t
01487 Hashtable<KeyType,ValueType,HashFunctorType>::EnsureSize(uint32 requestedSize)
01488 {
01489 if (_tableSize >= requestedSize) return B_NO_ERROR;
01490
01491
01492 {
01493 HashtableIterator<KeyType,ValueType,HashFunctorType> * nextIter = _iterList;
01494 while(nextIter)
01495 {
01496 nextIter->_scratchSpace[0] = nextIter->_scratchSpace[1] = NULL;
01497 nextIter = nextIter->_nextIter;
01498 }
01499 }
01500
01501
01502 Hashtable<KeyType,ValueType,HashFunctorType> biggerTable(NextPrime(muscleMax(_count, requestedSize)));
01503 biggerTable.SetKeyCompareFunction(_userKeyCompareFunc);
01504 biggerTable.SetValueCompareFunction(_userValueCompareFunc);
01505 biggerTable.SetCompareCookie(_compareCookie);
01506 biggerTable.SetAutoSortMode(_autoSortMode);
01507 {
01508 HashtableEntry * next = _iterHead;
01509 while(next)
01510 {
01511 HashtableEntry * hisClone = biggerTable.PutAux(next->_hash, next->_key, next->_value, NULL, NULL);
01512 if (hisClone)
01513 {
01514
01515 HashtableIterator<KeyType,ValueType,HashFunctorType> * nextIter = _iterList;
01516 while(nextIter)
01517 {
01518 if (nextIter->_nextKeyCookie == next) nextIter->_scratchSpace[0] = hisClone;
01519 if (nextIter->_nextValueCookie == next) nextIter->_scratchSpace[1] = hisClone;
01520 nextIter = nextIter->_nextIter;
01521 }
01522 }
01523 else return B_ERROR;
01524
01525 next = next->_iterNext;
01526 }
01527 }
01528
01529
01530 {
01531 HashtableIterator<KeyType,ValueType,HashFunctorType> * temp = _iterList;
01532 _iterList = NULL;
01533 SwapContents(biggerTable);
01534 _iterList = temp;
01535 }
01536
01537
01538 {
01539 HashtableIterator<KeyType,ValueType,HashFunctorType> * nextIter = _iterList;
01540 while(nextIter)
01541 {
01542 nextIter->_nextKeyCookie = nextIter->_scratchSpace[0];
01543 nextIter->_nextValueCookie = nextIter->_scratchSpace[1];
01544 nextIter = nextIter->_nextIter;
01545 }
01546 }
01547
01548 return B_NO_ERROR;
01549 }
01550
01551 template <class KeyType, class ValueType, class HashFunctorType>
01552 void
01553 Hashtable<KeyType,ValueType,HashFunctorType>::SwapContents(Hashtable<KeyType,ValueType,HashFunctorType> & swapMe)
01554 {
01555 muscleSwap(_count, swapMe._count);
01556 muscleSwap(_tableSize, swapMe._tableSize);
01557 muscleSwap(_table, swapMe._table);
01558 muscleSwap(_iterHead, swapMe._iterHead);
01559 muscleSwap(_iterTail, swapMe._iterTail);
01560 muscleSwap(_freeHead, swapMe._freeHead);
01561 muscleSwap(_userKeyCompareFunc, swapMe._userKeyCompareFunc);
01562 muscleSwap(_userValueCompareFunc, swapMe._userValueCompareFunc);
01563 muscleSwap(_autoSortMode, swapMe._autoSortMode);
01564 muscleSwap(_compareCookie, swapMe._compareCookie);
01565 muscleSwap(_iterList, swapMe._iterList);
01566
01567
01568 {
01569 HashtableIterator<KeyType,ValueType,HashFunctorType> * next = _iterList;
01570 while(next)
01571 {
01572 next->_owner = &swapMe;
01573 next = next->_nextIter;
01574 }
01575 }
01576 {
01577 HashtableIterator<KeyType,ValueType,HashFunctorType> * next = swapMe._iterList;
01578 while(next)
01579 {
01580 next->_owner = this;
01581 next = next->_nextIter;
01582 }
01583 }
01584 }
01585
01586 template <class KeyType, class ValueType, class HashFunctorType>
01587 status_t
01588 Hashtable<KeyType,ValueType,HashFunctorType>::CopyToTable(const KeyType & copyMe, Hashtable<KeyType, ValueType> & toTable) const
01589 {
01590 uint32 hash = ComputeHash(copyMe);
01591 const HashtableEntry * e = GetEntry(hash, copyMe);
01592 if (e)
01593 {
01594 if (this == &toTable) return B_NO_ERROR;
01595 if (toTable.PutAux(hash, copyMe, e->_value, NULL, NULL) != NULL) return B_NO_ERROR;
01596 }
01597 return B_ERROR;
01598 }
01599
01600 template <class KeyType, class ValueType, class HashFunctorType>
01601 status_t
01602 Hashtable<KeyType,ValueType,HashFunctorType>::MoveToTable(const KeyType & moveMe, Hashtable<KeyType, ValueType> & toTable)
01603 {
01604 uint32 hash = ComputeHash(moveMe);
01605 const HashtableEntry * e = GetEntry(hash, moveMe);
01606 if (e)
01607 {
01608 if (this == &toTable) return B_NO_ERROR;
01609 if (toTable.PutAux(hash, moveMe, e->_value, NULL, NULL) != NULL) return RemoveAux(e->_hash, moveMe, NULL);
01610 }
01611 return B_ERROR;
01612 }
01613
01614 template <class KeyType, class ValueType, class HashFunctorType>
01615 status_t
01616 Hashtable<KeyType,ValueType,HashFunctorType>::MoveToFront(const KeyType & moveMe)
01617 {
01618 HashtableEntry * e = GetEntry(ComputeHash(moveMe), moveMe);
01619 if (e == NULL) return B_ERROR;
01620 MoveToFrontAux(e);
01621 return B_NO_ERROR;
01622 }
01623
01624 template <class KeyType, class ValueType, class HashFunctorType>
01625 status_t
01626 Hashtable<KeyType,ValueType,HashFunctorType>::MoveToBack(const KeyType & moveMe)
01627 {
01628 HashtableEntry * e = GetEntry(ComputeHash(moveMe), moveMe);
01629 if (e == NULL) return B_ERROR;
01630 MoveToBackAux(e);
01631 return B_NO_ERROR;
01632 }
01633
01634 template <class KeyType, class ValueType, class HashFunctorType>
01635 status_t
01636 Hashtable<KeyType,ValueType,HashFunctorType>::MoveToBefore(const KeyType & moveMe, const KeyType & toBeforeMe)
01637 {
01638 if (HasItems())
01639 {
01640 HashtableEntry * e = GetEntry(ComputeHash(moveMe), moveMe);
01641 HashtableEntry * f = GetEntry(ComputeHash(toBeforeMe), toBeforeMe);
01642 if ((e == NULL)||(f == NULL)||(e == f)) return B_ERROR;
01643 MoveToBeforeAux(e, f);
01644 return B_NO_ERROR;
01645 }
01646 else return B_ERROR;
01647 }
01648
01649 template <class KeyType, class ValueType, class HashFunctorType>
01650 status_t
01651 Hashtable<KeyType,ValueType,HashFunctorType>::MoveToBehind(const KeyType & moveMe, const KeyType & toBehindMe)
01652 {
01653 if (HasItems())
01654 {
01655 HashtableEntry * d = GetEntry(ComputeHash(toBehindMe), toBehindMe);
01656 HashtableEntry * e = GetEntry(ComputeHash(moveMe), moveMe);
01657 if ((d == NULL)||(e == NULL)||(d == e)) return B_ERROR;
01658 MoveToBehindAux(e, d);
01659 return B_NO_ERROR;
01660 }
01661 else return B_ERROR;
01662 }
01663
01664
01665 template <class KeyType, class ValueType, class HashFunctorType>
01666 void
01667 Hashtable<KeyType,ValueType,HashFunctorType>::InsertSortedIterationEntry(HashtableEntry * e, KeyCompareFunc optKeyFunc, ValueCompareFunc optValueFunc, void * cookie)
01668 {
01669 HashtableEntry * insertAfter = _iterTail;
01670 if ((_iterHead)&&((optKeyFunc)||(optValueFunc)))
01671 {
01672
01673 if (CompareEntries(*e, *_iterHead, optKeyFunc, optValueFunc, cookie) < 0) insertAfter = NULL;
01674 else if (CompareEntries(*e, *_iterTail, optKeyFunc, optValueFunc, cookie) < 0)
01675 {
01676 HashtableEntry * prev = _iterHead;
01677 HashtableEntry * next = _iterHead->_iterNext;
01678 while(next)
01679 {
01680 if (CompareEntries(*e, *next, optKeyFunc, optValueFunc, cookie) < 0)
01681 {
01682 insertAfter = prev;
01683 break;
01684 }
01685 else
01686 {
01687 prev = next;
01688 next = next->_iterNext;
01689 }
01690 }
01691 }
01692 }
01693 InsertIterationEntry(e, insertAfter);
01694 }
01695
01696
01697 template <class KeyType, class ValueType, class HashFunctorType>
01698 void
01699 Hashtable<KeyType,ValueType,HashFunctorType>::InsertIterationEntry(HashtableEntry * e, HashtableEntry * optBehindThis)
01700 {
01701 e->_iterPrev = optBehindThis;
01702 e->_iterNext = optBehindThis ? optBehindThis->_iterNext : _iterHead;
01703 if (e->_iterPrev) e->_iterPrev->_iterNext = e;
01704 else _iterHead = e;
01705 if (e->_iterNext) e->_iterNext->_iterPrev = e;
01706 else _iterTail = e;
01707 }
01708
01709
01710 template <class KeyType, class ValueType, class HashFunctorType>
01711 void
01712 Hashtable<KeyType,ValueType,HashFunctorType>::RemoveIterationEntry(HashtableEntry * e)
01713 {
01714
01715 HashtableIterator<KeyTyp