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.

284 lines
6.4 KiB

  1. //////////////////////////////////////////////////////////////////////
  2. // Hash.cpp: implementation of the CHash class.
  3. //
  4. // Created by JOEM 03-2000
  5. // Copyright (C) 2000 Microsoft Corporation
  6. // All Rights Reserved
  7. //
  8. /////////////////////////////////////////////////////// JOEM 3-2000 //
  9. #include "stdafx.h"
  10. #include "Hash.h"
  11. #include "common.h"
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. /////////////////////////////////////////////////////// JOEM 3-2000 //
  15. CHashNode::CHashNode()
  16. {
  17. m_pszKey = NULL;
  18. m_pValue = NULL;
  19. m_pNext = NULL;
  20. }
  21. CHashNode::~CHashNode()
  22. {
  23. if ( m_pszKey )
  24. {
  25. free(m_pszKey);
  26. m_pszKey = NULL;
  27. }
  28. if ( m_pValue )
  29. {
  30. m_pValue->Release();
  31. m_pValue = NULL;
  32. }
  33. if ( m_pNext )
  34. {
  35. delete m_pNext;
  36. m_pNext = NULL;
  37. }
  38. }
  39. //////////////////////////////////////////////////////////////////////
  40. // Construction/Destruction
  41. /////////////////////////////////////////////////////// JOEM 3-2000 //
  42. CHash::CHash()
  43. {
  44. memset (m_heads, 0, sizeof(m_heads));
  45. }
  46. //////////////////////////////////////////////////////////////////////
  47. // CHash
  48. /////////////////////////////////////////////////////// JOEM 3-2000 //
  49. CHash::~CHash()
  50. {
  51. for (int i=0; i < HASH_SIZE; i++)
  52. {
  53. if (m_heads[i])
  54. {
  55. delete m_heads[i];
  56. }
  57. }
  58. }
  59. //////////////////////////////////////////////////////////////////////
  60. // CHash
  61. //
  62. // BuildEntry
  63. /////////////////////////////////////////////////////// JOEM 3-2000 //
  64. HRESULT CHash::BuildEntry(const WCHAR* pszKey, IUnknown* pValue)
  65. {
  66. SPDBG_FUNC( "CHash::BuildEntry" );
  67. HRESULT hr = S_OK;
  68. CHashNode* pNewNode = NULL;
  69. CHashNode* pTempNode = NULL;
  70. CHashNode* pLastNode = NULL;
  71. int iIndex;
  72. SPDBG_ASSERT (pszKey);
  73. SPDBG_ASSERT (pValue);
  74. if (pszKey && *pszKey)
  75. {
  76. iIndex = HashValue((WCHAR*)pszKey);
  77. pTempNode = m_heads[iIndex];
  78. // Look for the key, see if we already have an entry
  79. while (pTempNode)
  80. {
  81. if ( wcscmp(pTempNode->m_pszKey, pszKey) == 0)
  82. {
  83. break;
  84. }
  85. pLastNode = pTempNode;
  86. pTempNode = pTempNode->m_pNext;
  87. }
  88. // If there is an entry, report error
  89. if (pTempNode)
  90. {
  91. hr = E_INVALIDARG;
  92. }
  93. if ( SUCCEEDED(hr) )
  94. {
  95. pNewNode = new CHashNode;
  96. if ( !pNewNode )
  97. {
  98. hr = E_OUTOFMEMORY;
  99. }
  100. }
  101. if ( SUCCEEDED(hr) )
  102. {
  103. if ( (pNewNode->m_pszKey = wcsdup (pszKey)) == NULL )
  104. {
  105. hr = E_OUTOFMEMORY;
  106. }
  107. }
  108. if ( SUCCEEDED(hr) )
  109. {
  110. pNewNode->m_pValue = pValue;
  111. pValue->AddRef();
  112. if (pLastNode)
  113. {
  114. pLastNode->m_pNext = pNewNode;
  115. }
  116. else
  117. {
  118. m_heads[iIndex] = pNewNode;
  119. }
  120. }
  121. if ( FAILED(hr) && pNewNode )
  122. {
  123. free (pNewNode);
  124. pNewNode = NULL;
  125. }
  126. }
  127. SPDBG_REPORT_ON_FAIL( hr );
  128. return hr;
  129. }
  130. //////////////////////////////////////////////////////////////////////
  131. // CHash
  132. //
  133. // DeleteEntry
  134. /////////////////////////////////////////////////////// JOEM 3-2000 //
  135. HRESULT CHash::DeleteEntry(const WCHAR *pszKey)
  136. {
  137. SPDBG_FUNC( "CHash::DeleteEntry" );
  138. HRESULT hr = E_INVALIDARG;
  139. CHashNode* pTempNode = NULL;
  140. CHashNode* pLastNode = NULL;
  141. int iIndex;
  142. SPDBG_ASSERT (pszKey);
  143. iIndex = HashValue((WCHAR*)pszKey);
  144. pTempNode = m_heads[iIndex];
  145. while (pTempNode)
  146. {
  147. if ( wcscmp (pTempNode->m_pszKey, pszKey) == 0 )
  148. {
  149. CHashNode* pRem = pTempNode;
  150. if (pLastNode)
  151. {
  152. pLastNode->m_pNext = pRem->m_pNext;
  153. }
  154. else
  155. {
  156. m_heads[iIndex] = pRem->m_pNext;
  157. }
  158. pRem->m_pNext = NULL; //Avoid cleaning up the rest of the chain
  159. delete pRem;
  160. hr = S_OK;
  161. break;
  162. }
  163. pLastNode = pTempNode;
  164. pTempNode = pTempNode->m_pNext;
  165. }
  166. SPDBG_REPORT_ON_FAIL( hr );
  167. return hr;
  168. }
  169. //////////////////////////////////////////////////////////////////////
  170. // CHash
  171. //
  172. // Find
  173. /////////////////////////////////////////////////////// JOEM 3-2000 //
  174. IUnknown* CHash::Find(const WCHAR *pszKey)
  175. {
  176. SPDBG_FUNC( "CHash::Find" );
  177. CHashNode* pTempNode = NULL;
  178. SPDBG_ASSERT (*pszKey);
  179. pTempNode = m_heads[HashValue((WCHAR*)pszKey)];
  180. while (pTempNode)
  181. {
  182. if ( wcscmp (pTempNode->m_pszKey, pszKey) == 0 )
  183. {
  184. return pTempNode->m_pValue;
  185. }
  186. pTempNode = pTempNode->m_pNext;
  187. }
  188. return NULL;
  189. }
  190. //////////////////////////////////////////////////////////////////////
  191. // CHash
  192. //
  193. // NextKey
  194. /////////////////////////////////////////////////////// JOEM 3-2000 //
  195. HRESULT CHash::NextKey(USHORT *punIdx1, USHORT* punIdx2, WCHAR** ppszKey)
  196. {
  197. SPDBG_FUNC( "CHash::NextKey" );
  198. CHashNode* pNode = NULL;
  199. USHORT i = 0;
  200. SPDBG_ASSERT (punIdx1);
  201. SPDBG_ASSERT (punIdx2);
  202. *ppszKey = NULL;
  203. if (m_heads)
  204. {
  205. while (*punIdx1 < HASH_SIZE )
  206. {
  207. if ((pNode = m_heads[*punIdx1]) != NULL)
  208. {
  209. for ( i=0; i<*punIdx2 && pNode->m_pNext; i++)
  210. {
  211. pNode = pNode->m_pNext;
  212. }
  213. if (i==*punIdx2)
  214. {
  215. (*punIdx2)++;
  216. *ppszKey = pNode->m_pszKey;
  217. break;
  218. }
  219. }
  220. (*punIdx1)++;
  221. *punIdx2 = 0;
  222. }
  223. }
  224. return S_OK;
  225. }
  226. //////////////////////////////////////////////////////////////////////
  227. // CHash
  228. //
  229. // HashValue
  230. /////////////////////////////////////////////////////// JOEM 3-2000 //
  231. int CHash::HashValue (WCHAR *pszKey)
  232. {
  233. SPDBG_FUNC( "CHash::HashValue" );
  234. USHORT unVal = 0;
  235. SPDBG_ASSERT (pszKey);
  236. for (unVal=0; *pszKey ; pszKey++)
  237. {
  238. unVal = (64*unVal + *pszKey) % HASH_SIZE;
  239. }
  240. return unVal;
  241. }