Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

235 lines
6.3 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Copyright (C) Microsoft Corporation, 1992 - 1996
  4. //
  5. // File: hash.hxx
  6. //
  7. // Contents: Template for a hash table that maps strings to data <T>
  8. //
  9. //--------------------------------------------------------------------------
  10. #pragma once
  11. const MAX_TAG_LENGTH = 50; // Max length of any hashed string
  12. const HASH_TABLE_SIZE = 97; // Size of hash table
  13. //+-------------------------------------------------------------------------
  14. //
  15. // Class: CHashTableEntry
  16. //
  17. // Purpose: An entry of hash table
  18. //
  19. //--------------------------------------------------------------------------
  20. template<class T>class CHashTableEntry
  21. {
  22. public:
  23. CHashTableEntry( WCHAR *pwszName, T data );
  24. WCHAR * GetName() { return _wszName; }
  25. T GetData() { return _data; }
  26. CHashTableEntry * GetNextHashEntry() { return _pHashEntryNext; }
  27. void SetNextHashEntry(CHashTableEntry *pEntry) { _pHashEntryNext = pEntry; }
  28. private:
  29. WCHAR _wszName[MAX_TAG_LENGTH]; // Char name
  30. T _data; // Data
  31. CHashTableEntry * _pHashEntryNext; // Link to next entry
  32. };
  33. //+-------------------------------------------------------------------------
  34. //
  35. // Class: CHashTable
  36. //
  37. // Purpose: Hash table for mapping strings to data
  38. //
  39. // Note: As these are static hence global objects, don't make them
  40. // unwindable.
  41. //
  42. //--------------------------------------------------------------------------
  43. template<class T>class CHashTable
  44. {
  45. public:
  46. CHashTable( BOOL fCaseInsensitive = TRUE );
  47. ~CHashTable();
  48. void Add( WCHAR *pwszName, T data );
  49. BOOL Lookup( WCHAR *pwcInputBuf, unsigned uLen, T& data );
  50. private:
  51. unsigned Hash( WCHAR *pwszName, unsigned cLen );
  52. BOOL _fCaseInsensitive;
  53. CHashTableEntry<T> * _aHashTable[HASH_TABLE_SIZE]; // Actual hash table
  54. };
  55. //+-------------------------------------------------------------------------
  56. //
  57. // Method: CHashTableEntry::CHashTableEntry
  58. //
  59. // Synopsis: Constructor
  60. //
  61. //--------------------------------------------------------------------------
  62. template<class T>CHashTableEntry<T>::CHashTableEntry( WCHAR *pwszName, T data )
  63. : _data(data),
  64. _pHashEntryNext(0)
  65. {
  66. Win4Assert( wcslen(pwszName) + 1 < MAX_TAG_LENGTH );
  67. wcscpy( _wszName, pwszName );
  68. }
  69. //+-------------------------------------------------------------------------
  70. //
  71. // Method: CHashTable::CHashTable
  72. //
  73. // Synopsis: Constructor
  74. //
  75. //--------------------------------------------------------------------------
  76. template<class T>CHashTable<T>::CHashTable( BOOL fCaseInsensitive ) :
  77. _fCaseInsensitive( fCaseInsensitive )
  78. {
  79. for (unsigned i=0; i<HASH_TABLE_SIZE; i++)
  80. _aHashTable[i] = 0;
  81. }
  82. //+-------------------------------------------------------------------------
  83. //
  84. // Method: CHashTable::~CHashTable
  85. //
  86. // Synopsis: Destructor
  87. //
  88. //--------------------------------------------------------------------------
  89. template<class T>CHashTable<T>::~CHashTable()
  90. {
  91. for ( unsigned i=0; i<HASH_TABLE_SIZE; i++)
  92. {
  93. CHashTableEntry<T> *pHashEntry = _aHashTable[i];
  94. while ( pHashEntry != 0 )
  95. {
  96. CHashTableEntry<T> *pHashEntryNext = pHashEntry->GetNextHashEntry();
  97. delete pHashEntry;
  98. pHashEntry = pHashEntryNext;
  99. }
  100. }
  101. }
  102. //+-------------------------------------------------------------------------
  103. //
  104. // Method: CHashTable::Add
  105. //
  106. // Synopsis: Add a special char -> data mapping
  107. //
  108. // Arguments: [pwszName] -- the special char
  109. // [data] -- the data
  110. //
  111. //--------------------------------------------------------------------------
  112. template<class T>void CHashTable<T>::Add( WCHAR *pwszName, T data )
  113. {
  114. #if DBG == 1
  115. //
  116. // Check for duplicate entries
  117. //
  118. T existingData;
  119. BOOL fFound = Lookup( pwszName, wcslen(pwszName), existingData );
  120. Win4Assert( !fFound );
  121. #endif
  122. CHashTableEntry<T> *pHashEntry = new CHashTableEntry<T>( pwszName,
  123. data );
  124. unsigned uHashValue = Hash( pwszName, wcslen(pwszName) );
  125. pHashEntry->SetNextHashEntry( _aHashTable[uHashValue] );
  126. _aHashTable[uHashValue] = pHashEntry;
  127. }
  128. //+-------------------------------------------------------------------------
  129. //
  130. // Method: CHashTable::Lookup
  131. //
  132. // Synopsis: Return the mapping corresponding to given string
  133. //
  134. // Arguments: [pwcInputBuf] -- Input buffer
  135. // [uLen] -- Length of input (not \0 terminated)
  136. // [data] -- Data returned here
  137. //
  138. // Returns: True if a mapping was found in the hash table
  139. //
  140. //--------------------------------------------------------------------------
  141. template<class T>BOOL CHashTable<T>::Lookup( WCHAR *pwcInputBuf,
  142. unsigned uLen,
  143. T& data )
  144. {
  145. unsigned uHashValue = Hash( pwcInputBuf, uLen );
  146. Win4Assert( uHashValue < HASH_TABLE_SIZE );
  147. for ( CHashTableEntry<T> *pHashEntry = _aHashTable[uHashValue];
  148. pHashEntry != 0;
  149. pHashEntry = pHashEntry->GetNextHashEntry() )
  150. {
  151. int i;
  152. if ( _fCaseInsensitive )
  153. i = _wcsnicmp( pwcInputBuf, pHashEntry->GetName(), uLen );
  154. else
  155. i = wcsncmp( pwcInputBuf, pHashEntry->GetName(), uLen );
  156. if ( 0 == i )
  157. {
  158. data = pHashEntry->GetData();
  159. return TRUE;
  160. }
  161. }
  162. return FALSE;
  163. }
  164. //+-------------------------------------------------------------------------
  165. //
  166. // Method: CHashTable::Hash
  167. //
  168. // Synopsis: Implements the hash function
  169. //
  170. // Arguments: [pwszName] -- name to hash
  171. // [cLen] -- length of pszName (it is not null terminated)
  172. //
  173. // Returns: Position of chained list in hash table
  174. //
  175. //--------------------------------------------------------------------------
  176. template<class T>unsigned CHashTable<T>::Hash( WCHAR *pwszName, unsigned cLen )
  177. {
  178. for ( ULONG uHashValue=0; cLen>0; pwszName++ )
  179. {
  180. uHashValue = toupper(*pwszName) + 31 * uHashValue;
  181. cLen--;
  182. }
  183. return uHashValue % HASH_TABLE_SIZE;
  184. }