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.

335 lines
9.0 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: scmhash.cxx
  7. //
  8. // Contents: Class definitions used for SCM hash table.
  9. //
  10. // History: 20-Jan-93 Ricksa Created from map_kv.cpp
  11. //
  12. // Notes: The reason for creating this file rather than using the
  13. // original class is that the SCM has different memory allocation
  14. // needs depending on whether it is built for Win95 or NT.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "act.hxx"
  18. //+-------------------------------------------------------------------------
  19. //
  20. // Member: CScmHashEntry::~CScmHashEntry
  21. //
  22. // Synopsis: Clean up hash entry
  23. //
  24. // History: 16-Feb-96 Ricksa Created
  25. //
  26. //--------------------------------------------------------------------------
  27. CScmHashEntry::~CScmHashEntry(void)
  28. {
  29. // Just exists hopefully to save some space
  30. }
  31. //+-------------------------------------------------------------------------
  32. //
  33. // Member: CScmHashTable::~CScmHashTable
  34. //
  35. // Synopsis: Free resources held by the hash table
  36. //
  37. // Algorithm: For each hash bucket, delete all member of the collison
  38. // list.
  39. //
  40. // History: 16-Feb-95 Ricksa Created
  41. //
  42. //--------------------------------------------------------------------------
  43. CScmHashTable::~CScmHashTable(void)
  44. {
  45. // Free all the objects in the table.
  46. // Loop through each hash bucket
  47. for (DWORD i = 0; i < _ndwHashTableSize; i++)
  48. {
  49. // For each entry in the hash bucket list delete it.
  50. CScmHashEntry *pshe = _apsheHashTable[i];
  51. while (pshe != NULL)
  52. {
  53. CScmHashEntry *psheNext = pshe->GetNext();
  54. delete pshe;
  55. pshe = psheNext;
  56. }
  57. }
  58. // Free the table itself
  59. PrivMemFree (_apsheHashTable);
  60. }
  61. //+-------------------------------------------------------------------------
  62. //
  63. // Member: CScmHashTable::Lookup
  64. //
  65. // Synopsis: Look up entry by hash and key
  66. //
  67. // Arguments: [dwHash] - hash value to use
  68. // [pKey] - key to use
  69. // [cbKey] - count of bytes in the key
  70. //
  71. // Returns: NULL - no matching entry was found
  72. // Pointer to first matching entry found
  73. //
  74. // Algorithm: If there is an entry for the hash bucket, search
  75. // through the collision entries for the first entry
  76. // that matches.
  77. //
  78. // History: 20-Jan-95 Ricksa Created
  79. //
  80. //--------------------------------------------------------------------------
  81. CScmHashEntry * CScmHashTable::Lookup(
  82. DWORD dwHash,
  83. LPVOID pKey,
  84. UINT cbKey) const
  85. {
  86. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::Lookup "
  87. "( %lx , %p , %lx )\n", this, dwHash, pKey, cbKey));
  88. CScmHashEntry *psheFound = NULL;
  89. // Are there any entries for this bucket?
  90. if (_apsheHashTable[dwHash] != NULL)
  91. {
  92. CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
  93. // Loop searching for a match
  94. do
  95. {
  96. if (psheToSearch->IsEqual(pKey, cbKey))
  97. {
  98. psheFound = psheToSearch;
  99. break;
  100. }
  101. } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
  102. }
  103. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::Lookup ( %p )\n",
  104. this, psheFound));
  105. return psheFound;
  106. }
  107. //+-------------------------------------------------------------------------
  108. //
  109. // Member: CScmHashTable::SetAt
  110. //
  111. // Synopsis: Add a new entry
  112. //
  113. // Arguments: [dwHash] - hash value to use
  114. // [psheToAdd] - hash entry to add
  115. //
  116. // Algorithm: If there are no entries for the bucket, make the bucket
  117. // point to this entry. Otherwise, put this entry on the
  118. // end of the list of collisions.
  119. //
  120. // History: 20-Jan-95 Ricksa Created
  121. //
  122. //--------------------------------------------------------------------------
  123. void CScmHashTable::SetAt(
  124. DWORD dwHash,
  125. CScmHashEntry *psheToAdd)
  126. {
  127. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::SetAt "
  128. "( %lx , %p )\n", this, dwHash, psheToAdd));
  129. // Are there entries that has to this bucket?
  130. if (_apsheHashTable[dwHash] != NULL)
  131. {
  132. // Yes -- then put this one on the end of the list
  133. CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
  134. CScmHashEntry *psheLast;
  135. do
  136. {
  137. psheLast = psheToSearch;
  138. } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
  139. psheLast->SetNext(psheToAdd);
  140. }
  141. else
  142. {
  143. // No entries on the list so put this one first
  144. _apsheHashTable[dwHash] = psheToAdd;
  145. }
  146. _ndwCount++;
  147. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::SetAt \n", this));
  148. }
  149. //+-------------------------------------------------------------------------
  150. //
  151. // Member: CScmHashTable::RemoveEntry
  152. //
  153. // Synopsis: Remove an entry from the list
  154. //
  155. // Arguments: [dwHash] - hash value to use
  156. // [psheToRemove] - hash entry to add
  157. //
  158. // Returns: TRUE - entry removed.
  159. // FALSE - no such entry found
  160. //
  161. // Algorithm: If bucket is not empty, if this is the first entry replace
  162. // it with its next. Otherwise, loop through the list searching
  163. // for the entry and make its previous point to the current
  164. // one's next.
  165. //
  166. // History: 20-Jan-95 Ricksa Created
  167. //
  168. //--------------------------------------------------------------------------
  169. BOOL CScmHashTable::RemoveEntry(
  170. DWORD dwHash,
  171. CScmHashEntry *psheToRemove)
  172. {
  173. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::RemoveEntry "
  174. "( %lx , %p )\n", this, dwHash, psheToRemove));
  175. BOOL fFound = FALSE;
  176. // Are there any entries for this bucket?
  177. if (_apsheHashTable[dwHash] != NULL)
  178. {
  179. CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
  180. CScmHashEntry *pshePrev = NULL;
  181. while (psheToSearch != NULL)
  182. {
  183. if (psheToSearch == psheToRemove)
  184. {
  185. if (pshePrev == NULL)
  186. {
  187. // First entry matches so update the head of the list
  188. _apsheHashTable[dwHash] = psheToSearch->GetNext();
  189. }
  190. else
  191. {
  192. // Found entry in the middle of the list so delete
  193. // the previous item's next pointer
  194. pshePrev->SetNext(psheToSearch->GetNext());
  195. }
  196. // Tell the caller we found the item
  197. fFound = TRUE;
  198. break;
  199. }
  200. pshePrev = psheToSearch;
  201. psheToSearch = psheToSearch->GetNext();
  202. }
  203. if (fFound)
  204. {
  205. _ndwCount--;
  206. }
  207. }
  208. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::RemoveEntry ( %lx )\n",
  209. this, fFound));
  210. return fFound;
  211. }
  212. //+-------------------------------------------------------------------------
  213. //
  214. // Member: CScmHashIter::FindNextBucketWithEntry
  215. //
  216. // Synopsis: Find next hash bucket that has an entry
  217. //
  218. // Returns: Entry for bucket or NULL if there are none/
  219. //
  220. // Algorithm: Beginning with the current bucket loop through the list
  221. // of buckets till one is not null or there are no more
  222. // buckets.
  223. //
  224. // History: 20-Jan-95 Ricksa Created
  225. //
  226. //--------------------------------------------------------------------------
  227. CScmHashEntry *CScmHashIter::FindNextBucketWithEntry(void)
  228. {
  229. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::FindNextBucketWithEntry\n",
  230. this));
  231. for (; _dwBucket < _psht->_ndwHashTableSize; _dwBucket++)
  232. {
  233. if ((_psheNext =_psht->_apsheHashTable[_dwBucket]) != NULL)
  234. {
  235. break;
  236. }
  237. }
  238. // Point to the next bucket
  239. _dwBucket++;
  240. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::FindNextBucketWithEntry "
  241. "( %p )\n", this, _psheNext));
  242. return _psheNext;
  243. }
  244. //+-------------------------------------------------------------------------
  245. //
  246. // Member: CScmHashIter::GetNext
  247. //
  248. // Synopsis: Find next hash bucket that has an entry
  249. //
  250. // Returns: Next entry in the iteration
  251. //
  252. // Algorithm: Get the next pointer from the object and then update
  253. // the next pointer if there are still entries to be
  254. // iterated.
  255. //
  256. // History: 20-Jan-95 Ricksa Created
  257. //
  258. //--------------------------------------------------------------------------
  259. CScmHashEntry *CScmHashIter::GetNext(void)
  260. {
  261. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::GetNext \n", this));
  262. CScmHashEntry *psheToReturn = _psheNext;
  263. // Search for the next entry to return
  264. if (_psheNext != NULL)
  265. {
  266. _psheNext = _psheNext->GetNext();
  267. if (_psheNext == NULL)
  268. {
  269. FindNextBucketWithEntry();
  270. }
  271. }
  272. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::GetNext "
  273. "( %p )\n", this, psheToReturn));
  274. return psheToReturn;
  275. }