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.

301 lines
6.6 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. hashtable.h
  5. Abstract:
  6. Definition of:
  7. CPool<T>, CStringPool, CHashTableElement<T>
  8. Implementation of:
  9. CHashTable<T>
  10. Author:
  11. Mohit Srivastava 10-Nov-2000
  12. Revision History:
  13. --*/
  14. #ifndef _hashtable_h_
  15. #define _hashtable_h_
  16. #include <lkrhash.h>
  17. const ULONG POOL_ARRAY_SIZE = 10;
  18. const ULONG HASH_TABLE_POOL_SIZE = 10;
  19. const ULONG STRING_POOL_STRING_SIZE = 64;
  20. //
  21. // This is an array of pointers to arrays (aka buckets).
  22. // -You pass the size of the first bucket to Initialize.
  23. // -When first bucket is full, a new bucket is created
  24. // that is twice as big as the last one.
  25. // -When the array itself is full, it is doubled and the
  26. // bucket pointers from the old array are copied. Then
  27. // the old array is cleaned up.
  28. //
  29. template <class T> class CPool
  30. {
  31. public:
  32. CPool() :
  33. m_bInitCalled(false),
  34. m_bInitSuccessful(false),
  35. m_apBuckets(NULL),
  36. m_iArrayPosition(0),
  37. m_iArraySize(0),
  38. m_iCurrentBucketPosition(0),
  39. m_iCurrentBucketSize(0),
  40. m_iFirstBucketSize(0) {}
  41. ~CPool()
  42. {
  43. for(ULONG i = 0; i < m_iArrayPosition; i++)
  44. {
  45. delete [] m_apBuckets[i];
  46. }
  47. delete [] m_apBuckets;
  48. }
  49. HRESULT Initialize(ULONG i_iFirstBucketSize);
  50. HRESULT GetNewElement(T** o_ppElement);
  51. T* Lookup(ULONG i_idx) const;
  52. ULONG GetUsed() const
  53. {
  54. return (GetSize() - m_iCurrentBucketSize) + m_iCurrentBucketPosition;
  55. }
  56. ULONG GetSize() const
  57. {
  58. return (2 * m_iCurrentBucketSize - m_iFirstBucketSize);
  59. }
  60. private:
  61. //
  62. // Change this as necessary for best performance.
  63. //
  64. static const ULONG ARRAY_SIZE = ::POOL_ARRAY_SIZE;
  65. bool m_bInitCalled;
  66. bool m_bInitSuccessful;
  67. ULONG m_iCurrentBucketPosition;
  68. ULONG m_iCurrentBucketSize;
  69. ULONG m_iFirstBucketSize;
  70. ULONG m_iArraySize;
  71. ULONG m_iArrayPosition;
  72. T** m_apBuckets;
  73. };
  74. //
  75. // CArrayPool contains two pools.
  76. // If a user calls GetNewArray with i <= size, then we serve request from fixedsize pool.
  77. // If i > size, then we serve request from dynamic pool. In this case, we need to perform
  78. // a new since the dynamic pool is a pool of ptrs to T.
  79. //
  80. template <class T, ULONG size>
  81. struct CArrayPoolEntry
  82. {
  83. T m_data[size];
  84. };
  85. template <class T, ULONG size> class CArrayPool
  86. {
  87. public:
  88. CArrayPool() {}
  89. virtual ~CArrayPool()
  90. {
  91. T* pElem;
  92. for(ULONG i = 0; i < m_PoolDynamic.GetUsed(); i++)
  93. {
  94. pElem = *m_PoolDynamic.Lookup(i);
  95. delete [] pElem;
  96. }
  97. }
  98. HRESULT Initialize();
  99. HRESULT GetNewArray(ULONG i_cElem, T** o_ppElem);
  100. T* Lookup(ULONG i_idx) const;
  101. protected:
  102. CPool< CArrayPoolEntry<T, size> > m_PoolFixedSize;
  103. CPool< T * > m_PoolDynamic;
  104. private:
  105. //
  106. // This is passed to constructor of the embedded CPools.
  107. //
  108. static const FIRST_BUCKET_SIZE = 10;
  109. };
  110. class CStringPool: public CArrayPool<wchar_t, ::STRING_POOL_STRING_SIZE>
  111. {
  112. public:
  113. void ToConsole() const;
  114. HRESULT GetNewString(LPCWSTR i_wsz, LPWSTR* o_pwsz);
  115. HRESULT GetNewString(LPCWSTR i_wsz, ULONG i_cch, LPWSTR* o_pwsz);
  116. };
  117. template <class T> class CHashTableElement
  118. {
  119. public:
  120. LPWSTR m_wszKey;
  121. T m_data;
  122. ULONG m_idx;
  123. };
  124. template <class T>
  125. class CHashTable : public CTypedHashTable<CHashTable, const CHashTableElement<T>, const WCHAR*>
  126. {
  127. public:
  128. CHashTable() : CTypedHashTable<CHashTable, const CHashTableElement<T>, const WCHAR*>("n")
  129. {
  130. m_idxCur = 0;
  131. }
  132. ~CHashTable()
  133. {
  134. }
  135. public:
  136. //
  137. // These 4 functions are callbacks and must be implemented.
  138. // The user of CHashTable should NOT call these explicitly.
  139. //
  140. static const WCHAR* ExtractKey(
  141. const CHashTableElement<T>* i_pElem)
  142. {
  143. return i_pElem->m_wszKey;
  144. }
  145. static DWORD CalcKeyHash(
  146. const WCHAR* i_wszKey)
  147. {
  148. return HashStringNoCase(i_wszKey);
  149. }
  150. static bool EqualKeys(
  151. const WCHAR* i_wszKey1,
  152. const WCHAR* i_wszKey2)
  153. {
  154. return ( _wcsicmp( i_wszKey1, i_wszKey2 ) == 0 );
  155. }
  156. static void AddRefRecord(
  157. const CHashTableElement<T>* i_pElem,
  158. int i_iIncrementAmount)
  159. {
  160. //
  161. // do nothing
  162. //
  163. }
  164. //
  165. // The following functions are the functions that the user should
  166. // actually call.
  167. //
  168. HRESULT Wmi_Initialize()
  169. {
  170. return m_pool.Initialize(HASH_TABLE_POOL_SIZE);
  171. }
  172. HRESULT Wmi_Insert(LPWSTR i_wszKey, T i_DataNew)
  173. {
  174. DBG_ASSERT(i_wszKey != NULL);
  175. HRESULT hr = WBEM_S_NO_ERROR;
  176. LK_RETCODE lkrc;
  177. CHashTableElement<T>* pElementNew;
  178. hr = m_pool.GetNewElement(&pElementNew);
  179. if(FAILED(hr))
  180. {
  181. goto exit;
  182. }
  183. pElementNew->m_data = i_DataNew;
  184. pElementNew->m_wszKey = i_wszKey;
  185. pElementNew->m_idx = m_idxCur;
  186. lkrc = InsertRecord(pElementNew);
  187. if(lkrc != LK_SUCCESS)
  188. {
  189. hr = Wmi_LKRToHR(lkrc);
  190. goto exit;
  191. }
  192. exit:
  193. if(SUCCEEDED(hr))
  194. {
  195. m_idxCur++;
  196. }
  197. return hr;
  198. }
  199. HRESULT Wmi_GetByKey(LPCWSTR i_wszKey, T* o_pData, ULONG *o_idx)
  200. {
  201. DBG_ASSERT(i_wszKey != NULL);
  202. DBG_ASSERT(o_pData != NULL);
  203. *o_pData = NULL;
  204. HRESULT hr = WBEM_S_NO_ERROR;
  205. LK_RETCODE lkrc;
  206. const CHashTableElement<T>* pElem = NULL;
  207. lkrc = FindKey(i_wszKey, &pElem);
  208. if(lkrc != LK_SUCCESS)
  209. {
  210. hr = Wmi_LKRToHR(lkrc);
  211. return hr;
  212. }
  213. *o_pData = pElem->m_data;
  214. if(o_idx != NULL)
  215. {
  216. *o_idx = pElem->m_idx;
  217. }
  218. return hr;
  219. }
  220. HRESULT Wmi_GetByKey(LPCWSTR i_wszKey, T* o_pData)
  221. {
  222. return Wmi_GetByKey(i_wszKey, o_pData, NULL);
  223. }
  224. HRESULT Wmi_LKRToHR(LK_RETCODE i_lkrc)
  225. {
  226. if(i_lkrc == LK_SUCCESS)
  227. {
  228. return WBEM_S_NO_ERROR;
  229. }
  230. switch(i_lkrc)
  231. {
  232. case LK_ALLOC_FAIL:
  233. return WBEM_E_OUT_OF_MEMORY;
  234. default:
  235. return E_FAIL;
  236. }
  237. }
  238. ULONG Wmi_GetNumElements()
  239. {
  240. CLKRHashTableStats stats;
  241. stats = GetStatistics();
  242. DBG_ASSERT(stats.RecordCount == m_idxCur);
  243. return m_idxCur;
  244. }
  245. private:
  246. CPool< CHashTableElement<T> > m_pool;
  247. ULONG m_idxCur;
  248. };
  249. //
  250. #endif // _hashtable_h_