236 lines
6.3 KiB
C++
236 lines
6.3 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1996
|
||
|
//
|
||
|
// File: hash.hxx
|
||
|
//
|
||
|
// Contents: Template for a hash table that maps strings to data <T>
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#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
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>class 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.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>class 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<T> * _aHashTable[HASH_TABLE_SIZE]; // Actual hash table
|
||
|
};
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CHashTableEntry::CHashTableEntry
|
||
|
//
|
||
|
// Synopsis: Constructor
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>CHashTableEntry<T>::CHashTableEntry( WCHAR *pwszName, T data )
|
||
|
: _data(data),
|
||
|
_pHashEntryNext(0)
|
||
|
{
|
||
|
Win4Assert( wcslen(pwszName) + 1 < MAX_TAG_LENGTH );
|
||
|
wcscpy( _wszName, pwszName );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CHashTable::CHashTable
|
||
|
//
|
||
|
// Synopsis: Constructor
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>CHashTable<T>::CHashTable( BOOL fCaseInsensitive ) :
|
||
|
_fCaseInsensitive( fCaseInsensitive )
|
||
|
{
|
||
|
for (unsigned i=0; i<HASH_TABLE_SIZE; i++)
|
||
|
_aHashTable[i] = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CHashTable::~CHashTable
|
||
|
//
|
||
|
// Synopsis: Destructor
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>CHashTable<T>::~CHashTable()
|
||
|
{
|
||
|
for ( unsigned i=0; i<HASH_TABLE_SIZE; i++)
|
||
|
{
|
||
|
CHashTableEntry<T> *pHashEntry = _aHashTable[i];
|
||
|
while ( pHashEntry != 0 )
|
||
|
{
|
||
|
CHashTableEntry<T> *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
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>void CHashTable<T>::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<T> *pHashEntry = new CHashTableEntry<T>( 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
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>BOOL CHashTable<T>::Lookup( WCHAR *pwcInputBuf,
|
||
|
unsigned uLen,
|
||
|
T& data )
|
||
|
{
|
||
|
unsigned uHashValue = Hash( pwcInputBuf, uLen );
|
||
|
|
||
|
Win4Assert( uHashValue < HASH_TABLE_SIZE );
|
||
|
|
||
|
for ( CHashTableEntry<T> *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
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
template<class T>unsigned CHashTable<T>::Hash( WCHAR *pwszName, unsigned cLen )
|
||
|
{
|
||
|
for ( ULONG uHashValue=0; cLen>0; pwszName++ )
|
||
|
{
|
||
|
uHashValue = toupper(*pwszName) + 31 * uHashValue;
|
||
|
cLen--;
|
||
|
}
|
||
|
|
||
|
return uHashValue % HASH_TABLE_SIZE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|