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.

1276 lines
35 KiB

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (c) 1992-2001 Microsoft Corporation, All Rights Reserved
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #ifndef __PROVTEMPL_H__
  11. #define __PROVTEMPL_H__
  12. #ifndef __PROVPLEX_H__
  13. #include "plex.h"
  14. #endif
  15. //#include <new.h>
  16. #include "provstd.h"
  17. #include "provstr.h"
  18. template<class TYPE>
  19. inline void AFXAPI ConstructElements(TYPE* pElements, int nCount)
  20. {
  21. // first do bit-wise zero initialization
  22. memset((void*)pElements, 0, nCount * sizeof(TYPE));
  23. // then call the constructor(s)
  24. for (; nCount--; pElements++)
  25. ::new((void*)pElements) TYPE;
  26. }
  27. template<class TYPE>
  28. inline void AFXAPI DestructElements(TYPE* pElements, int nCount)
  29. {
  30. // call the destructor(s)
  31. for (; nCount--; pElements++)
  32. pElements->~TYPE();
  33. }
  34. template<class TYPE>
  35. inline void AFXAPI CopyElements(TYPE* pDest, const TYPE* pSrc, int nCount)
  36. {
  37. // default is element-copy using assignment
  38. while (nCount--)
  39. *pDest++ = *pSrc++;
  40. }
  41. template<class TYPE, class ARG_TYPE>
  42. BOOL AFXAPI CompareElements(const TYPE* pElement1, const ARG_TYPE* pElement2)
  43. {
  44. return *pElement1 == *pElement2;
  45. }
  46. template<class ARG_KEY>
  47. inline UINT AFXAPI HashKey(ARG_KEY key)
  48. {
  49. // default identity hash - works for most primitive values
  50. return (UINT)((UINT_PTR)key) >> 4;
  51. }
  52. ///////////////////////////////////////////////////////////////////////////////
  53. // CString support for template collections
  54. #if _MSC_VER >= 1100
  55. template<> void AFXAPI ConstructElements<CString> (CString* pElements, int nCount);
  56. #else
  57. void AFXAPI ConstructElements(CString* pElements, int nCount);
  58. #endif
  59. #if _MSC_VER >= 1100
  60. template<> void AFXAPI DestructElements<CString> (CString* pElements, int nCount);
  61. #else
  62. void AFXAPI DestructElements(CString* pElements, int nCount);
  63. #endif
  64. #if _MSC_VER >= 1100
  65. template<> void AFXAPI CopyElements<CString> (CString* pDest, const CString* pSrc, int nCount);
  66. #else
  67. void AFXAPI CopyElements(CString* pDest, const CString* pSrc, int nCount);
  68. #endif
  69. #if _MSC_VER >= 1100
  70. template<> void AFXAPI ConstructElements<CStringA> (CStringA* pElements, int nCount);
  71. #else
  72. void AFXAPI ConstructElements(CStringA* pElements, int nCount);
  73. #endif
  74. #if _MSC_VER >= 1100
  75. template<> void AFXAPI DestructElements<CStringA> (CStringA* pElements, int nCount);
  76. #else
  77. void AFXAPI DestructElements(CStringA* pElements, int nCount);
  78. #endif
  79. #if _MSC_VER >= 1100
  80. template<> void AFXAPI CopyElements<CStringA> (CStringA* pDest, const CStringA* pSrc, int nCount);
  81. #else
  82. void AFXAPI CopyElements(CStringA* pDest, const CStringA* pSrc, int nCount);
  83. #endif
  84. #if _MSC_VER >= 1100
  85. template<> void AFXAPI ConstructElements<CStringW> (CStringW* pElements, int nCount);
  86. #else
  87. void AFXAPI ConstructElements(CStringW* pElements, int nCount);
  88. #endif
  89. #if _MSC_VER >= 1100
  90. template<> void AFXAPI DestructElements<CStringW> (CStringW* pElements, int nCount);
  91. #else
  92. void AFXAPI DestructElements(CStringW* pElements, int nCount);
  93. #endif
  94. #if _MSC_VER >= 1100
  95. template<> void AFXAPI CopyElements<CStringW> (CStringW* pDest, const CStringW* pSrc, int nCount);
  96. #else
  97. void AFXAPI CopyElements(CStringW* pDest, const CStringW* pSrc, int nCount);
  98. #endif
  99. /*
  100. #ifndef OLE2ANSI
  101. #if _MSC_VER >= 1100
  102. template<> UINT AFXAPI HashKey<LPCWSTR> (LPCWSTR key);
  103. #else
  104. UINT AFXAPI HashKey(LPCWSTR key);
  105. #endif
  106. #endif
  107. #if _MSC_VER >= 1100
  108. template<> UINT AFXAPI HashKey<LPCSTR> (LPCSTR key);
  109. #else
  110. UINT AFXAPI HashKey(LPCSTR key);
  111. #endif
  112. */
  113. UINT AFXAPI HashKeyLPCWSTR(LPCWSTR key);
  114. UINT AFXAPI HashKeyLPCSTR(LPCSTR key);
  115. /////////////////////////////////////////////////////////////////////////////
  116. // CArray<TYPE, ARG_TYPE>
  117. template<class TYPE, class ARG_TYPE>
  118. class CArray
  119. {
  120. public:
  121. // Construction
  122. CArray();
  123. // Attributes
  124. int GetSize() const;
  125. int GetUpperBound() const;
  126. void SetSize(int nNewSize, int nGrowBy = -1);
  127. // Operations
  128. // Clean up
  129. void FreeExtra();
  130. void RemoveAll();
  131. // Accessing elements
  132. TYPE GetAt(int nIndex) const;
  133. void SetAt(int nIndex, ARG_TYPE newElement);
  134. TYPE& ElementAt(int nIndex);
  135. // Direct Access to the element data (may return NULL)
  136. const TYPE* GetData() const;
  137. TYPE* GetData();
  138. // Potentially growing the array
  139. void SetAtGrow(int nIndex, ARG_TYPE newElement);
  140. int Add(ARG_TYPE newElement);
  141. int Append(const CArray& src);
  142. void Copy(const CArray& src);
  143. // overloaded operator helpers
  144. TYPE operator[](int nIndex) const;
  145. TYPE& operator[](int nIndex);
  146. // Operations that move elements around
  147. void InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
  148. void RemoveAt(int nIndex, int nCount = 1);
  149. void InsertAt(int nStartIndex, CArray* pNewArray);
  150. // Implementation
  151. protected:
  152. TYPE* m_pData; // the actual array of data
  153. int m_nSize; // # of elements (upperBound - 1)
  154. int m_nMaxSize; // max allocated
  155. int m_nGrowBy; // grow amount
  156. public:
  157. ~CArray();
  158. };
  159. /////////////////////////////////////////////////////////////////////////////
  160. // CArray<TYPE, ARG_TYPE> inline functions
  161. template<class TYPE, class ARG_TYPE>
  162. inline int CArray<TYPE, ARG_TYPE>::GetSize() const
  163. { return m_nSize; }
  164. template<class TYPE, class ARG_TYPE>
  165. inline int CArray<TYPE, ARG_TYPE>::GetUpperBound() const
  166. { return m_nSize-1; }
  167. template<class TYPE, class ARG_TYPE>
  168. inline void CArray<TYPE, ARG_TYPE>::RemoveAll()
  169. { SetSize(0, -1); }
  170. template<class TYPE, class ARG_TYPE>
  171. inline TYPE CArray<TYPE, ARG_TYPE>::GetAt(int nIndex) const
  172. { return m_pData[nIndex]; }
  173. template<class TYPE, class ARG_TYPE>
  174. inline void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, ARG_TYPE newElement)
  175. { m_pData[nIndex] = newElement; }
  176. template<class TYPE, class ARG_TYPE>
  177. inline TYPE& CArray<TYPE, ARG_TYPE>::ElementAt(int nIndex)
  178. { return m_pData[nIndex]; }
  179. template<class TYPE, class ARG_TYPE>
  180. inline const TYPE* CArray<TYPE, ARG_TYPE>::GetData() const
  181. { return (const TYPE*)m_pData; }
  182. template<class TYPE, class ARG_TYPE>
  183. inline TYPE* CArray<TYPE, ARG_TYPE>::GetData()
  184. { return (TYPE*)m_pData; }
  185. template<class TYPE, class ARG_TYPE>
  186. inline int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
  187. { int nIndex = m_nSize;
  188. SetAtGrow(nIndex, newElement);
  189. return nIndex; }
  190. template<class TYPE, class ARG_TYPE>
  191. inline TYPE CArray<TYPE, ARG_TYPE>::operator[](int nIndex) const
  192. { return GetAt(nIndex); }
  193. template<class TYPE, class ARG_TYPE>
  194. inline TYPE& CArray<TYPE, ARG_TYPE>::operator[](int nIndex)
  195. { return ElementAt(nIndex); }
  196. /////////////////////////////////////////////////////////////////////////////
  197. // CArray<TYPE, ARG_TYPE> out-of-line functions
  198. template<class TYPE, class ARG_TYPE>
  199. CArray<TYPE, ARG_TYPE>::CArray()
  200. {
  201. m_pData = NULL;
  202. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  203. }
  204. template<class TYPE, class ARG_TYPE>
  205. CArray<TYPE, ARG_TYPE>::~CArray()
  206. {
  207. if (m_pData != NULL)
  208. {
  209. DestructElements<TYPE>(m_pData, m_nSize);
  210. delete[] (BYTE*)m_pData;
  211. }
  212. }
  213. template<class TYPE, class ARG_TYPE>
  214. void CArray<TYPE, ARG_TYPE>::SetSize(int nNewSize, int nGrowBy)
  215. {
  216. if (nGrowBy != -1)
  217. m_nGrowBy = nGrowBy; // set new size
  218. if (nNewSize == 0)
  219. {
  220. // shrink to nothing
  221. if (m_pData != NULL)
  222. {
  223. DestructElements<TYPE>(m_pData, m_nSize);
  224. delete[] (BYTE*)m_pData;
  225. m_pData = NULL;
  226. }
  227. m_nSize = m_nMaxSize = 0;
  228. }
  229. else if (m_pData == NULL)
  230. {
  231. // create one with exact size
  232. m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)];
  233. ConstructElements<TYPE>(m_pData, nNewSize);
  234. m_nSize = m_nMaxSize = nNewSize;
  235. }
  236. else if (nNewSize <= m_nMaxSize)
  237. {
  238. // it fits
  239. if (nNewSize > m_nSize)
  240. {
  241. // initialize the new elements
  242. ConstructElements<TYPE>(&m_pData[m_nSize], nNewSize-m_nSize);
  243. }
  244. else if (m_nSize > nNewSize)
  245. {
  246. // destroy the old elements
  247. DestructElements<TYPE>(&m_pData[nNewSize], m_nSize-nNewSize);
  248. }
  249. m_nSize = nNewSize;
  250. }
  251. else
  252. {
  253. // otherwise, grow array
  254. int nGrowBy = m_nGrowBy;
  255. if (nGrowBy == 0)
  256. {
  257. // heuristically determine growth when nGrowBy == 0
  258. // (this avoids heap fragmentation in many situations)
  259. nGrowBy = m_nSize / 8;
  260. nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy);
  261. }
  262. int nNewMax;
  263. if (nNewSize < m_nMaxSize + nGrowBy)
  264. nNewMax = m_nMaxSize + nGrowBy; // granularity
  265. else
  266. nNewMax = nNewSize; // no slush
  267. TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];
  268. // copy new data from old
  269. memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
  270. // construct remaining elements
  271. ConstructElements<TYPE>(&pNewData[m_nSize], nNewSize-m_nSize);
  272. // get rid of old stuff (note: no destructors called)
  273. delete[] (BYTE*)m_pData;
  274. m_pData = pNewData;
  275. m_nSize = nNewSize;
  276. m_nMaxSize = nNewMax;
  277. }
  278. }
  279. template<class TYPE, class ARG_TYPE>
  280. int CArray<TYPE, ARG_TYPE>::Append(const CArray& src)
  281. {
  282. int nOldSize = m_nSize;
  283. SetSize(m_nSize + src.m_nSize);
  284. CopyElements<TYPE>(m_pData + nOldSize, src.m_pData, src.m_nSize);
  285. return nOldSize;
  286. }
  287. template<class TYPE, class ARG_TYPE>
  288. void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src)
  289. {
  290. SetSize(src.m_nSize);
  291. CopyElements<TYPE>(m_pData, src.m_pData, src.m_nSize);
  292. }
  293. template<class TYPE, class ARG_TYPE>
  294. void CArray<TYPE, ARG_TYPE>::FreeExtra()
  295. {
  296. if (m_nSize != m_nMaxSize)
  297. {
  298. // shrink to desired size
  299. TYPE* pNewData = NULL;
  300. if (m_nSize != 0)
  301. {
  302. pNewData = (TYPE*) new BYTE[m_nSize * sizeof(TYPE)];
  303. // copy new data from old
  304. memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
  305. }
  306. // get rid of old stuff (note: no destructors called)
  307. delete[] (BYTE*)m_pData;
  308. m_pData = pNewData;
  309. m_nMaxSize = m_nSize;
  310. }
  311. }
  312. template<class TYPE, class ARG_TYPE>
  313. void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
  314. {
  315. if (nIndex >= m_nSize)
  316. SetSize(nIndex+1, -1);
  317. m_pData[nIndex] = newElement;
  318. }
  319. template<class TYPE, class ARG_TYPE>
  320. void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, ARG_TYPE newElement, int nCount /*=1*/)
  321. {
  322. if (nIndex >= m_nSize)
  323. {
  324. // adding after the end of the array
  325. SetSize(nIndex + nCount, -1); // grow so nIndex is valid
  326. }
  327. else
  328. {
  329. // inserting in the middle of the array
  330. int nOldSize = m_nSize;
  331. SetSize(m_nSize + nCount, -1); // grow it to new size
  332. // destroy intial data before copying over it
  333. DestructElements<TYPE>(&m_pData[nOldSize], nCount);
  334. // shift old data up to fill gap
  335. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  336. (nOldSize-nIndex) * sizeof(TYPE));
  337. // re-init slots we copied from
  338. ConstructElements<TYPE>(&m_pData[nIndex], nCount);
  339. }
  340. // insert new value in the gap
  341. while (nCount--)
  342. m_pData[nIndex++] = newElement;
  343. }
  344. template<class TYPE, class ARG_TYPE>
  345. void CArray<TYPE, ARG_TYPE>::RemoveAt(int nIndex, int nCount)
  346. {
  347. // just remove a range
  348. int nMoveCount = m_nSize - (nIndex + nCount);
  349. DestructElements<TYPE>(&m_pData[nIndex], nCount);
  350. if (nMoveCount)
  351. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  352. nMoveCount * sizeof(TYPE));
  353. m_nSize -= nCount;
  354. }
  355. template<class TYPE, class ARG_TYPE>
  356. void CArray<TYPE, ARG_TYPE>::InsertAt(int nStartIndex, CArray* pNewArray)
  357. {
  358. if (pNewArray->GetSize() > 0)
  359. {
  360. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  361. for (int i = 0; i < pNewArray->GetSize(); i++)
  362. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  363. }
  364. }
  365. /////////////////////////////////////////////////////////////////////////////
  366. // CList<TYPE, ARG_TYPE>
  367. template<class TYPE, class ARG_TYPE>
  368. class CList
  369. {
  370. protected:
  371. struct CNode
  372. {
  373. CNode* pNext;
  374. CNode* pPrev;
  375. TYPE data;
  376. };
  377. public:
  378. // Construction
  379. CList(int nBlockSize = 10);
  380. // Attributes (head and tail)
  381. // count of elements
  382. int GetCount() const;
  383. BOOL IsEmpty() const;
  384. // peek at head or tail
  385. TYPE& GetHead();
  386. TYPE GetHead() const;
  387. TYPE& GetTail();
  388. TYPE GetTail() const;
  389. // Operations
  390. // get head or tail (and remove it) - don't call on empty list !
  391. TYPE RemoveHead();
  392. TYPE RemoveTail();
  393. // add before head or after tail
  394. POSITION AddHead(ARG_TYPE newElement);
  395. POSITION AddTail(ARG_TYPE newElement);
  396. // add another list of elements before head or after tail
  397. void AddHead(CList* pNewList);
  398. void AddTail(CList* pNewList);
  399. // remove all elements
  400. void RemoveAll();
  401. // iteration
  402. POSITION GetHeadPosition() const;
  403. POSITION GetTailPosition() const;
  404. TYPE& GetNext(POSITION& rPosition); // return *Position++
  405. TYPE GetNext(POSITION& rPosition) const; // return *Position++
  406. TYPE& GetPrev(POSITION& rPosition); // return *Position--
  407. TYPE GetPrev(POSITION& rPosition) const; // return *Position--
  408. // getting/modifying an element at a given position
  409. TYPE& GetAt(POSITION position);
  410. TYPE GetAt(POSITION position) const;
  411. void SetAt(POSITION pos, ARG_TYPE newElement);
  412. void RemoveAt(POSITION position);
  413. // inserting before or after a given position
  414. POSITION InsertBefore(POSITION position, ARG_TYPE newElement);
  415. POSITION InsertAfter(POSITION position, ARG_TYPE newElement);
  416. // helper functions (note: O(n) speed)
  417. POSITION Find(ARG_TYPE searchValue, POSITION startAfter = NULL) const;
  418. // defaults to starting at the HEAD, return NULL if not found
  419. POSITION FindIndex(int nIndex) const;
  420. // get the 'nIndex'th element (may return NULL)
  421. // Implementation
  422. protected:
  423. CNode* m_pNodeHead;
  424. CNode* m_pNodeTail;
  425. int m_nCount;
  426. CNode* m_pNodeFree;
  427. struct CPlex* m_pBlocks;
  428. int m_nBlockSize;
  429. CNode* NewNode(CNode*, CNode*);
  430. void FreeNode(CNode*);
  431. public:
  432. ~CList();
  433. };
  434. /////////////////////////////////////////////////////////////////////////////
  435. // CList<TYPE, ARG_TYPE> inline functions
  436. template<class TYPE, class ARG_TYPE>
  437. inline int CList<TYPE, ARG_TYPE>::GetCount() const
  438. { return m_nCount; }
  439. template<class TYPE, class ARG_TYPE>
  440. inline BOOL CList<TYPE, ARG_TYPE>::IsEmpty() const
  441. { return m_nCount == 0; }
  442. template<class TYPE, class ARG_TYPE>
  443. inline TYPE& CList<TYPE, ARG_TYPE>::GetHead()
  444. { return m_pNodeHead->data; }
  445. template<class TYPE, class ARG_TYPE>
  446. inline TYPE CList<TYPE, ARG_TYPE>::GetHead() const
  447. { return m_pNodeHead->data; }
  448. template<class TYPE, class ARG_TYPE>
  449. inline TYPE& CList<TYPE, ARG_TYPE>::GetTail()
  450. { return m_pNodeTail->data; }
  451. template<class TYPE, class ARG_TYPE>
  452. inline TYPE CList<TYPE, ARG_TYPE>::GetTail() const
  453. { return m_pNodeTail->data; }
  454. template<class TYPE, class ARG_TYPE>
  455. inline POSITION CList<TYPE, ARG_TYPE>::GetHeadPosition() const
  456. { return (POSITION) m_pNodeHead; }
  457. template<class TYPE, class ARG_TYPE>
  458. inline POSITION CList<TYPE, ARG_TYPE>::GetTailPosition() const
  459. { return (POSITION) m_pNodeTail; }
  460. template<class TYPE, class ARG_TYPE>
  461. inline TYPE& CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) // return *Position++
  462. { CNode* pNode = (CNode*) rPosition;
  463. rPosition = (POSITION) pNode->pNext;
  464. return pNode->data; }
  465. template<class TYPE, class ARG_TYPE>
  466. inline TYPE CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) const // return *Position++
  467. { CNode* pNode = (CNode*) rPosition;
  468. rPosition = (POSITION) pNode->pNext;
  469. return pNode->data; }
  470. template<class TYPE, class ARG_TYPE>
  471. inline TYPE& CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) // return *Position--
  472. { CNode* pNode = (CNode*) rPosition;
  473. rPosition = (POSITION) pNode->pPrev;
  474. return pNode->data; }
  475. template<class TYPE, class ARG_TYPE>
  476. inline TYPE CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) const // return *Position--
  477. { CNode* pNode = (CNode*) rPosition;
  478. rPosition = (POSITION) pNode->pPrev;
  479. return pNode->data; }
  480. template<class TYPE, class ARG_TYPE>
  481. inline TYPE& CList<TYPE, ARG_TYPE>::GetAt(POSITION position)
  482. { CNode* pNode = (CNode*) position;
  483. return pNode->data; }
  484. template<class TYPE, class ARG_TYPE>
  485. inline TYPE CList<TYPE, ARG_TYPE>::GetAt(POSITION position) const
  486. { CNode* pNode = (CNode*) position;
  487. return pNode->data; }
  488. template<class TYPE, class ARG_TYPE>
  489. inline void CList<TYPE, ARG_TYPE>::SetAt(POSITION pos, ARG_TYPE newElement)
  490. { CNode* pNode = (CNode*) pos;
  491. pNode->data = newElement; }
  492. template<class TYPE, class ARG_TYPE>
  493. CList<TYPE, ARG_TYPE>::CList(int nBlockSize)
  494. {
  495. m_nCount = 0;
  496. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  497. m_pBlocks = NULL;
  498. m_nBlockSize = nBlockSize;
  499. }
  500. template<class TYPE, class ARG_TYPE>
  501. void CList<TYPE, ARG_TYPE>::RemoveAll()
  502. {
  503. // destroy elements
  504. CNode* pNode;
  505. for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)
  506. DestructElements<TYPE>(&pNode->data, 1);
  507. m_nCount = 0;
  508. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  509. m_pBlocks->FreeDataChain();
  510. m_pBlocks = NULL;
  511. }
  512. template<class TYPE, class ARG_TYPE>
  513. CList<TYPE, ARG_TYPE>::~CList()
  514. {
  515. RemoveAll();
  516. }
  517. /////////////////////////////////////////////////////////////////////////////
  518. // Node helpers
  519. //
  520. // Implementation note: CNode's are stored in CPlex blocks and
  521. // chained together. Free blocks are maintained in a singly linked list
  522. // using the 'pNext' member of CNode with 'm_pNodeFree' as the head.
  523. // Used blocks are maintained in a doubly linked list using both 'pNext'
  524. // and 'pPrev' as links and 'm_pNodeHead' and 'm_pNodeTail'
  525. // as the head/tail.
  526. //
  527. // We never free a CPlex block unless the List is destroyed or RemoveAll()
  528. // is used - so the total number of CPlex blocks may grow large depending
  529. // on the maximum past size of the list.
  530. //
  531. template<class TYPE, class ARG_TYPE>
  532. typename CList<TYPE, ARG_TYPE>::CNode*
  533. CList<TYPE, ARG_TYPE>::NewNode(CNode* pPrev, CNode* pNext)
  534. {
  535. if (m_pNodeFree == NULL)
  536. {
  537. // add another block
  538. CPlex* pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize,
  539. sizeof(CNode));
  540. // chain them into free list
  541. CNode* pNode = (CNode*) pNewBlock->data();
  542. // free in reverse order to make it easier to debug
  543. pNode += m_nBlockSize - 1;
  544. for (int i = m_nBlockSize-1; i >= 0; i--, pNode--)
  545. {
  546. pNode->pNext = m_pNodeFree;
  547. m_pNodeFree = pNode;
  548. }
  549. }
  550. CList::CNode* pNode = m_pNodeFree;
  551. m_pNodeFree = m_pNodeFree->pNext;
  552. pNode->pPrev = pPrev;
  553. pNode->pNext = pNext;
  554. m_nCount++;
  555. ConstructElements<TYPE>(&pNode->data, 1);
  556. return pNode;
  557. }
  558. template<class TYPE, class ARG_TYPE>
  559. void CList<TYPE, ARG_TYPE>::FreeNode(CNode* pNode)
  560. {
  561. DestructElements<TYPE>(&pNode->data, 1);
  562. pNode->pNext = m_pNodeFree;
  563. m_pNodeFree = pNode;
  564. m_nCount--;
  565. // if no more elements, cleanup completely
  566. if (m_nCount == 0)
  567. RemoveAll();
  568. }
  569. template<class TYPE, class ARG_TYPE>
  570. POSITION CList<TYPE, ARG_TYPE>::AddHead(ARG_TYPE newElement)
  571. {
  572. CNode* pNewNode = NewNode(NULL, m_pNodeHead);
  573. pNewNode->data = newElement;
  574. if (m_pNodeHead != NULL)
  575. m_pNodeHead->pPrev = pNewNode;
  576. else
  577. m_pNodeTail = pNewNode;
  578. m_pNodeHead = pNewNode;
  579. return (POSITION) pNewNode;
  580. }
  581. template<class TYPE, class ARG_TYPE>
  582. POSITION CList<TYPE, ARG_TYPE>::AddTail(ARG_TYPE newElement)
  583. {
  584. CNode* pNewNode = NewNode(m_pNodeTail, NULL);
  585. pNewNode->data = newElement;
  586. if (m_pNodeTail != NULL)
  587. m_pNodeTail->pNext = pNewNode;
  588. else
  589. m_pNodeHead = pNewNode;
  590. m_pNodeTail = pNewNode;
  591. return (POSITION) pNewNode;
  592. }
  593. template<class TYPE, class ARG_TYPE>
  594. void CList<TYPE, ARG_TYPE>::AddHead(CList* pNewList)
  595. {
  596. // add a list of same elements to head (maintain order)
  597. POSITION pos = pNewList->GetTailPosition();
  598. while (pos != NULL)
  599. AddHead(pNewList->GetPrev(pos));
  600. }
  601. template<class TYPE, class ARG_TYPE>
  602. void CList<TYPE, ARG_TYPE>::AddTail(CList* pNewList)
  603. {
  604. // add a list of same elements
  605. POSITION pos = pNewList->GetHeadPosition();
  606. while (pos != NULL)
  607. AddTail(pNewList->GetNext(pos));
  608. }
  609. template<class TYPE, class ARG_TYPE>
  610. TYPE CList<TYPE, ARG_TYPE>::RemoveHead()
  611. {
  612. CNode* pOldNode = m_pNodeHead;
  613. TYPE returnValue = pOldNode->data;
  614. m_pNodeHead = pOldNode->pNext;
  615. if (m_pNodeHead != NULL)
  616. m_pNodeHead->pPrev = NULL;
  617. else
  618. m_pNodeTail = NULL;
  619. FreeNode(pOldNode);
  620. return returnValue;
  621. }
  622. template<class TYPE, class ARG_TYPE>
  623. TYPE CList<TYPE, ARG_TYPE>::RemoveTail()
  624. {
  625. CNode* pOldNode = m_pNodeTail;
  626. TYPE returnValue = pOldNode->data;
  627. m_pNodeTail = pOldNode->pPrev;
  628. if (m_pNodeTail != NULL)
  629. m_pNodeTail->pNext = NULL;
  630. else
  631. m_pNodeHead = NULL;
  632. FreeNode(pOldNode);
  633. return returnValue;
  634. }
  635. template<class TYPE, class ARG_TYPE>
  636. POSITION CList<TYPE, ARG_TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement)
  637. {
  638. if (position == NULL)
  639. return AddHead(newElement); // insert before nothing -> head of the list
  640. // Insert it before position
  641. CNode* pOldNode = (CNode*) position;
  642. CNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode);
  643. pNewNode->data = newElement;
  644. if (pOldNode->pPrev != NULL)
  645. {
  646. pOldNode->pPrev->pNext = pNewNode;
  647. }
  648. else
  649. {
  650. m_pNodeHead = pNewNode;
  651. }
  652. pOldNode->pPrev = pNewNode;
  653. return (POSITION) pNewNode;
  654. }
  655. template<class TYPE, class ARG_TYPE>
  656. POSITION CList<TYPE, ARG_TYPE>::InsertAfter(POSITION position, ARG_TYPE newElement)
  657. {
  658. if (position == NULL)
  659. return AddTail(newElement); // insert after nothing -> tail of the list
  660. // Insert it before position
  661. CNode* pOldNode = (CNode*) position;
  662. CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
  663. pNewNode->data = newElement;
  664. if (pOldNode->pNext != NULL)
  665. {
  666. pOldNode->pNext->pPrev = pNewNode;
  667. }
  668. else
  669. {
  670. m_pNodeTail = pNewNode;
  671. }
  672. pOldNode->pNext = pNewNode;
  673. return (POSITION) pNewNode;
  674. }
  675. template<class TYPE, class ARG_TYPE>
  676. void CList<TYPE, ARG_TYPE>::RemoveAt(POSITION position)
  677. {
  678. CNode* pOldNode = (CNode*) position;
  679. // remove pOldNode from list
  680. if (pOldNode == m_pNodeHead)
  681. {
  682. m_pNodeHead = pOldNode->pNext;
  683. }
  684. else
  685. {
  686. pOldNode->pPrev->pNext = pOldNode->pNext;
  687. }
  688. if (pOldNode == m_pNodeTail)
  689. {
  690. m_pNodeTail = pOldNode->pPrev;
  691. }
  692. else
  693. {
  694. pOldNode->pNext->pPrev = pOldNode->pPrev;
  695. }
  696. FreeNode(pOldNode);
  697. }
  698. template<class TYPE, class ARG_TYPE>
  699. POSITION CList<TYPE, ARG_TYPE>::FindIndex(int nIndex) const
  700. {
  701. if (nIndex >= m_nCount)
  702. return NULL; // went too far
  703. CNode* pNode = m_pNodeHead;
  704. while (nIndex--)
  705. {
  706. pNode = pNode->pNext;
  707. }
  708. return (POSITION) pNode;
  709. }
  710. template<class TYPE, class ARG_TYPE>
  711. POSITION CList<TYPE, ARG_TYPE>::Find(ARG_TYPE searchValue, POSITION startAfter) const
  712. {
  713. CNode* pNode = (CNode*) startAfter;
  714. if (pNode == NULL)
  715. {
  716. pNode = m_pNodeHead; // start at head
  717. }
  718. else
  719. {
  720. pNode = pNode->pNext; // start after the one specified
  721. }
  722. for (; pNode != NULL; pNode = pNode->pNext)
  723. if (CompareElements<TYPE>(&pNode->data, &searchValue))
  724. return (POSITION)pNode;
  725. return NULL;
  726. }
  727. /////////////////////////////////////////////////////////////////////////////
  728. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>
  729. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  730. class CMap
  731. {
  732. protected:
  733. // Association
  734. struct CAssoc
  735. {
  736. CAssoc* pNext;
  737. UINT nHashValue; // needed for efficient iteration
  738. KEY key;
  739. VALUE value;
  740. };
  741. public:
  742. // Construction
  743. CMap(int nBlockSize = 10);
  744. // Attributes
  745. // number of elements
  746. int GetCount() const;
  747. BOOL IsEmpty() const;
  748. // Lookup
  749. BOOL Lookup(ARG_KEY key, VALUE& rValue) const;
  750. // Operations
  751. // Lookup and add if not there
  752. VALUE& operator[](ARG_KEY key);
  753. // add a new (key, value) pair
  754. void SetAt(ARG_KEY key, ARG_VALUE newValue);
  755. // removing existing (key, ?) pair
  756. BOOL RemoveKey(ARG_KEY key);
  757. void RemoveAll();
  758. // iterating all (key, value) pairs
  759. POSITION GetStartPosition() const;
  760. void GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue) const;
  761. // advanced features for derived classes
  762. UINT GetHashTableSize() const;
  763. void InitHashTable(UINT hashSize, BOOL bAllocNow = TRUE);
  764. // Implementation
  765. protected:
  766. CAssoc** m_pHashTable;
  767. UINT m_nHashTableSize;
  768. int m_nCount;
  769. CAssoc* m_pFreeList;
  770. struct CPlex* m_pBlocks;
  771. int m_nBlockSize;
  772. CAssoc* NewAssoc();
  773. void FreeAssoc(CAssoc*);
  774. CAssoc* GetAssocAt(ARG_KEY, UINT&) const;
  775. public:
  776. ~CMap();
  777. };
  778. /////////////////////////////////////////////////////////////////////////////
  779. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> inline functions
  780. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  781. inline int CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetCount() const
  782. { return m_nCount; }
  783. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  784. inline BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::IsEmpty() const
  785. { return m_nCount == 0; }
  786. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  787. inline void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::SetAt(ARG_KEY key, ARG_VALUE newValue)
  788. { (*this)[key] = newValue; }
  789. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  790. inline POSITION CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetStartPosition() const
  791. { return (m_nCount == 0) ? NULL : BEFORE_START_POSITION; }
  792. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  793. inline UINT CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetHashTableSize() const
  794. { return m_nHashTableSize; }
  795. /////////////////////////////////////////////////////////////////////////////
  796. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> out-of-line functions
  797. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  798. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMap(int nBlockSize)
  799. {
  800. m_pHashTable = NULL;
  801. m_nHashTableSize = 17; // default size
  802. m_nCount = 0;
  803. m_pFreeList = NULL;
  804. m_pBlocks = NULL;
  805. m_nBlockSize = nBlockSize;
  806. }
  807. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  808. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::InitHashTable(
  809. UINT nHashSize, BOOL bAllocNow)
  810. //
  811. // Used to force allocation of a hash table or to override the default
  812. // hash table size of (which is fairly small)
  813. {
  814. if (m_pHashTable != NULL)
  815. {
  816. // free hash table
  817. delete[] m_pHashTable;
  818. m_pHashTable = NULL;
  819. }
  820. if (bAllocNow)
  821. {
  822. m_pHashTable = new CAssoc* [nHashSize];
  823. memset(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
  824. }
  825. m_nHashTableSize = nHashSize;
  826. }
  827. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  828. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAll()
  829. {
  830. if (m_pHashTable != NULL)
  831. {
  832. // destroy elements (values and keys)
  833. for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
  834. {
  835. CAssoc* pAssoc;
  836. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
  837. pAssoc = pAssoc->pNext)
  838. {
  839. DestructElements<VALUE>(&pAssoc->value, 1);
  840. DestructElements<KEY>(&pAssoc->key, 1);
  841. }
  842. }
  843. }
  844. // free hash table
  845. delete[] m_pHashTable;
  846. m_pHashTable = NULL;
  847. m_nCount = 0;
  848. m_pFreeList = NULL;
  849. m_pBlocks->FreeDataChain();
  850. m_pBlocks = NULL;
  851. }
  852. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  853. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::~CMap()
  854. {
  855. RemoveAll();
  856. }
  857. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  858. typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
  859. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::NewAssoc()
  860. {
  861. if (m_pFreeList == NULL)
  862. {
  863. // add another block
  864. CPlex* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CMap::CAssoc));
  865. // chain them into free list
  866. CMap::CAssoc* pAssoc = (CMap::CAssoc*) newBlock->data();
  867. // free in reverse order to make it easier to debug
  868. pAssoc += m_nBlockSize - 1;
  869. for (int i = m_nBlockSize-1; i >= 0; i--, pAssoc--)
  870. {
  871. pAssoc->pNext = m_pFreeList;
  872. m_pFreeList = pAssoc;
  873. }
  874. }
  875. CMap::CAssoc* pAssoc = m_pFreeList;
  876. m_pFreeList = m_pFreeList->pNext;
  877. m_nCount++;
  878. ConstructElements<KEY>(&pAssoc->key, 1);
  879. ConstructElements<VALUE>(&pAssoc->value, 1); // special construct values
  880. return pAssoc;
  881. }
  882. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  883. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::FreeAssoc(CAssoc* pAssoc)
  884. {
  885. DestructElements<VALUE>(&pAssoc->value, 1);
  886. DestructElements<KEY>(&pAssoc->key, 1);
  887. pAssoc->pNext = m_pFreeList;
  888. m_pFreeList = pAssoc;
  889. m_nCount--;
  890. // if no more elements, cleanup completely
  891. if (m_nCount == 0)
  892. RemoveAll();
  893. }
  894. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  895. typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
  896. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAssocAt(ARG_KEY key, UINT& nHash) const
  897. // find association (or return NULL)
  898. {
  899. nHash = HashKey<ARG_KEY>(key) % m_nHashTableSize;
  900. if (m_pHashTable == NULL)
  901. return NULL;
  902. // see if it exists
  903. CAssoc* pAssoc;
  904. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
  905. {
  906. if (CompareElements(&pAssoc->key, &key))
  907. return pAssoc;
  908. }
  909. return NULL;
  910. }
  911. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  912. BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(ARG_KEY key, VALUE& rValue) const
  913. {
  914. UINT nHash;
  915. CAssoc* pAssoc = GetAssocAt(key, nHash);
  916. if (pAssoc == NULL)
  917. return FALSE; // not in map
  918. rValue = pAssoc->value;
  919. return TRUE;
  920. }
  921. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  922. VALUE& CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator[](ARG_KEY key)
  923. {
  924. UINT nHash;
  925. CAssoc* pAssoc;
  926. if ((pAssoc = GetAssocAt(key, nHash)) == NULL)
  927. {
  928. if (m_pHashTable == NULL)
  929. InitHashTable(m_nHashTableSize);
  930. // it doesn't exist, add a new Association
  931. pAssoc = NewAssoc();
  932. pAssoc->nHashValue = nHash;
  933. pAssoc->key = key;
  934. // 'pAssoc->value' is a constructed object, nothing more
  935. // put into hash table
  936. pAssoc->pNext = m_pHashTable[nHash];
  937. m_pHashTable[nHash] = pAssoc;
  938. }
  939. return pAssoc->value; // return new reference
  940. }
  941. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  942. BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveKey(ARG_KEY key)
  943. // remove key - return TRUE if removed
  944. {
  945. if (m_pHashTable == NULL)
  946. return FALSE; // nothing in the table
  947. CAssoc** ppAssocPrev;
  948. ppAssocPrev = &m_pHashTable[HashKey<ARG_KEY>(key) % m_nHashTableSize];
  949. CAssoc* pAssoc;
  950. for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
  951. {
  952. if (CompareElements(&pAssoc->key, &key))
  953. {
  954. // remove it
  955. *ppAssocPrev = pAssoc->pNext; // remove from list
  956. FreeAssoc(pAssoc);
  957. return TRUE;
  958. }
  959. ppAssocPrev = &pAssoc->pNext;
  960. }
  961. return FALSE; // not found
  962. }
  963. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  964. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetNextAssoc(POSITION& rNextPosition,
  965. KEY& rKey, VALUE& rValue) const
  966. {
  967. CAssoc* pAssocRet = (CAssoc*)rNextPosition;
  968. if (pAssocRet == (CAssoc*) BEFORE_START_POSITION)
  969. {
  970. // find the first association
  971. for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
  972. if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
  973. break;
  974. }
  975. // find next association
  976. CAssoc* pAssocNext;
  977. if ((pAssocNext = pAssocRet->pNext) == NULL)
  978. {
  979. // go to next bucket
  980. for (UINT nBucket = pAssocRet->nHashValue + 1;
  981. nBucket < m_nHashTableSize; nBucket++)
  982. if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
  983. break;
  984. }
  985. rNextPosition = (POSITION) pAssocNext;
  986. // fill in return data
  987. rKey = pAssocRet->key;
  988. rValue = pAssocRet->value;
  989. }
  990. /////////////////////////////////////////////////////////////////////////////
  991. // CTypedPtrArray<BASE_CLASS, TYPE>
  992. template<class BASE_CLASS, class TYPE>
  993. class CTypedPtrArray : public BASE_CLASS
  994. {
  995. public:
  996. // Accessing elements
  997. TYPE GetAt(int nIndex) const
  998. { return (TYPE)BASE_CLASS::GetAt(nIndex); }
  999. TYPE& ElementAt(int nIndex)
  1000. { return (TYPE&)BASE_CLASS::ElementAt(nIndex); }
  1001. void SetAt(int nIndex, TYPE ptr)
  1002. { BASE_CLASS::SetAt(nIndex, ptr); }
  1003. // Potentially growing the array
  1004. void SetAtGrow(int nIndex, TYPE newElement)
  1005. { BASE_CLASS::SetAtGrow(nIndex, newElement); }
  1006. int Add(TYPE newElement)
  1007. { return BASE_CLASS::Add(newElement); }
  1008. int Append(const CTypedPtrArray<BASE_CLASS, TYPE>& src)
  1009. { return BASE_CLASS::Append(src); }
  1010. void Copy(const CTypedPtrArray<BASE_CLASS, TYPE>& src)
  1011. { BASE_CLASS::Copy(src); }
  1012. // Operations that move elements around
  1013. void InsertAt(int nIndex, TYPE newElement, int nCount = 1)
  1014. { BASE_CLASS::InsertAt(nIndex, newElement, nCount); }
  1015. void InsertAt(int nStartIndex, CTypedPtrArray<BASE_CLASS, TYPE>* pNewArray)
  1016. { BASE_CLASS::InsertAt(nStartIndex, pNewArray); }
  1017. // overloaded operator helpers
  1018. TYPE operator[](int nIndex) const
  1019. { return (TYPE)BASE_CLASS::operator[](nIndex); }
  1020. TYPE& operator[](int nIndex)
  1021. { return (TYPE&)BASE_CLASS::operator[](nIndex); }
  1022. };
  1023. /////////////////////////////////////////////////////////////////////////////
  1024. // CTypedPtrList<BASE_CLASS, TYPE>
  1025. template<class BASE_CLASS, class TYPE>
  1026. class CTypedPtrList : public BASE_CLASS
  1027. {
  1028. public:
  1029. // Construction
  1030. CTypedPtrList(int nBlockSize = 10)
  1031. : BASE_CLASS(nBlockSize) { }
  1032. // peek at head or tail
  1033. TYPE& GetHead()
  1034. { return (TYPE&)BASE_CLASS::GetHead(); }
  1035. TYPE GetHead() const
  1036. { return (TYPE)BASE_CLASS::GetHead(); }
  1037. TYPE& GetTail()
  1038. { return (TYPE&)BASE_CLASS::GetTail(); }
  1039. TYPE GetTail() const
  1040. { return (TYPE)BASE_CLASS::GetTail(); }
  1041. // get head or tail (and remove it) - don't call on empty list!
  1042. TYPE RemoveHead()
  1043. { return (TYPE)BASE_CLASS::RemoveHead(); }
  1044. TYPE RemoveTail()
  1045. { return (TYPE)BASE_CLASS::RemoveTail(); }
  1046. // add before head or after tail
  1047. POSITION AddHead(TYPE newElement)
  1048. { return BASE_CLASS::AddHead(newElement); }
  1049. POSITION AddTail(TYPE newElement)
  1050. { return BASE_CLASS::AddTail(newElement); }
  1051. // add another list of elements before head or after tail
  1052. void AddHead(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
  1053. { BASE_CLASS::AddHead(pNewList); }
  1054. void AddTail(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
  1055. { BASE_CLASS::AddTail(pNewList); }
  1056. // iteration
  1057. TYPE& GetNext(POSITION& rPosition)
  1058. { return (TYPE&)BASE_CLASS::GetNext(rPosition); }
  1059. TYPE GetNext(POSITION& rPosition) const
  1060. { return (TYPE)BASE_CLASS::GetNext(rPosition); }
  1061. TYPE& GetPrev(POSITION& rPosition)
  1062. { return (TYPE&)BASE_CLASS::GetPrev(rPosition); }
  1063. TYPE GetPrev(POSITION& rPosition) const
  1064. { return (TYPE)BASE_CLASS::GetPrev(rPosition); }
  1065. // getting/modifying an element at a given position
  1066. TYPE& GetAt(POSITION position)
  1067. { return (TYPE&)BASE_CLASS::GetAt(position); }
  1068. TYPE GetAt(POSITION position) const
  1069. { return (TYPE)BASE_CLASS::GetAt(position); }
  1070. void SetAt(POSITION pos, TYPE newElement)
  1071. { BASE_CLASS::SetAt(pos, newElement); }
  1072. };
  1073. /////////////////////////////////////////////////////////////////////////////
  1074. // CTypedPtrMap<BASE_CLASS, KEY, VALUE>
  1075. template<class BASE_CLASS, class KEY, class VALUE>
  1076. class CTypedPtrMap : public BASE_CLASS
  1077. {
  1078. public:
  1079. // Construction
  1080. CTypedPtrMap(int nBlockSize = 10)
  1081. : BASE_CLASS(nBlockSize) { }
  1082. // Lookup
  1083. BOOL Lookup(typename BASE_CLASS::BASE_ARG_KEY key, VALUE& rValue) const
  1084. { return BASE_CLASS::Lookup(key, (BASE_CLASS::BASE_VALUE&)rValue); }
  1085. // Lookup and add if not there
  1086. VALUE& operator[](typename BASE_CLASS::BASE_ARG_KEY key)
  1087. { return (VALUE&)BASE_CLASS::operator[](key); }
  1088. // add a new key (key, value) pair
  1089. void SetAt(KEY key, VALUE newValue)
  1090. { BASE_CLASS::SetAt(key, newValue); }
  1091. // removing existing (key, ?) pair
  1092. BOOL RemoveKey(KEY key)
  1093. { return BASE_CLASS::RemoveKey(key); }
  1094. // iteration
  1095. void GetNextAssoc(POSITION& rPosition, KEY& rKey, VALUE& rValue) const
  1096. { BASE_CLASS::GetNextAssoc(rPosition, (BASE_CLASS::BASE_KEY&)rKey,
  1097. (BASE_CLASS::BASE_VALUE&)rValue); }
  1098. };
  1099. /////////////////////////////////////////////////////////////////////////////
  1100. #endif //__AFXTEMPL_H__
  1101. /////////////////////////////////////////////////////////////////////////////