windows-nt/Source/XPSP1/NT/inetsrv/query/qutil/h/hash.hxx

236 lines
6.3 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// 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;
}