//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: scmhash.cxx // // Contents: Class definitions used for SCM hash table. // // History: 20-Jan-93 Ricksa Created from map_kv.cpp // // Notes: The reason for creating this file rather than using the // original class is that the SCM has different memory allocation // needs depending on whether it is built for Win95 or NT. // //-------------------------------------------------------------------------- #include "act.hxx" //+------------------------------------------------------------------------- // // Member: CScmHashEntry::~CScmHashEntry // // Synopsis: Clean up hash entry // // History: 16-Feb-96 Ricksa Created // //-------------------------------------------------------------------------- CScmHashEntry::~CScmHashEntry(void) { // Just exists hopefully to save some space } //+------------------------------------------------------------------------- // // Member: CScmHashTable::~CScmHashTable // // Synopsis: Free resources held by the hash table // // Algorithm: For each hash bucket, delete all member of the collison // list. // // History: 16-Feb-95 Ricksa Created // //-------------------------------------------------------------------------- CScmHashTable::~CScmHashTable(void) { // Free all the objects in the table. // Loop through each hash bucket for (DWORD i = 0; i < _ndwHashTableSize; i++) { // For each entry in the hash bucket list delete it. CScmHashEntry *pshe = _apsheHashTable[i]; while (pshe != NULL) { CScmHashEntry *psheNext = pshe->GetNext(); delete pshe; pshe = psheNext; } } // Free the table itself PrivMemFree (_apsheHashTable); } //+------------------------------------------------------------------------- // // Member: CScmHashTable::Lookup // // Synopsis: Look up entry by hash and key // // Arguments: [dwHash] - hash value to use // [pKey] - key to use // [cbKey] - count of bytes in the key // // Returns: NULL - no matching entry was found // Pointer to first matching entry found // // Algorithm: If there is an entry for the hash bucket, search // through the collision entries for the first entry // that matches. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- CScmHashEntry * CScmHashTable::Lookup( DWORD dwHash, LPVOID pKey, UINT cbKey) const { CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::Lookup " "( %lx , %p , %lx )\n", this, dwHash, pKey, cbKey)); CScmHashEntry *psheFound = NULL; // Are there any entries for this bucket? if (_apsheHashTable[dwHash] != NULL) { CScmHashEntry *psheToSearch = _apsheHashTable[dwHash]; // Loop searching for a match do { if (psheToSearch->IsEqual(pKey, cbKey)) { psheFound = psheToSearch; break; } } while ((psheToSearch = psheToSearch->GetNext()) != NULL); } CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::Lookup ( %p )\n", this, psheFound)); return psheFound; } //+------------------------------------------------------------------------- // // Member: CScmHashTable::SetAt // // Synopsis: Add a new entry // // Arguments: [dwHash] - hash value to use // [psheToAdd] - hash entry to add // // Algorithm: If there are no entries for the bucket, make the bucket // point to this entry. Otherwise, put this entry on the // end of the list of collisions. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- void CScmHashTable::SetAt( DWORD dwHash, CScmHashEntry *psheToAdd) { CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::SetAt " "( %lx , %p )\n", this, dwHash, psheToAdd)); // Are there entries that has to this bucket? if (_apsheHashTable[dwHash] != NULL) { // Yes -- then put this one on the end of the list CScmHashEntry *psheToSearch = _apsheHashTable[dwHash]; CScmHashEntry *psheLast; do { psheLast = psheToSearch; } while ((psheToSearch = psheToSearch->GetNext()) != NULL); psheLast->SetNext(psheToAdd); } else { // No entries on the list so put this one first _apsheHashTable[dwHash] = psheToAdd; } _ndwCount++; CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::SetAt \n", this)); } //+------------------------------------------------------------------------- // // Member: CScmHashTable::RemoveEntry // // Synopsis: Remove an entry from the list // // Arguments: [dwHash] - hash value to use // [psheToRemove] - hash entry to add // // Returns: TRUE - entry removed. // FALSE - no such entry found // // Algorithm: If bucket is not empty, if this is the first entry replace // it with its next. Otherwise, loop through the list searching // for the entry and make its previous point to the current // one's next. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- BOOL CScmHashTable::RemoveEntry( DWORD dwHash, CScmHashEntry *psheToRemove) { CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::RemoveEntry " "( %lx , %p )\n", this, dwHash, psheToRemove)); BOOL fFound = FALSE; // Are there any entries for this bucket? if (_apsheHashTable[dwHash] != NULL) { CScmHashEntry *psheToSearch = _apsheHashTable[dwHash]; CScmHashEntry *pshePrev = NULL; while (psheToSearch != NULL) { if (psheToSearch == psheToRemove) { if (pshePrev == NULL) { // First entry matches so update the head of the list _apsheHashTable[dwHash] = psheToSearch->GetNext(); } else { // Found entry in the middle of the list so delete // the previous item's next pointer pshePrev->SetNext(psheToSearch->GetNext()); } // Tell the caller we found the item fFound = TRUE; break; } pshePrev = psheToSearch; psheToSearch = psheToSearch->GetNext(); } if (fFound) { _ndwCount--; } } CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::RemoveEntry ( %lx )\n", this, fFound)); return fFound; } //+------------------------------------------------------------------------- // // Member: CScmHashIter::FindNextBucketWithEntry // // Synopsis: Find next hash bucket that has an entry // // Returns: Entry for bucket or NULL if there are none/ // // Algorithm: Beginning with the current bucket loop through the list // of buckets till one is not null or there are no more // buckets. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- CScmHashEntry *CScmHashIter::FindNextBucketWithEntry(void) { CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::FindNextBucketWithEntry\n", this)); for (; _dwBucket < _psht->_ndwHashTableSize; _dwBucket++) { if ((_psheNext =_psht->_apsheHashTable[_dwBucket]) != NULL) { break; } } // Point to the next bucket _dwBucket++; CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::FindNextBucketWithEntry " "( %p )\n", this, _psheNext)); return _psheNext; } //+------------------------------------------------------------------------- // // Member: CScmHashIter::GetNext // // Synopsis: Find next hash bucket that has an entry // // Returns: Next entry in the iteration // // Algorithm: Get the next pointer from the object and then update // the next pointer if there are still entries to be // iterated. // // History: 20-Jan-95 Ricksa Created // //-------------------------------------------------------------------------- CScmHashEntry *CScmHashIter::GetNext(void) { CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::GetNext \n", this)); CScmHashEntry *psheToReturn = _psheNext; // Search for the next entry to return if (_psheNext != NULL) { _psheNext = _psheNext->GetNext(); if (_psheNext == NULL) { FindNextBucketWithEntry(); } } CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::GetNext " "( %p )\n", this, psheToReturn)); return psheToReturn; }