#pragma once #include ////////////////////////////////////////////////////////////////////////////// // Hash table entry. ////////////////////////////////////////////////////////////////////////////// template class THashTableEntry { public: DWORD _dwSig; HRESULT _hr; T _tKey; V _vItem; DWORD _dwHash; THashTableEntry(T& tKey, V& vItem); ~THashTableEntry(); }; //----------------------------------------------------------------------------- // THashTableEntry ctor //----------------------------------------------------------------------------- template THashTableEntry::THashTableEntry(T& tKey, V& vItem) : _hr(S_OK), _dwSig('RTNE') { IF_FAILED_EXIT(_tKey.Assign(tKey)); IF_FAILED_EXIT(_vItem.Assign(vItem)); IF_FAILED_EXIT(_tKey.GetHash(&_dwHash, T::CaseSensitive)); exit: return; } //----------------------------------------------------------------------------- // THashTableEntry dtor //----------------------------------------------------------------------------- template THashTableEntry::~THashTableEntry() { } ////////////////////////////////////////////////////////////////////////////// // Hash table class ////////////////////////////////////////////////////////////////////////////// template class THashTable { public: THashTable(); THashTable(DWORD nSlots); ~THashTable(); HRESULT Init(DWORD nSlots); HRESULT Destruct(); HRESULT Insert(T& tKey, V& vItem); HRESULT Retrieve(T& tKey, V** ppvItem); private: HRESULT _hr; DWORD _dwSig; DWORD _nSlots; TList *> *_pListArray; }; //----------------------------------------------------------------------------- // THashTable ctor //----------------------------------------------------------------------------- template THashTable::THashTable() : _hr(S_OK), _dwSig('HSAH'), _nSlots(0), _pListArray(NULL) {} //----------------------------------------------------------------------------- // THashTable ctor //----------------------------------------------------------------------------- template THashTable::THashTable(DWORD nSlots) : THashTable() { Init(nSlots); } //----------------------------------------------------------------------------- // THashTable dtor //----------------------------------------------------------------------------- template THashTable::~THashTable(void) { Destruct(); SAFEDELETEARRAY(_pListArray); } //----------------------------------------------------------------------------- // THashTable::Init //----------------------------------------------------------------------------- template HRESULT THashTable::Init(DWORD nSlots) { _nSlots = nSlots; _pListArray = new TList * > [_nSlots]; IF_ALLOC_FAILED_EXIT((_pListArray)); exit: return _hr; } //----------------------------------------------------------------------------- // THashTable::Insert //----------------------------------------------------------------------------- template HRESULT THashTable::Insert(T& tKey, V& vItem) { _hr = S_OK; THashTableEntry *pEntry = new THashTableEntry(tKey, vItem); IF_ALLOC_FAILED_EXIT(pEntry); IF_FALSE_EXIT((pEntry->_hr == S_OK), pEntry->_hr); IF_FAILED_EXIT(_pListArray[(pEntry->_dwHash) % _nSlots].Insert(pEntry)); exit: return _hr; } //----------------------------------------------------------------------------- // THashTable::Retrieve //----------------------------------------------------------------------------- template HRESULT THashTable::Retrieve(T& tKey, V** ppvItem) { _hr = S_OK; DWORD dwHash = 0; BOOL bFound = FALSE; THashTableEntry **ppEntry = 0; tKey.GetHash(&dwHash, T::CaseSensitive); TList_Iter * > Iterator(_pListArray[dwHash % _nSlots]); while (ppEntry = Iterator.Next()) { if (dwHash != ((*ppEntry)->_dwHash)) continue; IF_FAILED_EXIT(tKey.CompareString((*ppEntry)->_tKey)); if (_hr == S_OK) { bFound = TRUE; break; } } exit: *ppvItem = bFound ? &((*ppEntry)->_vItem) : NULL; _hr = bFound ? S_OK : S_FALSE; return _hr; } //----------------------------------------------------------------------------- // THashTable::Destruct //----------------------------------------------------------------------------- template HRESULT THashTable::Destruct() { for (DWORD i = 0; i < _nSlots; i++) _pListArray[i].Destruct(); return S_OK; }