//+------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation, 1992 - 1996 // // File: hash.hxx // // Contents: Template for a hash table that maps strings to data // //-------------------------------------------------------------------------- #pragma once const MAX_TAG_LENGTH = 50; // Max length of any hashed string const HASH_TABLE_SIZE = 97; // Size of hash table //+------------------------------------------------------------------------- // // Class: CHashTableEntry // // Purpose: An entry of hash table // //-------------------------------------------------------------------------- templateclass CHashTableEntry { public: CHashTableEntry( WCHAR *pwszName, T data ); WCHAR * GetName() { return _wszName; } T GetData() { return _data; } CHashTableEntry * GetNextHashEntry() { return _pHashEntryNext; } void SetNextHashEntry(CHashTableEntry *pEntry) { _pHashEntryNext = pEntry; } private: WCHAR _wszName[MAX_TAG_LENGTH]; // Char name T _data; // Data CHashTableEntry * _pHashEntryNext; // Link to next entry }; //+------------------------------------------------------------------------- // // Class: CHashTable // // Purpose: Hash table for mapping strings to data // // Note: As these are static hence global objects, don't make them // unwindable. // //-------------------------------------------------------------------------- templateclass CHashTable { public: CHashTable( BOOL fCaseInsensitive = TRUE ); ~CHashTable(); void Add( WCHAR *pwszName, T data ); BOOL Lookup( WCHAR *pwcInputBuf, unsigned uLen, T& data ); private: unsigned Hash( WCHAR *pwszName, unsigned cLen ); BOOL _fCaseInsensitive; CHashTableEntry * _aHashTable[HASH_TABLE_SIZE]; // Actual hash table }; //+------------------------------------------------------------------------- // // Method: CHashTableEntry::CHashTableEntry // // Synopsis: Constructor // //-------------------------------------------------------------------------- templateCHashTableEntry::CHashTableEntry( WCHAR *pwszName, T data ) : _data(data), _pHashEntryNext(0) { Win4Assert( wcslen(pwszName) + 1 < MAX_TAG_LENGTH ); wcscpy( _wszName, pwszName ); } //+------------------------------------------------------------------------- // // Method: CHashTable::CHashTable // // Synopsis: Constructor // //-------------------------------------------------------------------------- templateCHashTable::CHashTable( BOOL fCaseInsensitive ) : _fCaseInsensitive( fCaseInsensitive ) { for (unsigned i=0; iCHashTable::~CHashTable() { for ( unsigned i=0; i *pHashEntry = _aHashTable[i]; while ( pHashEntry != 0 ) { CHashTableEntry *pHashEntryNext = pHashEntry->GetNextHashEntry(); delete pHashEntry; pHashEntry = pHashEntryNext; } } } //+------------------------------------------------------------------------- // // Method: CHashTable::Add // // Synopsis: Add a special char -> data mapping // // Arguments: [pwszName] -- the special char // [data] -- the data // //-------------------------------------------------------------------------- templatevoid CHashTable::Add( WCHAR *pwszName, T data ) { #if DBG == 1 // // Check for duplicate entries // T existingData; BOOL fFound = Lookup( pwszName, wcslen(pwszName), existingData ); Win4Assert( !fFound ); #endif CHashTableEntry *pHashEntry = new CHashTableEntry( pwszName, data ); unsigned uHashValue = Hash( pwszName, wcslen(pwszName) ); pHashEntry->SetNextHashEntry( _aHashTable[uHashValue] ); _aHashTable[uHashValue] = pHashEntry; } //+------------------------------------------------------------------------- // // Method: CHashTable::Lookup // // Synopsis: Return the mapping corresponding to given string // // Arguments: [pwcInputBuf] -- Input buffer // [uLen] -- Length of input (not \0 terminated) // [data] -- Data returned here // // Returns: True if a mapping was found in the hash table // //-------------------------------------------------------------------------- templateBOOL CHashTable::Lookup( WCHAR *pwcInputBuf, unsigned uLen, T& data ) { unsigned uHashValue = Hash( pwcInputBuf, uLen ); Win4Assert( uHashValue < HASH_TABLE_SIZE ); for ( CHashTableEntry *pHashEntry = _aHashTable[uHashValue]; pHashEntry != 0; pHashEntry = pHashEntry->GetNextHashEntry() ) { int i; if ( _fCaseInsensitive ) i = _wcsnicmp( pwcInputBuf, pHashEntry->GetName(), uLen ); else i = wcsncmp( pwcInputBuf, pHashEntry->GetName(), uLen ); if ( 0 == i ) { data = pHashEntry->GetData(); return TRUE; } } return FALSE; } //+------------------------------------------------------------------------- // // Method: CHashTable::Hash // // Synopsis: Implements the hash function // // Arguments: [pwszName] -- name to hash // [cLen] -- length of pszName (it is not null terminated) // // Returns: Position of chained list in hash table // //-------------------------------------------------------------------------- templateunsigned CHashTable::Hash( WCHAR *pwszName, unsigned cLen ) { for ( ULONG uHashValue=0; cLen>0; pwszName++ ) { uHashValue = toupper(*pwszName) + 31 * uHashValue; cLen--; } return uHashValue % HASH_TABLE_SIZE; }