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.

270 lines
5.3 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. table.c
  5. ABSTRACT
  6. Generic hash table manipulation routines.
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 28-Jul-1995
  9. REVISION HISTORY
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <stdlib.h>
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include <npapi.h>
  20. #include <acd.h>
  21. #include <debug.h>
  22. #include "table.h"
  23. #include "misc.h"
  24. //
  25. // Generic hash table entry.
  26. //
  27. typedef struct _HASH_ENTRY {
  28. LIST_ENTRY ListEntry;
  29. LPTSTR pszKey;
  30. PVOID pData;
  31. } HASH_ENTRY, *PHASH_ENTRY;
  32. PHASH_TABLE
  33. NewTable()
  34. {
  35. PHASH_TABLE pTable;
  36. INT i;
  37. pTable = LocalAlloc(LPTR, sizeof (HASH_TABLE));
  38. if (pTable == NULL) {
  39. RASAUTO_TRACE("NewTable: LocalAlloc failed");
  40. return NULL;
  41. }
  42. for (i = 0; i < NBUCKETS; i++)
  43. InitializeListHead(&pTable->ListEntry[i]);
  44. pTable->ulSize = 0;
  45. return pTable;
  46. } // NewTable
  47. VOID
  48. FreeHashTableEntry(
  49. IN PHASH_ENTRY pHashEntry
  50. )
  51. {
  52. LocalFree(pHashEntry->pszKey);
  53. if (pHashEntry->pData != NULL)
  54. LocalFree(pHashEntry->pData);
  55. LocalFree(pHashEntry);
  56. } // FreeHashTableEntry
  57. VOID
  58. ClearTable(
  59. IN PHASH_TABLE pTable
  60. )
  61. {
  62. INT i;
  63. PLIST_ENTRY pHead;
  64. PHASH_ENTRY pHashEntry;
  65. for (i = 0; i < NBUCKETS; i++) {
  66. while (!IsListEmpty(&pTable->ListEntry[i])) {
  67. pHead = RemoveHeadList(&pTable->ListEntry[i]);
  68. pHashEntry = CONTAINING_RECORD(pHead, HASH_ENTRY, ListEntry);
  69. FreeHashTableEntry(pHashEntry);
  70. }
  71. }
  72. pTable->ulSize = 0;
  73. } // ClearTable
  74. VOID
  75. EnumTable(
  76. IN PHASH_TABLE pTable,
  77. IN PHASH_TABLE_ENUM_PROC pProc,
  78. IN PVOID pArg
  79. )
  80. {
  81. INT i;
  82. PLIST_ENTRY pEntry, pNextEntry;
  83. PHASH_ENTRY pHashEntry;
  84. for (i = 0; i < NBUCKETS; i++) {
  85. pEntry = pTable->ListEntry[i].Flink;
  86. while (pEntry != &pTable->ListEntry[i]) {
  87. pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
  88. //
  89. // Get the next entry before calling
  90. // the enumerator procedure to allow
  91. // it to call DeleteTableEntry().
  92. //
  93. pNextEntry = pEntry->Flink;
  94. //
  95. // If the enumerator procedure
  96. // returns FALSE, terminate the
  97. // enumeration.
  98. //
  99. if (!pProc(pArg, pHashEntry->pszKey, pHashEntry->pData))
  100. return;
  101. pEntry = pNextEntry;
  102. }
  103. }
  104. } // EnumTable
  105. VOID
  106. FreeTable(
  107. IN PHASH_TABLE pTable
  108. )
  109. {
  110. ClearTable(pTable);
  111. LocalFree(pTable);
  112. } // FreeTable
  113. INT
  114. HashString(
  115. IN LPTSTR pszKey
  116. )
  117. {
  118. CHAR ch;
  119. DWORD dwHashValue = 0;
  120. LPTSTR p = pszKey;
  121. while (*p != L'\0') {
  122. ch = (CHAR)tolower(*p);
  123. dwHashValue += (INT)ch * (INT)ch;
  124. p++;
  125. }
  126. return (INT)(dwHashValue % NBUCKETS);
  127. } // HashString
  128. PHASH_ENTRY
  129. GetTableEntryCommon(
  130. IN PHASH_TABLE pTable,
  131. IN LPTSTR pszKey
  132. )
  133. {
  134. INT nBucket = HashString(pszKey);
  135. PLIST_ENTRY pEntry;
  136. PHASH_ENTRY pHashEntry;
  137. for (pEntry = pTable->ListEntry[nBucket].Flink;
  138. pEntry != &pTable->ListEntry[nBucket];
  139. pEntry = pEntry->Flink)
  140. {
  141. pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
  142. if (!_wcsicmp(pHashEntry->pszKey, pszKey))
  143. return pHashEntry;
  144. }
  145. return NULL;
  146. } // GetTableEntryCommon
  147. BOOLEAN
  148. GetTableEntry(
  149. IN PHASH_TABLE pTable,
  150. IN LPTSTR pszKey,
  151. OUT PVOID *pData
  152. )
  153. {
  154. PHASH_ENTRY pHashEntry;
  155. pHashEntry = GetTableEntryCommon(pTable, pszKey);
  156. if (pHashEntry != NULL) {
  157. if (pData != NULL)
  158. *pData = pHashEntry->pData;
  159. return TRUE;
  160. }
  161. return FALSE;
  162. } // GetTableEntry
  163. BOOLEAN
  164. PutTableEntry(
  165. IN PHASH_TABLE pTable,
  166. IN LPTSTR pszKey,
  167. IN PVOID pData
  168. )
  169. {
  170. INT nBucket = HashString(pszKey);
  171. PHASH_ENTRY pHashEntry;
  172. pHashEntry = GetTableEntryCommon(pTable, pszKey);
  173. if (pHashEntry == NULL) {
  174. pHashEntry = LocalAlloc(LPTR, sizeof (HASH_ENTRY));
  175. if (pHashEntry == NULL) {
  176. RASAUTO_TRACE("PutTableEntry: LocalAlloc failed");
  177. return FALSE;
  178. }
  179. pHashEntry->pszKey = CopyString(pszKey);
  180. if (pHashEntry->pszKey == NULL) {
  181. RASAUTO_TRACE("PutTableEntry: LocalAlloc failed");
  182. LocalFree(pHashEntry);
  183. return FALSE;
  184. }
  185. InsertHeadList(
  186. &pTable->ListEntry[nBucket],
  187. &pHashEntry->ListEntry);
  188. pTable->ulSize++;
  189. }
  190. else {
  191. if (pHashEntry->pData != pData)
  192. LocalFree(pHashEntry->pData);
  193. }
  194. pHashEntry->pData = pData;
  195. return TRUE;
  196. } // PutTableEntry
  197. BOOLEAN
  198. DeleteTableEntry(
  199. IN PHASH_TABLE pTable,
  200. IN LPTSTR pszKey
  201. )
  202. {
  203. PHASH_ENTRY pHashEntry;
  204. pHashEntry = GetTableEntryCommon(pTable, pszKey);
  205. if (pHashEntry != NULL) {
  206. RemoveEntryList(&pHashEntry->ListEntry);
  207. FreeHashTableEntry(pHashEntry);
  208. pTable->ulSize--;
  209. }
  210. return (pHashEntry != NULL);
  211. } // DeleteTableEntry