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.

270 lines
6.2 KiB

  1. /*
  2. File HashTab.h
  3. Definitions for creating/dealing with hash tables.
  4. Paul Mayfield, 3/30/98
  5. */
  6. #include "hashtab.h"
  7. // Represents nodes in the binary tree
  8. typedef struct _HTNODE {
  9. HANDLE hData;
  10. struct _HTNODE * pNext;
  11. } HTNODE;
  12. // Represents a binary tree
  13. typedef struct _HASHTAB {
  14. HTNODE ** ppNodes;
  15. ULONG ulSize;
  16. HashTabHashFuncPtr pHash;
  17. HashTabKeyCompFuncPtr pCompKeyAndElem;
  18. HashTabAllocFuncPtr pAlloc;
  19. HashTabFreeFuncPtr pFree;
  20. HashTabFreeElemFuncPtr pFreeElem;
  21. ULONG dwCount;
  22. } HASHTAB;
  23. // Default allocator
  24. PVOID HashTabAlloc (ULONG ulSize) {
  25. return RtlAllocateHeap (RtlProcessHeap(), 0, ulSize);
  26. }
  27. // Default freer
  28. VOID HashTabFree (PVOID pvData) {
  29. RtlFreeHeap (RtlProcessHeap(), 0, pvData);
  30. }
  31. //
  32. // Create a hash table
  33. //
  34. ULONG HashTabCreate (
  35. IN ULONG ulSize,
  36. IN HashTabHashFuncPtr pHash,
  37. IN HashTabKeyCompFuncPtr pCompKeyAndElem,
  38. IN OPTIONAL HashTabAllocFuncPtr pAlloc,
  39. IN OPTIONAL HashTabFreeFuncPtr pFree,
  40. IN OPTIONAL HashTabFreeElemFuncPtr pFreeElem,
  41. OUT HANDLE * phHashTab )
  42. {
  43. HASHTAB * pTable;
  44. // Validate and initailize variables
  45. if (!pHash || !pCompKeyAndElem || !phHashTab)
  46. return ERROR_INVALID_PARAMETER;
  47. if (!pAlloc)
  48. pAlloc = HashTabAlloc;
  49. // Allocate the table structure
  50. pTable = (*pAlloc)(sizeof(HASHTAB));
  51. if (!pTable)
  52. return ERROR_NOT_ENOUGH_MEMORY;
  53. // Initialize
  54. pTable->pHash = pHash;
  55. pTable->ulSize = ulSize;
  56. pTable->pCompKeyAndElem = pCompKeyAndElem;
  57. pTable->pAlloc = pAlloc;
  58. pTable->pFree = (pFree) ? pFree : HashTabFree;
  59. pTable->pFreeElem = pFreeElem;
  60. // Allocate the table
  61. pTable->ppNodes = (pAlloc)(sizeof(HTNODE*) * ulSize);
  62. if (!pTable->ppNodes) {
  63. (*(pTable->pFree))(pTable);
  64. return ERROR_NOT_ENOUGH_MEMORY;
  65. }
  66. RtlZeroMemory (pTable->ppNodes, sizeof(HTNODE*) * ulSize);
  67. *phHashTab = (HANDLE)pTable;
  68. return NO_ERROR;
  69. }
  70. //
  71. // Clean up the hash table.
  72. //
  73. ULONG
  74. HashTabCleanup (
  75. IN HANDLE hHashTab )
  76. {
  77. HASHTAB * pTable = (HASHTAB*)hHashTab;
  78. HTNODE * pNode, * pNext;
  79. ULONG i;
  80. if (pTable == NULL)
  81. {
  82. return ERROR_INVALID_PARAMETER;
  83. }
  84. for (i = 0; i < pTable->ulSize; i++ )
  85. {
  86. if ((pNode = pTable->ppNodes[i]) != NULL)
  87. {
  88. while (pNode)
  89. {
  90. pNext = pNode->pNext;
  91. if (pTable->pFreeElem)
  92. {
  93. (*(pTable->pFreeElem))(pNode->hData);
  94. }
  95. (*(pTable->pFree))(pNode);
  96. pNode = pNext;
  97. }
  98. }
  99. }
  100. (*(pTable->pFree))(pTable->ppNodes);
  101. (*(pTable->pFree))(pTable);
  102. return NO_ERROR;
  103. }
  104. //
  105. // Insert an element in a hash table
  106. //
  107. ULONG HashTabInsert (
  108. IN HANDLE hHashTab,
  109. IN HANDLE hKey,
  110. IN HANDLE hData )
  111. {
  112. HASHTAB * pTable = (HASHTAB*)hHashTab;
  113. HTNODE * pNode;
  114. ULONG ulIndex;
  115. // Validate Params
  116. if (!hHashTab || !hData)
  117. return ERROR_INVALID_PARAMETER;
  118. // Find out where the element goes
  119. ulIndex = (* (pTable->pHash))(hKey);
  120. if (ulIndex >= pTable->ulSize)
  121. return ERROR_INVALID_INDEX;
  122. // Allocate a new hash table node
  123. pNode = (* (pTable->pAlloc))(sizeof (HTNODE));
  124. if (!pNode)
  125. return ERROR_NOT_ENOUGH_MEMORY;
  126. // Insert the node into the appropriate location in the
  127. // hash table.
  128. pNode->pNext = pTable->ppNodes[ulIndex];
  129. pTable->ppNodes[ulIndex] = pNode;
  130. pNode->hData = hData;
  131. pTable->dwCount++;
  132. return NO_ERROR;
  133. }
  134. //
  135. // Removes the data associated with the given key
  136. //
  137. ULONG HashTabRemove (
  138. IN HANDLE hHashTab,
  139. IN HANDLE hKey)
  140. {
  141. HASHTAB * pTable = (HASHTAB*)hHashTab;
  142. HTNODE * pCur, * pPrev;
  143. ULONG ulIndex;
  144. int iCmp;
  145. // Validate Params
  146. if (!hHashTab)
  147. return ERROR_INVALID_PARAMETER;
  148. // Find out where the element should be
  149. ulIndex = (* (pTable->pHash))(hKey);
  150. if (ulIndex >= pTable->ulSize)
  151. return ERROR_INVALID_INDEX;
  152. if (pTable->ppNodes[ulIndex] == NULL)
  153. return ERROR_NOT_FOUND;
  154. // If the element is at the start of the
  155. // list, remove it and we're done.
  156. pCur = pTable->ppNodes[ulIndex];
  157. if ( (*(pTable->pCompKeyAndElem))(hKey, pCur->hData) == 0 ) {
  158. pTable->ppNodes[ulIndex] = pCur->pNext;
  159. if (pTable->pFreeElem)
  160. (*(pTable->pFreeElem))(pCur->hData);
  161. (*(pTable->pFree))(pCur);
  162. pTable->dwCount--;
  163. return NO_ERROR;
  164. }
  165. // Otherwise, loop through the list until we find a
  166. // match.
  167. pPrev = pCur;
  168. pCur = pCur->pNext;
  169. while (pCur) {
  170. iCmp = (*(pTable->pCompKeyAndElem))(hKey, pCur->hData);
  171. if ( iCmp == 0 ) {
  172. pPrev->pNext = pCur->pNext;
  173. if (pTable->pFreeElem)
  174. (*(pTable->pFreeElem))(pCur->hData);
  175. (*(pTable->pFree))(pCur);
  176. pTable->dwCount--;
  177. return NO_ERROR;
  178. }
  179. pPrev = pCur;
  180. pCur = pCur->pNext;
  181. }
  182. return ERROR_NOT_FOUND;
  183. }
  184. //
  185. // Search in the table for the data associated with the given key
  186. //
  187. ULONG HashTabFind (
  188. IN HANDLE hHashTab,
  189. IN HANDLE hKey,
  190. OUT HANDLE * phData )
  191. {
  192. HASHTAB * pTable = (HASHTAB*)hHashTab;
  193. HTNODE * pNode;
  194. ULONG ulIndex;
  195. // Validate Params
  196. if (!hHashTab || !phData)
  197. return ERROR_INVALID_PARAMETER;
  198. // Find out where the element goes
  199. ulIndex = (* (pTable->pHash))(hKey);
  200. if (ulIndex >= pTable->ulSize)
  201. return ERROR_INVALID_INDEX;
  202. // Search through the list at the given index
  203. pNode = pTable->ppNodes[ulIndex];
  204. while (pNode) {
  205. if ( (*(pTable->pCompKeyAndElem))(hKey, pNode->hData) == 0 ) {
  206. *phData = pNode->hData;
  207. return NO_ERROR;
  208. }
  209. pNode = pNode->pNext;
  210. }
  211. return ERROR_NOT_FOUND;
  212. }
  213. ULONG
  214. HashTabGetCount(
  215. IN HANDLE hHashTab,
  216. OUT ULONG* lpdwCount)
  217. {
  218. HASHTAB * pTable = (HASHTAB*)hHashTab;
  219. if (!lpdwCount || !hHashTab)
  220. {
  221. return ERROR_INVALID_PARAMETER;
  222. }
  223. *lpdwCount = pTable->dwCount;
  224. return NO_ERROR;
  225. }