Leaked source code of windows server 2003
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.

389 lines
11 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::Lookup
  110. //
  111. // Synopsis: Look up entry by entry pointer
  112. //
  113. // Arguments: [dwHash] - hash value to use
  114. // [pvEntry] - entry pointer to find
  115. //
  116. // Returns: NULL - no matching entry was found
  117. // Pointer to first matching entry found
  118. //
  119. // Algorithm: If there is an entry for the hash bucket, search
  120. // through the collision entries for the first entry
  121. // that matches.
  122. //
  123. // History: 05-Mar-02 JohnDoty Created
  124. //
  125. //--------------------------------------------------------------------------
  126. CScmHashEntry * CScmHashTable::Lookup(
  127. DWORD dwHash,
  128. LPVOID pvEntry) const
  129. {
  130. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::Lookup "
  131. "( %lx , %p )\n", this, dwHash, pvEntry));
  132. // Make sure the hash is valid.
  133. if (dwHash >= SCM_HASH_SIZE)
  134. return NULL;
  135. CScmHashEntry *psheFound = NULL;
  136. // Are there any entries for this bucket?
  137. if (_apsheHashTable[dwHash] != NULL)
  138. {
  139. CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
  140. // Loop searching for a match
  141. do
  142. {
  143. if (psheToSearch == pvEntry)
  144. {
  145. psheFound = psheToSearch;
  146. break;
  147. }
  148. } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
  149. }
  150. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::Lookup ( %p )\n",
  151. this, psheFound));
  152. return psheFound;
  153. }
  154. //+-------------------------------------------------------------------------
  155. //
  156. // Member: CScmHashTable::SetAt
  157. //
  158. // Synopsis: Add a new entry
  159. //
  160. // Arguments: [dwHash] - hash value to use
  161. // [psheToAdd] - hash entry to add
  162. //
  163. // Algorithm: If there are no entries for the bucket, make the bucket
  164. // point to this entry. Otherwise, put this entry on the
  165. // end of the list of collisions.
  166. //
  167. // History: 20-Jan-95 Ricksa Created
  168. //
  169. //--------------------------------------------------------------------------
  170. void CScmHashTable::SetAt(
  171. DWORD dwHash,
  172. CScmHashEntry *psheToAdd)
  173. {
  174. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::SetAt "
  175. "( %lx , %p )\n", this, dwHash, psheToAdd));
  176. // Are there entries that has to this bucket?
  177. if (_apsheHashTable[dwHash] != NULL)
  178. {
  179. // Yes -- then put this one on the end of the list
  180. CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
  181. CScmHashEntry *psheLast;
  182. do
  183. {
  184. psheLast = psheToSearch;
  185. } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
  186. psheLast->SetNext(psheToAdd);
  187. }
  188. else
  189. {
  190. // No entries on the list so put this one first
  191. _apsheHashTable[dwHash] = psheToAdd;
  192. }
  193. _ndwCount++;
  194. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::SetAt \n", this));
  195. }
  196. //+-------------------------------------------------------------------------
  197. //
  198. // Member: CScmHashTable::RemoveEntry
  199. //
  200. // Synopsis: Remove an entry from the list
  201. //
  202. // Arguments: [dwHash] - hash value to use
  203. // [psheToRemove] - hash entry to add
  204. //
  205. // Returns: TRUE - entry removed.
  206. // FALSE - no such entry found
  207. //
  208. // Algorithm: If bucket is not empty, if this is the first entry replace
  209. // it with its next. Otherwise, loop through the list searching
  210. // for the entry and make its previous point to the current
  211. // one's next.
  212. //
  213. // History: 20-Jan-95 Ricksa Created
  214. //
  215. //--------------------------------------------------------------------------
  216. BOOL CScmHashTable::RemoveEntry(
  217. DWORD dwHash,
  218. CScmHashEntry *psheToRemove)
  219. {
  220. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::RemoveEntry "
  221. "( %lx , %p )\n", this, dwHash, psheToRemove));
  222. BOOL fFound = FALSE;
  223. // Are there any entries for this bucket?
  224. if (_apsheHashTable[dwHash] != NULL)
  225. {
  226. CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
  227. CScmHashEntry *pshePrev = NULL;
  228. while (psheToSearch != NULL)
  229. {
  230. if (psheToSearch == psheToRemove)
  231. {
  232. if (pshePrev == NULL)
  233. {
  234. // First entry matches so update the head of the list
  235. _apsheHashTable[dwHash] = psheToSearch->GetNext();
  236. }
  237. else
  238. {
  239. // Found entry in the middle of the list so delete
  240. // the previous item's next pointer
  241. pshePrev->SetNext(psheToSearch->GetNext());
  242. }
  243. // Tell the caller we found the item
  244. fFound = TRUE;
  245. break;
  246. }
  247. pshePrev = psheToSearch;
  248. psheToSearch = psheToSearch->GetNext();
  249. }
  250. if (fFound)
  251. {
  252. _ndwCount--;
  253. }
  254. }
  255. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::RemoveEntry ( %lx )\n",
  256. this, fFound));
  257. return fFound;
  258. }
  259. //+-------------------------------------------------------------------------
  260. //
  261. // Member: CScmHashIter::FindNextBucketWithEntry
  262. //
  263. // Synopsis: Find next hash bucket that has an entry
  264. //
  265. // Returns: Entry for bucket or NULL if there are none/
  266. //
  267. // Algorithm: Beginning with the current bucket loop through the list
  268. // of buckets till one is not null or there are no more
  269. // buckets.
  270. //
  271. // History: 20-Jan-95 Ricksa Created
  272. //
  273. //--------------------------------------------------------------------------
  274. CScmHashEntry *CScmHashIter::FindNextBucketWithEntry(void)
  275. {
  276. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::FindNextBucketWithEntry\n",
  277. this));
  278. for (; _dwBucket < _psht->_ndwHashTableSize; _dwBucket++)
  279. {
  280. if ((_psheNext =_psht->_apsheHashTable[_dwBucket]) != NULL)
  281. {
  282. break;
  283. }
  284. }
  285. // Point to the next bucket
  286. _dwBucket++;
  287. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::FindNextBucketWithEntry "
  288. "( %p )\n", this, _psheNext));
  289. return _psheNext;
  290. }
  291. //+-------------------------------------------------------------------------
  292. //
  293. // Member: CScmHashIter::GetNext
  294. //
  295. // Synopsis: Find next hash bucket that has an entry
  296. //
  297. // Returns: Next entry in the iteration
  298. //
  299. // Algorithm: Get the next pointer from the object and then update
  300. // the next pointer if there are still entries to be
  301. // iterated.
  302. //
  303. // History: 20-Jan-95 Ricksa Created
  304. //
  305. //--------------------------------------------------------------------------
  306. CScmHashEntry *CScmHashIter::GetNext(void)
  307. {
  308. CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::GetNext \n", this));
  309. CScmHashEntry *psheToReturn = _psheNext;
  310. // Search for the next entry to return
  311. if (_psheNext != NULL)
  312. {
  313. _psheNext = _psheNext->GetNext();
  314. if (_psheNext == NULL)
  315. {
  316. FindNextBucketWithEntry();
  317. }
  318. }
  319. CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::GetNext "
  320. "( %p )\n", this, psheToReturn));
  321. return psheToReturn;
  322. }