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.

252 lines
6.9 KiB

  1. //
  2. // Copyright (c) Microsoft Corporation 1991-1993
  3. //
  4. // File: Hash.c
  5. //
  6. // Comments:
  7. // This file contains functions that are roughly equivelent to the
  8. // kernel atom function. There are two main differences. The first
  9. // is that in 32 bit land the tables are maintined in our shared heap,
  10. // which makes it shared between all of our apps. The second is that
  11. // we can assocate a long pointer with each of the items, which in many
  12. // cases allows us to keep from having to do a secondary lookup from
  13. // a different table
  14. //
  15. // History:
  16. // 09/08/93 - Created KurtE
  17. //
  18. //---------------------------------------------------------------------------
  19. #ifdef STRICT
  20. #undef STRICT
  21. #endif
  22. #define NO_SHELL_HEAP_ALLOCATOR //Kludge to get around new mem heaps in nt
  23. #define NO_SHELL_VALIDATION
  24. // to fix assert problem
  25. #ifdef ASSERT
  26. #undef ASSERT
  27. #endif
  28. #include "project.h"
  29. #include "urlshell.h"
  30. #include <platform.h>
  31. //--------------------------------------------------------------------------
  32. // First define a data structure to use to maintain the list
  33. #define PRIME 37
  34. // NOTE a PHASHITEM is defined as a LPCSTR externaly (for old code to work)
  35. #undef PHASHITEM
  36. typedef struct _HashItem FAR * PHASHITEM;
  37. typedef struct _HashItem
  38. {
  39. PHASHITEM phiNext; //
  40. UINT wCount; // Usage count
  41. BYTE cbLen; // Length of name in characters.
  42. char szName[1]; // name
  43. } HASHITEM;
  44. typedef struct _HashTable
  45. {
  46. UINT wBuckets; // Number of buckets
  47. UINT wcbExtra; // Extra bytes per item
  48. BOOL fUpperCase; // Uppercase names
  49. PHASHITEM phiLast; // Pointer to the last item we worked with
  50. PHASHITEM ahiBuckets[EMPTY_SIZE]; // Set of buckets for the table
  51. } HASHTABLE, FAR * PHASHTABLE;
  52. #define HIFROMSZ(sz) ((PHASHITEM)((BYTE*)(sz) - FIELDOFFSET(HASHITEM, szName)))
  53. #define HIDATAPTR(sz) ((DWORD UNALIGNED *)((BYTE*)(sz) + HIFROMSZ(sz)->cbLen+1))
  54. #define LOOKUPHASHITEM 0
  55. #define ADDHASHITEM 1
  56. #define DELETEHASHITEM 2
  57. static PHASHTABLE g_pHashTable = NULL;
  58. PHASHTABLE NEAR PASCAL GetGlobalHashTable();
  59. //--------------------------------------------------------------------------
  60. // This function looks up the name in the hash table and optionally does
  61. // things like add it, or delete it.
  62. //
  63. //// FEATURE
  64. // we will need to serialize this eventually.
  65. LPCSTR NEAR PASCAL LookupItemInHashTable(PHASHTABLE pht, LPCSTR pszName, int iOp)
  66. {
  67. // First thing to do is calculate the hash value for the item
  68. DWORD dwHash = 0;
  69. UINT wBucket;
  70. BYTE cbName = 0;
  71. BYTE c;
  72. PHASHITEM phi, phiPrev;
  73. LPCSTR psz = pszName;
  74. if (pht == NULL) {
  75. pht = GetGlobalHashTable();
  76. }
  77. if (pht)
  78. {
  79. while (*psz)
  80. {
  81. // Same type of hash like HashItem manager
  82. c = *psz++;
  83. if (pht->fUpperCase && ( c >= 'a') && (c <= 'z'))
  84. c = c - 'a' + 'A';
  85. dwHash += (c << 1) + (c >> 1) + c;
  86. cbName++;
  87. ASSERT(cbName);
  88. if (cbName == 0)
  89. return(NULL); // Length to long!
  90. }
  91. // now search for the item in the buckets.
  92. phiPrev = NULL;
  93. ENTERCRITICAL;
  94. phi = pht->ahiBuckets[wBucket = (UINT)(dwHash % pht->wBuckets)];
  95. while (phi)
  96. {
  97. if (phi->cbLen == cbName)
  98. {
  99. if (pht->fUpperCase)
  100. {
  101. if (!lstrcmpi(pszName, phi->szName))
  102. break; // Found match
  103. }
  104. else
  105. {
  106. if (!lstrcmp(pszName, phi->szName))
  107. break; // Found match
  108. }
  109. }
  110. phiPrev = phi; // Keep the previous item
  111. phi = phi->phiNext;
  112. }
  113. //
  114. // Sortof gross, but do the work here
  115. //
  116. switch (iOp)
  117. {
  118. case ADDHASHITEM:
  119. if (phi)
  120. {
  121. // Simply increment the reference count
  122. #ifdef HITTRACE
  123. DebugMsg(DM_TRACE, "Add Hit on '%s'", pszName);
  124. #endif
  125. phi->wCount++;
  126. }
  127. else
  128. {
  129. #ifdef HITTRACE
  130. DebugMsg(DM_TRACE, "Add MISS on '%s'", pszName);
  131. #endif
  132. // Not Found, try to allocate it out of the heap
  133. phi = (PHASHITEM)Alloc(sizeof(HASHITEM) + cbName + pht->wcbExtra);
  134. if (phi != NULL)
  135. {
  136. // Initialize it
  137. phi->wCount = 1; // One use of it
  138. phi->cbLen = cbName; // The length of it;
  139. lstrcpy(phi->szName, pszName);
  140. // And link it in to the right bucket
  141. phi->phiNext = pht->ahiBuckets[wBucket];
  142. pht->ahiBuckets[wBucket] = phi;
  143. }
  144. }
  145. pht->phiLast = phi;
  146. break;
  147. case DELETEHASHITEM:
  148. if (phi)
  149. {
  150. phi->wCount--;
  151. if (phi->wCount == 0)
  152. {
  153. // Useage count went to zero so unlink it and delete it
  154. if (phiPrev != NULL)
  155. phiPrev->phiNext = phi->phiNext;
  156. else
  157. pht->ahiBuckets[wBucket] = phi->phiNext;
  158. // And delete it
  159. Free(phi);
  160. phi = NULL;
  161. }
  162. }
  163. case LOOKUPHASHITEM:
  164. pht->phiLast = phi;
  165. break;
  166. }
  167. LEAVECRITICAL;
  168. }
  169. else
  170. {
  171. phi = NULL;
  172. }
  173. // If find was passed in simply return it.
  174. return phi ? (LPCSTR)phi->szName : NULL;
  175. }
  176. //--------------------------------------------------------------------------
  177. LPCSTR WINAPI AddHashItem(PHASHTABLE pht, LPCSTR lpszStr)
  178. {
  179. return LookupItemInHashTable(pht, lpszStr, ADDHASHITEM);
  180. }
  181. //--------------------------------------------------------------------------
  182. LPCSTR WINAPI DeleteHashItem(PHASHTABLE pht, LPCSTR lpszStr)
  183. {
  184. return LookupItemInHashTable(pht, lpszStr, DELETEHASHITEM);
  185. }
  186. //======================================================================
  187. PHASHTABLE WINAPI CreateHashItemTable(UINT wBuckets, UINT wExtra, BOOL fCaseSensitive)
  188. {
  189. PHASHTABLE pht;
  190. if (wBuckets == 0)
  191. wBuckets = 71;
  192. pht = (PHASHTABLE)Alloc(sizeof(HASHTABLE) + wBuckets * sizeof(PHASHITEM));
  193. if (pht) {
  194. pht->fUpperCase = !fCaseSensitive;
  195. pht->wBuckets = wBuckets;
  196. pht->wcbExtra = wExtra;
  197. }
  198. return pht;
  199. }
  200. //======================================================================
  201. PHASHTABLE NEAR PASCAL GetGlobalHashTable()
  202. {
  203. if (g_pHashTable == NULL) {
  204. g_pHashTable = CreateHashItemTable(71, 0, FALSE);
  205. }
  206. return g_pHashTable;
  207. }