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.

342 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. hashtable.h
  5. Abstract:
  6. Implementation of:
  7. CPool<T>, CStringPool, CHashTableElement<T>
  8. Author:
  9. Mohit Srivastava 10-Nov-2000
  10. Revision History:
  11. --*/
  12. #include "iisprov.h"
  13. template CPool<METABASE_PROPERTY>;
  14. template CHashTable<METABASE_PROPERTY*>;
  15. template CPool<WMI_CLASS>;
  16. template CHashTable<WMI_CLASS*>;
  17. template CPool<WMI_ASSOCIATION>;
  18. template CHashTable<WMI_ASSOCIATION*>;
  19. template CPool<METABASE_KEYTYPE>;
  20. template CHashTable<METABASE_KEYTYPE*>;
  21. template CArrayPool<wchar_t, ::STRING_POOL_STRING_SIZE>;
  22. template CArrayPool<METABASE_PROPERTY*, 10>;
  23. template CArrayPool<BYTE, 10>;
  24. template CPool<METABASE_KEYTYPE_NODE>;
  25. //
  26. // CPool<T>
  27. //
  28. template <class T>
  29. HRESULT CPool<T>::Initialize(ULONG i_iFirstBucketSize)
  30. /*++
  31. Synopsis:
  32. Set up data structures:
  33. Initialize array to size CPool::ARRAY_SIZE
  34. Create first bucket of size i_iFirstBucketSize
  35. Arguments: [i_iFirstBucketSize] -
  36. Return Value:
  37. S_OK, E_OUTOFMEMORY
  38. --*/
  39. {
  40. DBG_ASSERT(m_bInitCalled == false);
  41. DBG_ASSERT(m_bInitSuccessful == false);
  42. m_bInitCalled = true;
  43. HRESULT hr = S_OK;
  44. m_apBuckets = new T*[ARRAY_SIZE];
  45. if(m_apBuckets == NULL)
  46. {
  47. hr = E_OUTOFMEMORY;
  48. goto exit;
  49. }
  50. m_iArraySize = ARRAY_SIZE;
  51. m_iArrayPosition = 1;
  52. m_apBuckets[0] = new T[i_iFirstBucketSize];
  53. if(m_apBuckets[0] == NULL)
  54. {
  55. hr = E_OUTOFMEMORY;
  56. goto exit;
  57. }
  58. m_iCurrentBucketSize = i_iFirstBucketSize;
  59. m_iFirstBucketSize = i_iFirstBucketSize;
  60. m_iCurrentBucketPosition = 0;
  61. exit:
  62. if(SUCCEEDED(hr))
  63. {
  64. m_bInitSuccessful = true;
  65. }
  66. return hr;
  67. }
  68. template <class T>
  69. HRESULT CPool<T>::GetNewElement(T** o_ppElement)
  70. /*++
  71. Synopsis:
  72. Normally, just a matter of returning pointer to next spot in bucket.
  73. May have to create a new bucket and/or grow the array, however.
  74. Arguments: [o_ppElement] -
  75. Return Value:
  76. S_OK, E_OUTOFMEMORY
  77. --*/{
  78. DBG_ASSERT(m_bInitCalled == true);
  79. DBG_ASSERT(m_bInitSuccessful == true);
  80. DBG_ASSERT(o_ppElement != NULL);
  81. HRESULT hr = S_OK;
  82. //
  83. // Check to see if we need to move on to the next bucket
  84. //
  85. if(m_iCurrentBucketPosition == m_iCurrentBucketSize)
  86. {
  87. //
  88. // Check to see if we need to grow the array
  89. //
  90. if(m_iArrayPosition == m_iArraySize)
  91. {
  92. T** apBucketsNew;
  93. apBucketsNew = new T*[m_iArraySize*2];
  94. if(m_apBuckets == NULL)
  95. {
  96. return E_OUTOFMEMORY;
  97. }
  98. memcpy(apBucketsNew, m_apBuckets, m_iArraySize * sizeof(T*));
  99. delete [] m_apBuckets;
  100. m_apBuckets = apBucketsNew;
  101. m_iArraySize *= 2;
  102. }
  103. T* pBucketNew;
  104. pBucketNew = new T[m_iCurrentBucketSize*2];
  105. if(pBucketNew == NULL)
  106. {
  107. return E_OUTOFMEMORY;
  108. }
  109. m_apBuckets[m_iArrayPosition] = pBucketNew;
  110. m_iCurrentBucketSize *= 2;
  111. m_iCurrentBucketPosition = 0;
  112. m_iArrayPosition++;
  113. }
  114. *o_ppElement = &m_apBuckets[m_iArrayPosition-1][m_iCurrentBucketPosition];
  115. m_iCurrentBucketPosition++;
  116. return hr;
  117. }
  118. template <class T>
  119. T* CPool<T>::Lookup(ULONG i_idx) const
  120. /*++
  121. Synopsis:
  122. Looks up data in pool by index
  123. Arguments: [i_idx] - Valid Range is 0 to GetUsed()-1
  124. Return Value:
  125. A pointer to the data unless i_idx is out of range.
  126. --*/
  127. {
  128. DBG_ASSERT(m_bInitCalled == true);
  129. DBG_ASSERT(m_bInitSuccessful == true);
  130. //
  131. // Total element capacity of all buckets up to and including the current one
  132. // in the for loop below
  133. //
  134. ULONG iElementsCovered = 0;
  135. ULONG iBucketPos = 0;
  136. if (i_idx >= GetUsed())
  137. {
  138. return NULL;
  139. }
  140. for(ULONG i = 0; i < m_iArrayPosition; i++)
  141. {
  142. iElementsCovered = iElementsCovered + (1 << i)*(m_iFirstBucketSize);
  143. if(i_idx < iElementsCovered)
  144. {
  145. iBucketPos =
  146. i_idx - ( iElementsCovered - (1 << i)*(m_iFirstBucketSize) );
  147. return &m_apBuckets[i][iBucketPos];
  148. }
  149. }
  150. return NULL;
  151. }
  152. //
  153. // CArrayPool
  154. //
  155. template <class T, ULONG size>
  156. HRESULT CArrayPool<T, size>::Initialize()
  157. /*++
  158. Synopsis:
  159. should only be called once
  160. Return Value:
  161. --*/
  162. {
  163. HRESULT hr = S_OK;
  164. hr = m_PoolFixedSize.Initialize(FIRST_BUCKET_SIZE);
  165. if(FAILED(hr))
  166. {
  167. return hr;
  168. }
  169. hr = m_PoolDynamic.Initialize(FIRST_BUCKET_SIZE);
  170. if(FAILED(hr))
  171. {
  172. return hr;
  173. }
  174. return hr;
  175. }
  176. template <class T, ULONG size>
  177. HRESULT CArrayPool<T, size>::GetNewArray(ULONG i_cElem, T** o_ppElem)
  178. /*++
  179. Synopsis:
  180. Fills o_ppElem from either the fixedsize or dynamic pool based on the
  181. requested size.
  182. Arguments: [i_cElem] - number of elements caller wants in new array
  183. [o_ppElem] - receives the new array
  184. Return Value:
  185. --*/
  186. {
  187. DBG_ASSERT(o_ppElem != NULL);
  188. HRESULT hr = S_OK;
  189. T** ppNew = NULL;
  190. T* pNew = NULL;
  191. if(i_cElem <= size)
  192. {
  193. hr = m_PoolFixedSize.GetNewElement((CArrayPoolEntry<T,size>**)&pNew);
  194. if(FAILED(hr))
  195. {
  196. return hr;
  197. }
  198. ppNew = &pNew;
  199. }
  200. else
  201. {
  202. hr = m_PoolDynamic.GetNewElement(&ppNew);
  203. if(FAILED(hr))
  204. {
  205. return hr;
  206. }
  207. *ppNew = NULL;
  208. *ppNew = new T[i_cElem+1];
  209. if(*ppNew == NULL)
  210. {
  211. return E_OUTOFMEMORY;
  212. }
  213. }
  214. *o_ppElem = *ppNew;
  215. return hr;
  216. }
  217. //
  218. // for debugging only
  219. // if msb set, goto dynamic pool
  220. // else use fixedsize pool
  221. //
  222. template <class T, ULONG size>
  223. T* CArrayPool<T, size>::Lookup(ULONG i_idx) const
  224. {
  225. ULONG i_msb;
  226. i_msb = i_idx >> 31;
  227. if(i_msb == 0)
  228. {
  229. return (T *)(m_PoolFixedSize.Lookup(i_idx));
  230. }
  231. else {
  232. T** pElem = m_PoolDynamic.Lookup( i_idx - (ULONG)(1 << 31) );
  233. if(pElem == NULL)
  234. {
  235. return NULL;
  236. }
  237. else
  238. {
  239. return *pElem;
  240. }
  241. }
  242. }
  243. //
  244. // CStringPool
  245. //
  246. HRESULT CStringPool::GetNewString(LPCWSTR i_wsz, ULONG i_cch, LPWSTR* o_pwsz)
  247. {
  248. DBG_ASSERT(o_pwsz != NULL);
  249. HRESULT hr;
  250. hr = GetNewArray(i_cch+1, o_pwsz);
  251. if(FAILED(hr))
  252. {
  253. return hr;
  254. }
  255. memcpy(*o_pwsz, i_wsz, (i_cch+1)*sizeof(wchar_t));
  256. return hr;
  257. }
  258. HRESULT CStringPool::GetNewString(LPCWSTR i_wsz, LPWSTR* o_pwsz)
  259. {
  260. return GetNewString(i_wsz, wcslen(i_wsz), o_pwsz);
  261. }
  262. //
  263. // for debugging only
  264. //
  265. void CStringPool::ToConsole() const
  266. {
  267. ULONG i;
  268. for(i = 0; i < m_PoolFixedSize.GetUsed(); i++)
  269. {
  270. wprintf(L"%s\n", Lookup(i));
  271. }
  272. for(i = 0; i < m_PoolDynamic.GetUsed(); i++)
  273. {
  274. wprintf( L"%s\n", Lookup( i | (1 << 31) ) );
  275. }
  276. }