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.

653 lines
14 KiB

  1. #include "precomp.h"
  2. #include "cntlist.h"
  3. CList::CList(void)
  4. :
  5. m_fQueue(FALSE),
  6. m_cMaxEntries(CLIST_DEFAULT_MAX_ITEMS)
  7. {
  8. Init(1);
  9. }
  10. CList::CList(ULONG cMaxItems)
  11. :
  12. m_fQueue(FALSE),
  13. m_cMaxEntries(cMaxItems)
  14. {
  15. Init(1);
  16. }
  17. CList::CList(ULONG cMaxItems, ULONG cSubItems)
  18. :
  19. m_fQueue(FALSE),
  20. m_cMaxEntries(cMaxItems)
  21. {
  22. Init(cSubItems);
  23. }
  24. CList::CList(ULONG cMaxItems, ULONG cSubItems, BOOL fQueue)
  25. :
  26. m_fQueue(fQueue),
  27. m_cMaxEntries(cMaxItems)
  28. {
  29. Init(cSubItems);
  30. }
  31. CList::CList(CList *pSrc)
  32. :
  33. m_fQueue(pSrc->m_fQueue),
  34. m_cMaxEntries(pSrc->GetCount())
  35. {
  36. Init(1);
  37. LPVOID p;
  38. pSrc->Reset();
  39. while (NULL != (p = pSrc->Iterate()))
  40. {
  41. Append(p);
  42. }
  43. }
  44. BOOL CList::Init(ULONG cSubItems)
  45. {
  46. if (m_cMaxEntries < CLIST_DEFAULT_MAX_ITEMS)
  47. {
  48. m_cMaxEntries = CLIST_DEFAULT_MAX_ITEMS;
  49. }
  50. m_cEntries = 0;
  51. m_nHeadOffset = 0;
  52. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  53. m_cSubItems = cSubItems;
  54. // it is kind of bad here because there is no way to return an error.
  55. // unfortunately it won't fault here and later.
  56. DBG_SAVE_FILE_LINE
  57. m_aEntries = (LPVOID *) new char[m_cMaxEntries * m_cSubItems * sizeof(LPVOID)];
  58. CalcKeyArray();
  59. return m_aEntries ? TRUE : FALSE;
  60. }
  61. CList::~CList(void)
  62. {
  63. delete m_aEntries;
  64. }
  65. void CList::CalcKeyArray(void)
  66. {
  67. if (1 == m_cSubItems)
  68. {
  69. m_aKeys = NULL;
  70. }
  71. else
  72. {
  73. ASSERT(2 == m_cSubItems);
  74. m_aKeys = (NULL != m_aEntries) ?
  75. (UINT_PTR *) &m_aEntries[m_cMaxEntries] :
  76. NULL;
  77. }
  78. }
  79. BOOL CList::Expand(void)
  80. {
  81. if (NULL == m_aEntries)
  82. {
  83. // it is impossible.
  84. ASSERT(FALSE);
  85. return Init(m_cSubItems);
  86. }
  87. // the current array is full
  88. ASSERT(m_cEntries == m_cMaxEntries);
  89. // remember the old array to free or to restore
  90. LPVOID *aOldEntries = m_aEntries;
  91. // we need to allocate a bigger array to hold more data.
  92. // the new array has twice the size of the old one
  93. ULONG cNewMaxEntries = m_cMaxEntries << 1;
  94. DBG_SAVE_FILE_LINE
  95. m_aEntries = (LPVOID *) new char[cNewMaxEntries * m_cSubItems * sizeof(LPVOID)];
  96. if (NULL == m_aEntries)
  97. {
  98. // we failed; we have to restore the array and return
  99. m_aEntries = aOldEntries;
  100. return FALSE;
  101. }
  102. // copy the old entries into the new array, starting from the beginning
  103. ULONG nIdx = m_cMaxEntries - m_nHeadOffset;
  104. ::CopyMemory(m_aEntries, &aOldEntries[m_nHeadOffset], nIdx * sizeof(LPVOID));
  105. ::CopyMemory(&m_aEntries[nIdx], aOldEntries, m_nHeadOffset * sizeof(LPVOID));
  106. // set the new max entries (required for the key array)
  107. m_cMaxEntries = cNewMaxEntries;
  108. if (m_cSubItems > 1)
  109. {
  110. ASSERT(2 == m_cSubItems);
  111. UINT_PTR *aOldKeys = m_aKeys;
  112. CalcKeyArray();
  113. ::CopyMemory(m_aKeys, &aOldKeys[m_nHeadOffset], nIdx * sizeof(UINT));
  114. ::CopyMemory(&m_aKeys[nIdx], aOldKeys, m_nHeadOffset * sizeof(UINT));
  115. }
  116. // Free the old array of entries
  117. delete aOldEntries;
  118. // Set the instance variables
  119. m_nHeadOffset = 0;
  120. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  121. return TRUE;
  122. }
  123. BOOL CList::Append(LPVOID pData)
  124. {
  125. if (NULL == m_aEntries || m_cEntries >= m_cMaxEntries)
  126. {
  127. if (! Expand())
  128. {
  129. return FALSE;
  130. }
  131. }
  132. ASSERT(NULL != m_aEntries);
  133. ASSERT(m_cEntries < m_cMaxEntries);
  134. m_aEntries[(m_nHeadOffset + (m_cEntries++)) % m_cMaxEntries] = pData;
  135. return TRUE;
  136. }
  137. BOOL CList::Prepend(LPVOID pData)
  138. {
  139. if (NULL == m_aEntries || m_cEntries >= m_cMaxEntries)
  140. {
  141. if (! Expand())
  142. {
  143. return FALSE;
  144. }
  145. }
  146. ASSERT(NULL != m_aEntries);
  147. ASSERT(m_cEntries < m_cMaxEntries);
  148. m_cEntries++;
  149. m_nHeadOffset = (0 == m_nHeadOffset) ? m_cMaxEntries - 1 : m_nHeadOffset - 1;
  150. m_aEntries[m_nHeadOffset] = pData;
  151. return TRUE;
  152. }
  153. BOOL CList::Find(LPVOID pData)
  154. {
  155. for (ULONG i = 0; i < m_cEntries; i++)
  156. {
  157. if (pData == m_aEntries[(m_nHeadOffset + i) % m_cMaxEntries])
  158. {
  159. return TRUE;
  160. }
  161. }
  162. return FALSE;
  163. }
  164. BOOL CList::Remove(LPVOID pData)
  165. {
  166. ULONG nIdx, nIdxSrc;
  167. for (ULONG i = 0; i < m_cEntries; i++)
  168. {
  169. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  170. if (pData == m_aEntries[nIdx])
  171. {
  172. if (! m_fQueue)
  173. {
  174. // to remove the current, we simply move the last to here.
  175. nIdxSrc = (m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries;
  176. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  177. if (m_cSubItems > 1)
  178. {
  179. ASSERT(2 == m_cSubItems);
  180. m_aKeys[nIdx] = m_aKeys[nIdxSrc];
  181. }
  182. }
  183. else
  184. {
  185. // to preserve the ordering
  186. if (0 == i)
  187. {
  188. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  189. }
  190. else
  191. {
  192. for (ULONG j = i + 1; j < m_cEntries; j++)
  193. {
  194. nIdx = (m_nHeadOffset + j - 1) % m_cMaxEntries;
  195. nIdxSrc = (m_nHeadOffset + j) % m_cMaxEntries;
  196. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  197. if (m_cSubItems > 1)
  198. {
  199. ASSERT(2 == m_cSubItems);
  200. m_aKeys[nIdx] = m_aKeys[nIdxSrc];
  201. }
  202. }
  203. }
  204. }
  205. m_cEntries--;
  206. return TRUE;
  207. }
  208. }
  209. return FALSE;
  210. }
  211. LPVOID CList::Get(void)
  212. {
  213. LPVOID pRet = NULL;
  214. if (m_cEntries > 0)
  215. {
  216. pRet = m_aEntries[m_nHeadOffset];
  217. m_cEntries--;
  218. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  219. }
  220. else
  221. {
  222. pRet = NULL;
  223. }
  224. return pRet;
  225. }
  226. LPVOID CList::Iterate(void)
  227. {
  228. if (0 == m_cEntries)
  229. {
  230. return NULL;
  231. }
  232. if (m_nCurrOffset == CLIST_END_OF_ARRAY_MARK)
  233. {
  234. // start from the beginning
  235. m_nCurrOffset = 0;
  236. }
  237. else
  238. {
  239. if (++m_nCurrOffset >= m_cEntries)
  240. {
  241. // reset the iterator
  242. m_nCurrOffset = CLIST_END_OF_ARRAY_MARK;
  243. return NULL;
  244. }
  245. }
  246. return m_aEntries[(m_nHeadOffset + m_nCurrOffset) % m_cMaxEntries];
  247. }
  248. CList2::CList2(CList2 *pSrc)
  249. :
  250. CList(pSrc->GetCount(), 2, pSrc->m_fQueue)
  251. {
  252. CalcKeyArray();
  253. LPVOID p;
  254. UINT_PTR n;
  255. pSrc->Reset();
  256. while (NULL != (p = pSrc->Iterate(&n)))
  257. {
  258. Append(n, p);
  259. }
  260. }
  261. BOOL CList2::Append(UINT_PTR nKey, LPVOID pData)
  262. {
  263. if (! CList::Append(pData))
  264. {
  265. return FALSE;
  266. }
  267. // after CList::append(), m_cEntries has been incremented,
  268. // therefore, we need decrement it again.
  269. m_aKeys[(m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries] = nKey;
  270. return TRUE;
  271. }
  272. BOOL CList2::Prepend(UINT_PTR nKey, LPVOID pData)
  273. {
  274. if (! CList::Prepend(pData))
  275. {
  276. return FALSE;
  277. }
  278. m_aKeys[m_nHeadOffset] = nKey;
  279. return TRUE;
  280. }
  281. LPVOID CList2::Find(UINT_PTR nKey)
  282. {
  283. ULONG nIdx;
  284. for (ULONG i = 0; i < m_cEntries; i++)
  285. {
  286. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  287. if (nKey == m_aKeys[nIdx])
  288. {
  289. return m_aEntries[nIdx];
  290. }
  291. }
  292. return NULL;
  293. }
  294. LPVOID CList2::Remove(UINT_PTR nKey)
  295. {
  296. ULONG nIdx, nIdxSrc;
  297. for (ULONG i = 0; i < m_cEntries; i++)
  298. {
  299. nIdx = (m_nHeadOffset + i) % m_cMaxEntries;
  300. if (nKey == m_aKeys[nIdx])
  301. {
  302. LPVOID pRet = m_aEntries[nIdx];
  303. if (! m_fQueue)
  304. {
  305. // to remove the current, we simply move the last to here.
  306. nIdxSrc = (m_nHeadOffset + (m_cEntries - 1)) % m_cMaxEntries;
  307. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  308. m_aKeys[nIdx] = m_aKeys[nIdxSrc];
  309. }
  310. else
  311. {
  312. // to preserve the ordering
  313. if (0 == i)
  314. {
  315. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  316. }
  317. else
  318. {
  319. for (ULONG j = i + 1; j < m_cEntries; j++)
  320. {
  321. nIdx = (m_nHeadOffset + j - 1) % m_cMaxEntries;
  322. nIdxSrc = (m_nHeadOffset + j) % m_cMaxEntries;
  323. m_aEntries[nIdx] = m_aEntries[nIdxSrc];
  324. m_aKeys[nIdx] = m_aKeys[nIdxSrc];
  325. }
  326. }
  327. }
  328. m_cEntries--;
  329. return pRet;
  330. }
  331. }
  332. return NULL;
  333. }
  334. LPVOID CList2::Get(UINT_PTR *pnKey)
  335. {
  336. LPVOID pRet;
  337. if (m_cEntries > 0)
  338. {
  339. pRet = m_aEntries[m_nHeadOffset];
  340. *pnKey = m_aKeys[m_nHeadOffset];
  341. m_cEntries--;
  342. m_nHeadOffset = (m_nHeadOffset + 1) % m_cMaxEntries;
  343. }
  344. else
  345. {
  346. pRet = NULL;
  347. *pnKey = 0;
  348. }
  349. return pRet;
  350. }
  351. LPVOID CList2::PeekHead(UINT_PTR *pnKey)
  352. {
  353. LPVOID pRet;
  354. if (m_cEntries > 0)
  355. {
  356. pRet = m_aEntries[m_nHeadOffset];
  357. *pnKey = m_aKeys[m_nHeadOffset];
  358. }
  359. else
  360. {
  361. pRet = NULL;
  362. *pnKey = 0;
  363. }
  364. return pRet;
  365. }
  366. LPVOID CList2::Iterate(UINT_PTR *pnKey)
  367. {
  368. LPVOID p = CList::Iterate();
  369. *pnKey = (NULL != p) ? m_aKeys[(m_nHeadOffset + m_nCurrOffset) % m_cMaxEntries] : 0;
  370. return p;
  371. }
  372. #ifdef ENABLE_HASHED_LIST2
  373. CHashedList2::CHashedList2(ULONG cBuckets, ULONG cInitItemsPerBucket)
  374. :
  375. m_cBuckets(cBuckets),
  376. m_cInitItemsPerBucket(cInitItemsPerBucket),
  377. m_cEntries(0),
  378. m_nCurrBucket(0)
  379. {
  380. m_aBuckets = new CList2* [m_cBuckets];
  381. ASSERT(NULL != m_aBuckets);
  382. if (NULL != m_aBuckets)
  383. {
  384. ::ZeroMemory(m_aBuckets, m_cBuckets * sizeof(CList2*));
  385. }
  386. }
  387. CHashedList2::CHashedList2(CHashedList2 *pSrc)
  388. :
  389. m_cBuckets(pSrc->m_cBuckets),
  390. m_cInitItemsPerBucket(pSrc->m_cInitItemsPerBucket),
  391. m_cEntries(0),
  392. m_nCurrBucket(0)
  393. {
  394. LPVOID p;
  395. UINT n;
  396. m_aBuckets = new CList2* [m_cBuckets];
  397. ASSERT(NULL != m_aBuckets);
  398. if (NULL != m_aBuckets)
  399. {
  400. ::ZeroMemory(m_aBuckets, m_cBuckets * sizeof(CList2*));
  401. pSrc->Reset();
  402. while (NULL != (p = pSrc->Iterate(&n)))
  403. {
  404. Insert(n, p);
  405. }
  406. }
  407. }
  408. CHashedList2::~CHashedList2(void)
  409. {
  410. if (NULL != m_aBuckets)
  411. {
  412. for (ULONG i = 0; i < m_cBuckets; i++)
  413. {
  414. delete m_aBuckets[i];
  415. }
  416. delete [] m_aBuckets;
  417. }
  418. }
  419. BOOL CHashedList2::Insert(UINT nKey, LPVOID pData)
  420. {
  421. if (NULL != m_aBuckets)
  422. {
  423. ULONG nBucket = GetHashValue(nKey);
  424. if (NULL == m_aBuckets[nBucket])
  425. {
  426. m_aBuckets[nBucket] = new CList2(m_cInitItemsPerBucket);
  427. }
  428. ASSERT(NULL != m_aBuckets[nBucket]);
  429. if (NULL != m_aBuckets[nBucket])
  430. {
  431. if (m_aBuckets[nBucket]->Append(nKey, pData))
  432. {
  433. m_cEntries++;
  434. return TRUE;
  435. }
  436. }
  437. }
  438. return FALSE;
  439. }
  440. LPVOID CHashedList2::Find(UINT nKey)
  441. {
  442. if (NULL != m_aBuckets)
  443. {
  444. ULONG nBucket = GetHashValue(nKey);
  445. if (NULL != m_aBuckets[nBucket])
  446. {
  447. return m_aBuckets[nBucket]->Find(nKey);
  448. }
  449. }
  450. return NULL;
  451. }
  452. LPVOID CHashedList2::Remove(UINT nKey)
  453. {
  454. if (NULL != m_aBuckets)
  455. {
  456. ULONG nBucket = GetHashValue(nKey);
  457. if (NULL != m_aBuckets[nBucket])
  458. {
  459. LPVOID pRet = m_aBuckets[nBucket]->Remove(nKey);
  460. if (NULL != pRet)
  461. {
  462. m_cEntries--;
  463. return pRet;
  464. }
  465. }
  466. }
  467. return NULL;
  468. }
  469. LPVOID CHashedList2::Get(UINT *pnKey)
  470. {
  471. if (NULL != m_aBuckets)
  472. {
  473. if (m_cEntries)
  474. {
  475. for (ULONG i = 0; i < m_cBuckets; i++)
  476. {
  477. if (NULL != m_aBuckets[i])
  478. {
  479. LPVOID pRet = m_aBuckets[i]->Get(pnKey);
  480. if (NULL != pRet)
  481. {
  482. m_cEntries--;
  483. return pRet;
  484. }
  485. }
  486. }
  487. }
  488. }
  489. return NULL;
  490. }
  491. LPVOID CHashedList2::Iterate(UINT *pnKey)
  492. {
  493. if (NULL != m_aBuckets)
  494. {
  495. for (ULONG i = m_nCurrBucket; i < m_cBuckets; i++)
  496. {
  497. if (NULL != m_aBuckets[i])
  498. {
  499. LPVOID pRet = m_aBuckets[i]->Iterate(pnKey);
  500. if (NULL != pRet)
  501. {
  502. m_nCurrBucket = i;
  503. return pRet;
  504. }
  505. }
  506. }
  507. }
  508. m_nCurrBucket = m_cBuckets; // over
  509. return NULL;
  510. }
  511. void CHashedList2::Reset(void)
  512. {
  513. m_nCurrBucket = 0;
  514. if (NULL != m_aBuckets)
  515. {
  516. for (ULONG i = 0; i < m_cBuckets; i++)
  517. {
  518. if (NULL != m_aBuckets[i])
  519. {
  520. m_aBuckets[i]->Reset();
  521. }
  522. }
  523. }
  524. }
  525. void CHashedList2::Clear(void)
  526. {
  527. m_cEntries = 0;
  528. m_nCurrBucket = 0;
  529. if (NULL != m_aBuckets)
  530. {
  531. for (ULONG i = 0; i < m_cBuckets; i++)
  532. {
  533. if (NULL != m_aBuckets[i])
  534. {
  535. m_aBuckets[i]->Clear();
  536. }
  537. }
  538. }
  539. };
  540. ULONG CHashedList2::GetHashValue(UINT nKey)
  541. {
  542. const UINT PRIME_NUMBER_1 = 89;
  543. const UINT PRIME_NUMBER_2 = 13;
  544. return ((ULONG) (nKey * PRIME_NUMBER_1 + PRIME_NUMBER_2) % m_cBuckets);
  545. }
  546. #endif // ENABLE_HASHED_LIST2
  547.