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.

1750 lines
55 KiB

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1995 Microsoft Corporation
  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 __AFXTEMPL_H__
  11. #define __AFXTEMPL_H__
  12. #ifndef __AFXPLEX_H__
  13. //#include <afxplex_.h>
  14. //#include "..\utils\afxplex_.h"
  15. #endif
  16. #ifdef unix
  17. #include <mainwin.h>
  18. #endif /* unix */
  19. #ifdef _AFX_MINREBUILD
  20. #pragma component(minrebuild, off)
  21. #endif
  22. #ifndef _AFX_FULLTYPEINFO
  23. #pragma component(mintypeinfo, on)
  24. #endif
  25. #ifdef _AFX_PACKING
  26. #pragma pack(push, _AFX_PACKING)
  27. #endif
  28. #ifdef _DEBUG
  29. static char _szAfxTempl[] = "afxtempl.h";
  30. #undef THIS_FILE
  31. #define THIS_FILE _szAfxTempl
  32. #endif
  33. #ifndef ALL_WARNINGS
  34. #pragma warning(disable: 4114)
  35. #endif
  36. /////////////////////////////////////////////////////////////////////////////
  37. // global helpers (can be overridden)
  38. /*
  39. use our new for now
  40. #ifdef new
  41. #undef new
  42. #define _REDEF_NEW
  43. #endif
  44. #ifndef _INC_NEW
  45. #include <new.h>
  46. #endif
  47. */
  48. template<class TYPE>
  49. inline void AFXAPI ConstructElements(TYPE* pElements, int nCount)
  50. {
  51. ASSERT(nCount == 0 ||
  52. AfxIsValidAddress(pElements, nCount * sizeof(TYPE)));
  53. // first do bit-wise zero initialization
  54. memset((void*)pElements, 0, nCount * sizeof(TYPE));
  55. // then call the constructor(s)
  56. for (; nCount--; pElements++)
  57. {
  58. }
  59. }
  60. template<class TYPE>
  61. inline void AFXAPI DestructElements(TYPE* pElements, int nCount)
  62. {
  63. ASSERT(nCount == 0 ||
  64. AfxIsValidAddress(pElements, nCount * sizeof(TYPE)));
  65. // call the destructor(s)
  66. for (; nCount--; pElements++)
  67. pElements->~TYPE();
  68. }
  69. template<class TYPE>
  70. inline void AFXAPI CopyElements(TYPE* pDest, const TYPE* pSrc, int nCount)
  71. {
  72. ASSERT(nCount == 0 ||
  73. AfxIsValidAddress(pDest, nCount * sizeof(TYPE)));
  74. ASSERT(nCount == 0 ||
  75. AfxIsValidAddress(pSrc, nCount * sizeof(TYPE)));
  76. // default is element-copy using assignment
  77. while (nCount--)
  78. *pDest++ = *pSrc;
  79. }
  80. template<class TYPE>
  81. void AFXAPI SerializeElements(CArchive& ar, TYPE* pElements, int nCount)
  82. {
  83. ASSERT(nCount == 0 ||
  84. AfxIsValidAddress(pElements, nCount * sizeof(TYPE)));
  85. // default is bit-wise read/write
  86. if (ar.IsStoring())
  87. ar.Write((void*)pElements, nCount * sizeof(TYPE));
  88. else
  89. ar.Read((void*)pElements, nCount * sizeof(TYPE));
  90. }
  91. #ifdef _DEBUG
  92. #ifndef unix
  93. template<class TYPE>
  94. void AFXAPI DumpElements(CDumpContext& dc, const TYPE* pElements, int nCount)
  95. {
  96. ASSERT(nCount == 0 ||
  97. AfxIsValidAddress(pElements, nCount * sizeof(TYPE)));
  98. &dc; // not used
  99. pElements; // not used
  100. nCount; // not used
  101. // default does nothing
  102. }
  103. #endif /* unix */
  104. #endif
  105. template<class TYPE, class ARG_TYPE>
  106. BOOL AFXAPI CompareElements(const TYPE* pElement1, const ARG_TYPE* pElement2)
  107. {
  108. ASSERT(AfxIsValidAddress(pElement1, sizeof(TYPE)));
  109. ASSERT(AfxIsValidAddress(pElement2, sizeof(ARG_TYPE)));
  110. return *pElement1 == *pElement2;
  111. }
  112. template<class ARG_KEY>
  113. inline UINT AFXAPI HashKey(ARG_KEY key)
  114. {
  115. // default identity hash - works for most primitive values
  116. return PtrToUlong((void*)(DWORD_PTR)key) >> 4;
  117. }
  118. // special versions for CString
  119. template<>
  120. void AFXAPI ConstructElements(CString* pElements, int nCount);
  121. template<>
  122. void AFXAPI DestructElements(CString* pElements, int nCount);
  123. template<>
  124. void AFXAPI CopyElements(CString* pDest, const CString* pSrc, int nCount);
  125. template<>
  126. void AFXAPI SerializeElements(CArchive& ar, CString* pElements, int nCount);
  127. template<>
  128. UINT AFXAPI HashKey(LPCTSTR key);
  129. // forward declarations
  130. class COleVariant;
  131. struct tagVARIANT;
  132. // special versions for COleVariant
  133. /*
  134. void AFXAPI ConstructElements(COleVariant* pElements, int nCount);
  135. void AFXAPI DestructElements(COleVariant* pElements, int nCount);
  136. void AFXAPI CopyElements(COleVariant* pDest, const COleVariant* pSrc, int nCount);
  137. void AFXAPI SerializeElements(CArchive& ar, COleVariant* pElements, int nCount);
  138. void AFXAPI DumpElements(CDumpContext& dc, COleVariant* pElements, int nCount);
  139. UINT AFXAPI HashKey(const struct tagVARIANT& var);
  140. */
  141. // special versions for guids
  142. //void AFXAPI ConstructElements(GUID* pElements, int nCount);
  143. //void AFXAPI DestructElements(GUID* pElements, int nCount);
  144. //void AFXAPI CopyElements(GUID* pDest, const GUID* pSrc, int nCount);
  145. //void AFXAPI SerializeElements(CArchive& ar, GUID* pElements, int nCount);
  146. //UINT AFXAPI HashKey(GUID key);
  147. template<>
  148. inline UINT AFXAPI HashKey(GUID Key)
  149. {
  150. UINT hash = 0;
  151. BYTE FAR* lpb = (BYTE FAR*)&Key;
  152. UINT cbKey = sizeof(GUID);
  153. while (cbKey-- != 0)
  154. hash = 257 * hash + *lpb++;
  155. return hash;
  156. }
  157. template<>
  158. inline UINT AFXAPI HashKey(SYSTEMTIME Key)
  159. {
  160. UINT hash = 0;
  161. BYTE FAR* lpb = (BYTE FAR*)&Key;
  162. UINT cbKey = sizeof(SYSTEMTIME);
  163. while (cbKey-- != 0)
  164. hash = 257 * hash + *lpb++;
  165. return hash;
  166. }
  167. /*
  168. inline UINT AFXAPI HashKey(IXY Key)
  169. {
  170. UINT hash = 0;
  171. BYTE FAR* lpb = (BYTE FAR*)&Key;
  172. UINT cbKey = sizeof(IXY);
  173. while (cbKey-- != 0)
  174. hash = 257 * hash + *lpb++;
  175. return hash;
  176. }
  177. */
  178. //#define new DEBUG_NEW
  179. /////////////////////////////////////////////////////////////////////////////
  180. // CArray<TYPE, ARG_TYPE>
  181. template<class TYPE, class ARG_TYPE>
  182. class CArray : public CObject
  183. {
  184. public:
  185. // Construction
  186. CArray();
  187. // Attributes
  188. int GetSize() const;
  189. int GetUpperBound() const;
  190. void SetSize(int nNewSize, int nGrowBy = -1);
  191. // Operations
  192. // Clean up
  193. void FreeExtra();
  194. void RemoveAll();
  195. // Accessing elements
  196. TYPE GetAt(int nIndex) const;
  197. void SetAt(int nIndex, ARG_TYPE newElement);
  198. TYPE& ElementAt(int nIndex);
  199. // Direct Access to the element data (may return NULL)
  200. const TYPE* GetData() const;
  201. TYPE* GetData();
  202. // Potentially growing the array
  203. void SetAtGrow(int nIndex, ARG_TYPE newElement);
  204. int Add(ARG_TYPE newElement);
  205. int Append(const CArray& src);
  206. void Copy(const CArray& src);
  207. // overloaded operator helpers
  208. TYPE operator[](int nIndex) const;
  209. TYPE& operator[](int nIndex);
  210. // Operations that move elements around
  211. void InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
  212. void RemoveAt(int nIndex, int nCount = 1);
  213. void InsertAt(int nStartIndex, CArray* pNewArray);
  214. // Implementation
  215. protected:
  216. TYPE* m_pData; // the actual array of data
  217. int m_nSize; // # of elements (upperBound - 1)
  218. int m_nMaxSize; // max allocated
  219. int m_nGrowBy; // grow amount
  220. public:
  221. ~CArray();
  222. void Serialize(CArchive&);
  223. #ifdef _DEBUG
  224. void Dump(CDumpContext&) const;
  225. void AssertValid() const;
  226. #endif
  227. };
  228. /////////////////////////////////////////////////////////////////////////////
  229. // CArray<TYPE, ARG_TYPE> inline functions
  230. template<class TYPE, class ARG_TYPE>
  231. inline int CArray<TYPE, ARG_TYPE>::GetSize() const
  232. { return m_nSize; }
  233. template<class TYPE, class ARG_TYPE>
  234. inline int CArray<TYPE, ARG_TYPE>::GetUpperBound() const
  235. { return m_nSize-1; }
  236. template<class TYPE, class ARG_TYPE>
  237. inline void CArray<TYPE, ARG_TYPE>::RemoveAll()
  238. { SetSize(0, -1); }
  239. template<class TYPE, class ARG_TYPE>
  240. inline TYPE CArray<TYPE, ARG_TYPE>::GetAt(int nIndex) const
  241. { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  242. return m_pData[nIndex]; }
  243. template<class TYPE, class ARG_TYPE>
  244. inline void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, ARG_TYPE newElement)
  245. { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  246. m_pData[nIndex] = newElement; }
  247. template<class TYPE, class ARG_TYPE>
  248. inline TYPE& CArray<TYPE, ARG_TYPE>::ElementAt(int nIndex)
  249. { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  250. return m_pData[nIndex]; }
  251. template<class TYPE, class ARG_TYPE>
  252. inline const TYPE* CArray<TYPE, ARG_TYPE>::GetData() const
  253. { return (const TYPE*)m_pData; }
  254. template<class TYPE, class ARG_TYPE>
  255. inline TYPE* CArray<TYPE, ARG_TYPE>::GetData()
  256. { return (TYPE*)m_pData; }
  257. template<class TYPE, class ARG_TYPE>
  258. inline int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
  259. { int nIndex = m_nSize;
  260. SetAtGrow(nIndex, newElement);
  261. return nIndex; }
  262. template<class TYPE, class ARG_TYPE>
  263. inline TYPE CArray<TYPE, ARG_TYPE>::operator[](int nIndex) const
  264. { return GetAt(nIndex); }
  265. template<class TYPE, class ARG_TYPE>
  266. inline TYPE& CArray<TYPE, ARG_TYPE>::operator[](int nIndex)
  267. { return ElementAt(nIndex); }
  268. /////////////////////////////////////////////////////////////////////////////
  269. // CArray<TYPE, ARG_TYPE> out-of-line functions
  270. template<class TYPE, class ARG_TYPE>
  271. CArray<TYPE, ARG_TYPE>::CArray()
  272. {
  273. m_pData = NULL;
  274. m_nSize = m_nMaxSize = m_nGrowBy = 0;
  275. }
  276. template<class TYPE, class ARG_TYPE>
  277. CArray<TYPE, ARG_TYPE>::~CArray()
  278. {
  279. ASSERT_VALID(this);
  280. if (m_pData != NULL)
  281. {
  282. DestructElements(m_pData, m_nSize);
  283. delete[] (BYTE*)m_pData;
  284. }
  285. }
  286. template<class TYPE, class ARG_TYPE>
  287. void CArray<TYPE, ARG_TYPE>::SetSize(int nNewSize, int nGrowBy)
  288. {
  289. ASSERT_VALID(this);
  290. ASSERT(nNewSize >= 0);
  291. if (nGrowBy != -1)
  292. m_nGrowBy = nGrowBy; // set new size
  293. if (nNewSize == 0)
  294. {
  295. // shrink to nothing
  296. if (m_pData != NULL)
  297. {
  298. DestructElements(m_pData, m_nSize);
  299. delete[] (BYTE*)m_pData;
  300. m_pData = NULL;
  301. }
  302. m_nSize = m_nMaxSize = 0;
  303. }
  304. else if (m_pData == NULL)
  305. {
  306. // create one with exact size
  307. #ifdef SIZE_T_MAX
  308. ASSERT(nNewSize <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
  309. #endif
  310. m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)];
  311. ConstructElements(m_pData, nNewSize);
  312. m_nSize = m_nMaxSize = nNewSize;
  313. }
  314. else if (nNewSize <= m_nMaxSize)
  315. {
  316. // it fits
  317. if (nNewSize > m_nSize)
  318. {
  319. // initialize the new elements
  320. ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  321. }
  322. else if (m_nSize > nNewSize)
  323. {
  324. // destroy the old elements
  325. DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  326. }
  327. m_nSize = nNewSize;
  328. }
  329. else
  330. {
  331. // otherwise, grow array
  332. int nGrowBy = m_nGrowBy;
  333. if (nGrowBy == 0)
  334. {
  335. // heuristically determine growth when nGrowBy == 0
  336. // (this avoids heap fragmentation in many situations)
  337. nGrowBy = m_nSize / 8;
  338. nGrowBy = (nGrowBy < 4) ? 4 : ((nGrowBy > 1024) ? 1024 : nGrowBy);
  339. }
  340. int nNewMax;
  341. if (nNewSize < m_nMaxSize + nGrowBy)
  342. nNewMax = m_nMaxSize + nGrowBy; // granularity
  343. else
  344. nNewMax = nNewSize; // no slush
  345. ASSERT(nNewMax >= m_nMaxSize); // no wrap around
  346. #ifdef SIZE_T_MAX
  347. ASSERT(nNewMax <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
  348. #endif
  349. TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];
  350. // copy new data from old
  351. memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
  352. // construct remaining elements
  353. ASSERT(nNewSize > m_nSize);
  354. ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  355. // get rid of old stuff (note: no destructors called)
  356. delete[] (BYTE*)m_pData;
  357. m_pData = pNewData;
  358. m_nSize = nNewSize;
  359. m_nMaxSize = nNewMax;
  360. }
  361. }
  362. template<class TYPE, class ARG_TYPE>
  363. int CArray<TYPE, ARG_TYPE>::Append(const CArray& src)
  364. {
  365. ASSERT_VALID(this);
  366. ASSERT(this != &src); // cannot append to itself
  367. int nOldSize = m_nSize;
  368. SetSize(m_nSize + src.m_nSize);
  369. CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);
  370. return nOldSize;
  371. }
  372. template<class TYPE, class ARG_TYPE>
  373. void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src)
  374. {
  375. ASSERT_VALID(this);
  376. ASSERT(this != &src); // cannot append to itself
  377. SetSize(src.m_nSize);
  378. CopyElements(m_pData, src.m_pData, src.m_nSize);
  379. }
  380. template<class TYPE, class ARG_TYPE>
  381. void CArray<TYPE, ARG_TYPE>::FreeExtra()
  382. {
  383. ASSERT_VALID(this);
  384. if (m_nSize != m_nMaxSize)
  385. {
  386. // shrink to desired size
  387. #ifdef SIZE_T_MAX
  388. ASSERT(m_nSize <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
  389. #endif
  390. TYPE* pNewData = NULL;
  391. if (m_nSize != 0)
  392. {
  393. pNewData = (TYPE*) new BYTE[m_nSize * sizeof(TYPE)];
  394. // copy new data from old
  395. memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
  396. }
  397. // get rid of old stuff (note: no destructors called)
  398. delete[] (BYTE*)m_pData;
  399. m_pData = pNewData;
  400. m_nMaxSize = m_nSize;
  401. }
  402. }
  403. template<class TYPE, class ARG_TYPE>
  404. void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
  405. {
  406. ASSERT_VALID(this);
  407. ASSERT(nIndex >= 0);
  408. if (nIndex >= m_nSize)
  409. SetSize(nIndex+1, -1);
  410. m_pData[nIndex] = newElement;
  411. }
  412. template<class TYPE, class ARG_TYPE>
  413. void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, ARG_TYPE newElement, int nCount /*=1*/)
  414. {
  415. ASSERT_VALID(this);
  416. ASSERT(nIndex >= 0); // will expand to meet need
  417. ASSERT(nCount > 0); // zero or negative size not allowed
  418. if (nIndex >= m_nSize)
  419. {
  420. // adding after the end of the array
  421. SetSize(nIndex + nCount, -1); // grow so nIndex is valid
  422. }
  423. else
  424. {
  425. // inserting in the middle of the array
  426. int nOldSize = m_nSize;
  427. SetSize(m_nSize + nCount, -1); // grow it to new size
  428. // destroy intial data before copying over it
  429. DestructElements(&m_pData[nOldSize], nCount);
  430. // shift old data up to fill gap
  431. memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  432. (nOldSize-nIndex) * sizeof(TYPE));
  433. // re-init slots we copied from
  434. ConstructElements(&m_pData[nIndex], nCount);
  435. }
  436. // insert new value in the gap
  437. ASSERT(nIndex + nCount <= m_nSize);
  438. while (nCount--)
  439. m_pData[nIndex++] = newElement;
  440. }
  441. template<class TYPE, class ARG_TYPE>
  442. void CArray<TYPE, ARG_TYPE>::RemoveAt(int nIndex, int nCount)
  443. {
  444. ASSERT_VALID(this);
  445. ASSERT(nIndex >= 0);
  446. ASSERT(nCount >= 0);
  447. ASSERT(nIndex + nCount <= m_nSize);
  448. // just remove a range
  449. int nMoveCount = m_nSize - (nIndex + nCount);
  450. DestructElements(&m_pData[nIndex], nCount);
  451. if (nMoveCount)
  452. memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  453. nMoveCount * sizeof(TYPE));
  454. m_nSize -= nCount;
  455. }
  456. template<class TYPE, class ARG_TYPE>
  457. void CArray<TYPE, ARG_TYPE>::InsertAt(int nStartIndex, CArray* pNewArray)
  458. {
  459. ASSERT_VALID(this);
  460. ASSERT(pNewArray != NULL);
  461. ASSERT_VALID(pNewArray);
  462. ASSERT(nStartIndex >= 0);
  463. if (pNewArray->GetSize() > 0)
  464. {
  465. InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  466. for (int i = 0; i < pNewArray->GetSize(); i++)
  467. SetAt(nStartIndex + i, pNewArray->GetAt(i));
  468. }
  469. }
  470. template<class TYPE, class ARG_TYPE>
  471. void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
  472. {
  473. ASSERT_VALID(this);
  474. #ifndef unix
  475. // UNIX found decl commented out in coll.hxx
  476. CObject::Serialize(ar);
  477. #else
  478. MwBugCheck();
  479. #endif /* unix */
  480. #ifndef unix
  481. if (ar.IsStoring())
  482. {
  483. ar.WriteCount(m_nSize);
  484. }
  485. else
  486. {
  487. DWORD nOldSize = ar.ReadCount();
  488. SetSize(nOldSize, -1);
  489. }
  490. SerializeElements(ar, m_pData, m_nSize);
  491. #endif /* unix */
  492. }
  493. #ifdef _DEBUG
  494. #ifndef unix
  495. template<class TYPE, class ARG_TYPE>
  496. void CArray<TYPE, ARG_TYPE>::Dump(CDumpContext& dc) const
  497. {
  498. CObject::Dump(dc);
  499. dc << "with " << m_nSize << " elements";
  500. if (dc.GetDepth() > 0)
  501. {
  502. dc << "\n";
  503. DumpElements(dc, m_pData, m_nSize);
  504. }
  505. dc << "\n";
  506. }
  507. #endif /* unix */
  508. template<class TYPE, class ARG_TYPE>
  509. void CArray<TYPE, ARG_TYPE>::AssertValid() const
  510. {
  511. CObject::AssertValid();
  512. if (m_pData == NULL)
  513. {
  514. ASSERT(m_nSize == 0);
  515. ASSERT(m_nMaxSize == 0);
  516. }
  517. else
  518. {
  519. ASSERT(m_nSize >= 0);
  520. ASSERT(m_nMaxSize >= 0);
  521. ASSERT(m_nSize <= m_nMaxSize);
  522. ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(TYPE)));
  523. }
  524. }
  525. #endif //_DEBUG
  526. #define _LIST_DEFINED_
  527. #ifndef _LIST_DEFINED_
  528. /////////////////////////////////////////////////////////////////////////////
  529. // CList<TYPE, ARG_TYPE>
  530. template<class TYPE, class ARG_TYPE>
  531. class CList : public CObject
  532. {
  533. protected:
  534. struct CNode
  535. {
  536. CNode* pNext;
  537. CNode* pPrev;
  538. TYPE data;
  539. };
  540. public:
  541. // Construction
  542. CList(int nBlockSize = 10);
  543. // Attributes (head and tail)
  544. // count of elements
  545. int GetCount() const;
  546. BOOL IsEmpty() const;
  547. // peek at head or tail
  548. TYPE& GetHead();
  549. TYPE GetHead() const;
  550. TYPE& GetTail();
  551. TYPE GetTail() const;
  552. // Operations
  553. // get head or tail (and remove it) - don't call on empty list !
  554. TYPE RemoveHead();
  555. TYPE RemoveTail();
  556. // add before head or after tail
  557. POSITION AddHead(ARG_TYPE newElement);
  558. POSITION AddTail(ARG_TYPE newElement);
  559. // add another list of elements before head or after tail
  560. void AddHead(CList* pNewList);
  561. void AddTail(CList* pNewList);
  562. // remove all elements
  563. void RemoveAll();
  564. // iteration
  565. POSITION GetHeadPosition() const;
  566. POSITION GetTailPosition() const;
  567. TYPE& GetNext(POSITION& rPosition); // return *Position++
  568. TYPE GetNext(POSITION& rPosition) const; // return *Position++
  569. TYPE& GetPrev(POSITION& rPosition); // return *Position--
  570. TYPE GetPrev(POSITION& rPosition) const; // return *Position--
  571. // getting/modifying an element at a given position
  572. TYPE& GetAt(POSITION position);
  573. TYPE GetAt(POSITION position) const;
  574. void SetAt(POSITION pos, ARG_TYPE newElement);
  575. void RemoveAt(POSITION position);
  576. // inserting before or after a given position
  577. POSITION InsertBefore(POSITION position, ARG_TYPE newElement);
  578. POSITION InsertAfter(POSITION position, ARG_TYPE newElement);
  579. // helper functions (note: O(n) speed)
  580. POSITION Find(ARG_TYPE searchValue, POSITION startAfter = NULL) const;
  581. // defaults to starting at the HEAD, return NULL if not found
  582. POSITION FindIndex(int nIndex) const;
  583. // get the 'nIndex'th element (may return NULL)
  584. // Implementation
  585. protected:
  586. CNode* m_pNodeHead;
  587. CNode* m_pNodeTail;
  588. int m_nCount;
  589. CNode* m_pNodeFree;
  590. struct CPlex* m_pBlocks;
  591. int m_nBlockSize;
  592. CNode* NewNode(CNode*, CNode*);
  593. void FreeNode(CNode*);
  594. public:
  595. ~CList();
  596. void Serialize(CArchive&);
  597. #ifdef _DEBUG
  598. void Dump(CDumpContext&) const;
  599. void AssertValid() const;
  600. #endif
  601. };
  602. /////////////////////////////////////////////////////////////////////////////
  603. // CList<TYPE, ARG_TYPE> inline functions
  604. template<class TYPE, class ARG_TYPE>
  605. inline int CList<TYPE, ARG_TYPE>::GetCount() const
  606. { return m_nCount; }
  607. template<class TYPE, class ARG_TYPE>
  608. inline BOOL CList<TYPE, ARG_TYPE>::IsEmpty() const
  609. { return m_nCount == 0; }
  610. template<class TYPE, class ARG_TYPE>
  611. inline TYPE& CList<TYPE, ARG_TYPE>::GetHead()
  612. { ASSERT(m_pNodeHead != NULL);
  613. return m_pNodeHead->data; }
  614. template<class TYPE, class ARG_TYPE>
  615. inline TYPE CList<TYPE, ARG_TYPE>::GetHead() const
  616. { ASSERT(m_pNodeHead != NULL);
  617. return m_pNodeHead->data; }
  618. template<class TYPE, class ARG_TYPE>
  619. inline TYPE& CList<TYPE, ARG_TYPE>::GetTail()
  620. { ASSERT(m_pNodeTail != NULL);
  621. return m_pNodeTail->data; }
  622. template<class TYPE, class ARG_TYPE>
  623. inline TYPE CList<TYPE, ARG_TYPE>::GetTail() const
  624. { ASSERT(m_pNodeTail != NULL);
  625. return m_pNodeTail->data; }
  626. template<class TYPE, class ARG_TYPE>
  627. inline POSITION CList<TYPE, ARG_TYPE>::GetHeadPosition() const
  628. { return (POSITION) m_pNodeHead; }
  629. template<class TYPE, class ARG_TYPE>
  630. inline POSITION CList<TYPE, ARG_TYPE>::GetTailPosition() const
  631. { return (POSITION) m_pNodeTail; }
  632. template<class TYPE, class ARG_TYPE>
  633. inline TYPE& CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) // return *Position++
  634. { CNode* pNode = (CNode*) rPosition;
  635. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  636. rPosition = (POSITION) pNode->pNext;
  637. return pNode->data; }
  638. template<class TYPE, class ARG_TYPE>
  639. inline TYPE CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) const // return *Position++
  640. { CNode* pNode = (CNode*) rPosition;
  641. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  642. rPosition = (POSITION) pNode->pNext;
  643. return pNode->data; }
  644. template<class TYPE, class ARG_TYPE>
  645. inline TYPE& CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) // return *Position--
  646. { CNode* pNode = (CNode*) rPosition;
  647. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  648. rPosition = (POSITION) pNode->pPrev;
  649. return pNode->data; }
  650. template<class TYPE, class ARG_TYPE>
  651. inline TYPE CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) const // return *Position--
  652. { CNode* pNode = (CNode*) rPosition;
  653. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  654. rPosition = (POSITION) pNode->pPrev;
  655. return pNode->data; }
  656. template<class TYPE, class ARG_TYPE>
  657. inline TYPE& CList<TYPE, ARG_TYPE>::GetAt(POSITION position)
  658. { CNode* pNode = (CNode*) position;
  659. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  660. return pNode->data; }
  661. template<class TYPE, class ARG_TYPE>
  662. inline TYPE CList<TYPE, ARG_TYPE>::GetAt(POSITION position) const
  663. { CNode* pNode = (CNode*) position;
  664. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  665. return pNode->data; }
  666. template<class TYPE, class ARG_TYPE>
  667. inline void CList<TYPE, ARG_TYPE>::SetAt(POSITION pos, ARG_TYPE newElement)
  668. { CNode* pNode = (CNode*) pos;
  669. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  670. pNode->data = newElement; }
  671. template<class TYPE, class ARG_TYPE>
  672. CList<TYPE, ARG_TYPE>::CList(int nBlockSize)
  673. {
  674. ASSERT(nBlockSize > 0);
  675. m_nCount = 0;
  676. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  677. m_pBlocks = NULL;
  678. m_nBlockSize = nBlockSize;
  679. }
  680. template<class TYPE, class ARG_TYPE>
  681. void CList<TYPE, ARG_TYPE>::RemoveAll()
  682. {
  683. ASSERT_VALID(this);
  684. // destroy elements
  685. CNode* pNode;
  686. for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)
  687. DestructElements(&pNode->data, 1);
  688. m_nCount = 0;
  689. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  690. m_pBlocks->FreeDataChain();
  691. m_pBlocks = NULL;
  692. }
  693. template<class TYPE, class ARG_TYPE>
  694. CList<TYPE, ARG_TYPE>::~CList()
  695. {
  696. RemoveAll();
  697. ASSERT(m_nCount == 0);
  698. }
  699. /////////////////////////////////////////////////////////////////////////////
  700. // Node helpers
  701. //
  702. // Implementation note: CNode's are stored in CPlex blocks and
  703. // chained together. Free blocks are maintained in a singly linked list
  704. // using the 'pNext' member of CNode with 'm_pNodeFree' as the head.
  705. // Used blocks are maintained in a doubly linked list using both 'pNext'
  706. // and 'pPrev' as links and 'm_pNodeHead' and 'm_pNodeTail'
  707. // as the head/tail.
  708. //
  709. // We never free a CPlex block unless the List is destroyed or RemoveAll()
  710. // is used - so the total number of CPlex blocks may grow large depending
  711. // on the maximum past size of the list.
  712. //
  713. template<class TYPE, class ARG_TYPE>
  714. typename CList<TYPE, ARG_TYPE>::CNode*
  715. CList<TYPE, ARG_TYPE>::NewNode(CNode* pPrev, CNode* pNext)
  716. {
  717. if (m_pNodeFree == NULL)
  718. {
  719. // add another block
  720. CPlex* pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize,
  721. sizeof(CNode));
  722. // chain them into free list
  723. CNode* pNode = (CNode*) pNewBlock->data();
  724. // free in reverse order to make it easier to debug
  725. pNode += m_nBlockSize - 1;
  726. for (int i = m_nBlockSize-1; i >= 0; i--, pNode--)
  727. {
  728. pNode->pNext = m_pNodeFree;
  729. m_pNodeFree = pNode;
  730. }
  731. }
  732. ASSERT(m_pNodeFree != NULL); // we must have something
  733. CList::CNode* pNode = m_pNodeFree;
  734. m_pNodeFree = m_pNodeFree->pNext;
  735. pNode->pPrev = pPrev;
  736. pNode->pNext = pNext;
  737. m_nCount++;
  738. ASSERT(m_nCount > 0); // make sure we don't overflow
  739. ConstructElements(&pNode->data, 1);
  740. return pNode;
  741. }
  742. template<class TYPE, class ARG_TYPE>
  743. void CList<TYPE, ARG_TYPE>::FreeNode(CNode* pNode)
  744. {
  745. DestructElements(&pNode->data, 1);
  746. pNode->pNext = m_pNodeFree;
  747. m_pNodeFree = pNode;
  748. m_nCount--;
  749. ASSERT(m_nCount >= 0); // make sure we don't underflow
  750. // if no more elements, cleanup completely
  751. if (m_nCount == 0)
  752. RemoveAll();
  753. }
  754. template<class TYPE, class ARG_TYPE>
  755. POSITION CList<TYPE, ARG_TYPE>::AddHead(ARG_TYPE newElement)
  756. {
  757. ASSERT_VALID(this);
  758. CNode* pNewNode = NewNode(NULL, m_pNodeHead);
  759. pNewNode->data = newElement;
  760. if (m_pNodeHead != NULL)
  761. m_pNodeHead->pPrev = pNewNode;
  762. else
  763. m_pNodeTail = pNewNode;
  764. m_pNodeHead = pNewNode;
  765. return (POSITION) pNewNode;
  766. }
  767. template<class TYPE, class ARG_TYPE>
  768. POSITION CList<TYPE, ARG_TYPE>::AddTail(ARG_TYPE newElement)
  769. {
  770. ASSERT_VALID(this);
  771. CNode* pNewNode = NewNode(m_pNodeTail, NULL);
  772. pNewNode->data = newElement;
  773. if (m_pNodeTail != NULL)
  774. m_pNodeTail->pNext = pNewNode;
  775. else
  776. m_pNodeHead = pNewNode;
  777. m_pNodeTail = pNewNode;
  778. return (POSITION) pNewNode;
  779. }
  780. template<class TYPE, class ARG_TYPE>
  781. void CList<TYPE, ARG_TYPE>::AddHead(CList* pNewList)
  782. {
  783. ASSERT_VALID(this);
  784. ASSERT(pNewList != NULL);
  785. ASSERT_VALID(pNewList);
  786. // add a list of same elements to head (maintain order)
  787. POSITION pos = pNewList->GetTailPosition();
  788. while (pos != NULL)
  789. AddHead(pNewList->GetPrev(pos));
  790. }
  791. template<class TYPE, class ARG_TYPE>
  792. void CList<TYPE, ARG_TYPE>::AddTail(CList* pNewList)
  793. {
  794. ASSERT_VALID(this);
  795. ASSERT(pNewList != NULL);
  796. ASSERT_VALID(pNewList);
  797. // add a list of same elements
  798. POSITION pos = pNewList->GetHeadPosition();
  799. while (pos != NULL)
  800. AddTail(pNewList->GetNext(pos));
  801. }
  802. template<class TYPE, class ARG_TYPE>
  803. TYPE CList<TYPE, ARG_TYPE>::RemoveHead()
  804. {
  805. ASSERT_VALID(this);
  806. ASSERT(m_pNodeHead != NULL); // don't call on empty list !!!
  807. ASSERT(AfxIsValidAddress(m_pNodeHead, sizeof(CNode)));
  808. CNode* pOldNode = m_pNodeHead;
  809. TYPE returnValue = pOldNode->data;
  810. m_pNodeHead = pOldNode->pNext;
  811. if (m_pNodeHead != NULL)
  812. m_pNodeHead->pPrev = NULL;
  813. else
  814. m_pNodeTail = NULL;
  815. FreeNode(pOldNode);
  816. return returnValue;
  817. }
  818. template<class TYPE, class ARG_TYPE>
  819. TYPE CList<TYPE, ARG_TYPE>::RemoveTail()
  820. {
  821. ASSERT_VALID(this);
  822. ASSERT(m_pNodeTail != NULL); // don't call on empty list !!!
  823. ASSERT(AfxIsValidAddress(m_pNodeTail, sizeof(CNode)));
  824. CNode* pOldNode = m_pNodeTail;
  825. TYPE returnValue = pOldNode->data;
  826. m_pNodeTail = pOldNode->pPrev;
  827. if (m_pNodeTail != NULL)
  828. m_pNodeTail->pNext = NULL;
  829. else
  830. m_pNodeHead = NULL;
  831. FreeNode(pOldNode);
  832. return returnValue;
  833. }
  834. template<class TYPE, class ARG_TYPE>
  835. POSITION CList<TYPE, ARG_TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement)
  836. {
  837. ASSERT_VALID(this);
  838. if (position == NULL)
  839. return AddHead(newElement); // insert before nothing -> head of the list
  840. // Insert it before position
  841. CNode* pOldNode = (CNode*) position;
  842. CNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode);
  843. pNewNode->data = newElement;
  844. if (pOldNode->pPrev != NULL)
  845. {
  846. ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(CNode)));
  847. pOldNode->pPrev->pNext = pNewNode;
  848. }
  849. else
  850. {
  851. ASSERT(pOldNode == m_pNodeHead);
  852. m_pNodeHead = pNewNode;
  853. }
  854. pOldNode->pPrev = pNewNode;
  855. return (POSITION) pNewNode;
  856. }
  857. template<class TYPE, class ARG_TYPE>
  858. POSITION CList<TYPE, ARG_TYPE>::InsertAfter(POSITION position, ARG_TYPE newElement)
  859. {
  860. ASSERT_VALID(this);
  861. if (position == NULL)
  862. return AddTail(newElement); // insert after nothing -> tail of the list
  863. // Insert it before position
  864. CNode* pOldNode = (CNode*) position;
  865. ASSERT(AfxIsValidAddress(pOldNode, sizeof(CNode)));
  866. CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
  867. pNewNode->data = newElement;
  868. if (pOldNode->pNext != NULL)
  869. {
  870. ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(CNode)));
  871. pOldNode->pNext->pPrev = pNewNode;
  872. }
  873. else
  874. {
  875. ASSERT(pOldNode == m_pNodeTail);
  876. m_pNodeTail = pNewNode;
  877. }
  878. pOldNode->pNext = pNewNode;
  879. return (POSITION) pNewNode;
  880. }
  881. template<class TYPE, class ARG_TYPE>
  882. void CList<TYPE, ARG_TYPE>::RemoveAt(POSITION position)
  883. {
  884. ASSERT_VALID(this);
  885. CNode* pOldNode = (CNode*) position;
  886. ASSERT(AfxIsValidAddress(pOldNode, sizeof(CNode)));
  887. // remove pOldNode from list
  888. if (pOldNode == m_pNodeHead)
  889. {
  890. m_pNodeHead = pOldNode->pNext;
  891. }
  892. else
  893. {
  894. ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(CNode)));
  895. pOldNode->pPrev->pNext = pOldNode->pNext;
  896. }
  897. if (pOldNode == m_pNodeTail)
  898. {
  899. m_pNodeTail = pOldNode->pPrev;
  900. }
  901. else
  902. {
  903. ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(CNode)));
  904. pOldNode->pNext->pPrev = pOldNode->pPrev;
  905. }
  906. FreeNode(pOldNode);
  907. }
  908. template<class TYPE, class ARG_TYPE>
  909. POSITION CList<TYPE, ARG_TYPE>::FindIndex(int nIndex) const
  910. {
  911. ASSERT_VALID(this);
  912. ASSERT(nIndex >= 0);
  913. if (nIndex >= m_nCount)
  914. return NULL; // went too far
  915. CNode* pNode = m_pNodeHead;
  916. while (nIndex--)
  917. {
  918. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  919. pNode = pNode->pNext;
  920. }
  921. return (POSITION) pNode;
  922. }
  923. template<class TYPE, class ARG_TYPE>
  924. POSITION CList<TYPE, ARG_TYPE>::Find(ARG_TYPE searchValue, POSITION startAfter) const
  925. {
  926. ASSERT_VALID(this);
  927. CNode* pNode = (CNode*) startAfter;
  928. if (pNode == NULL)
  929. {
  930. pNode = m_pNodeHead; // start at head
  931. }
  932. else
  933. {
  934. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  935. pNode = pNode->pNext; // start after the one specified
  936. }
  937. for (; pNode != NULL; pNode = pNode->pNext)
  938. if (CompareElements(&pNode->data, &searchValue))
  939. return (POSITION)pNode;
  940. return NULL;
  941. }
  942. template<class TYPE, class ARG_TYPE>
  943. void CList<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
  944. {
  945. ASSERT_VALID(this);
  946. #ifndef unix
  947. // UNIX found decl commented out in coll.hxx
  948. CObject::Serialize(ar);
  949. #else
  950. MwBugCheck();
  951. #endif /* unix */
  952. #ifndef unix
  953. if (ar.IsStoring())
  954. {
  955. ar.WriteCount(m_nCount);
  956. for (CNode* pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)
  957. {
  958. ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
  959. SerializeElements(ar, &pNode->data, 1);
  960. }
  961. }
  962. else
  963. {
  964. DWORD nNewCount = ar.ReadCount();
  965. TYPE newData;
  966. while (nNewCount--)
  967. {
  968. SerializeElements(ar, &newData, 1);
  969. AddTail(newData);
  970. }
  971. }
  972. #endif /* unix */
  973. }
  974. #ifdef _DEBUG
  975. template<class TYPE, class ARG_TYPE>
  976. void CList<TYPE, ARG_TYPE>::Dump(CDumpContext& dc) const
  977. {
  978. CObject::Dump(dc);
  979. dc << "with " << m_nCount << " elements";
  980. if (dc.GetDepth() > 0)
  981. {
  982. POSITION pos = GetHeadPosition();
  983. while (pos != NULL)
  984. {
  985. dc << "\n";
  986. DumpElements(dc, &((CList*)this)->GetNext(pos), 1);
  987. }
  988. }
  989. dc << "\n";
  990. }
  991. template<class TYPE, class ARG_TYPE>
  992. void CList<TYPE, ARG_TYPE>::AssertValid() const
  993. {
  994. CObject::AssertValid();
  995. if (m_nCount == 0)
  996. {
  997. // empty list
  998. ASSERT(m_pNodeHead == NULL);
  999. ASSERT(m_pNodeTail == NULL);
  1000. }
  1001. else
  1002. {
  1003. // non-empty list
  1004. ASSERT(AfxIsValidAddress(m_pNodeHead, sizeof(CNode)));
  1005. ASSERT(AfxIsValidAddress(m_pNodeTail, sizeof(CNode)));
  1006. }
  1007. }
  1008. #endif //_DEBUG
  1009. #endif //LIST_DEFINED
  1010. /////////////////////////////////////////////////////////////////////////////
  1011. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>
  1012. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1013. class CMap : public CObject
  1014. {
  1015. #ifndef unix
  1016. protected:
  1017. #else
  1018. // If this was not made public we get complier warnings
  1019. // that CMap<T,...>::CAssoc is not accessible from file scope
  1020. // which means functions cant return CNode pointers
  1021. public:
  1022. #endif /* unix */
  1023. // Association
  1024. struct CAssoc
  1025. {
  1026. CAssoc* pNext;
  1027. UINT nHashValue; // needed for efficient iteration
  1028. KEY key;
  1029. VALUE value;
  1030. };
  1031. public:
  1032. // Construction
  1033. CMap(int nBlockSize = 10);
  1034. // Attributes
  1035. // number of elements
  1036. int GetCount() const;
  1037. BOOL IsEmpty() const;
  1038. // Lookup
  1039. BOOL Lookup(ARG_KEY key, VALUE& rValue) const;
  1040. // Operations
  1041. // Lookup and add if not there
  1042. VALUE& operator[](ARG_KEY key);
  1043. // add a new (key, value) pair
  1044. void SetAt(ARG_KEY key, ARG_VALUE newValue);
  1045. // removing existing (key, ?) pair
  1046. BOOL RemoveKey(ARG_KEY key);
  1047. void RemoveAll();
  1048. // iterating all (key, value) pairs
  1049. POSITION GetStartPosition() const;
  1050. void GetNextAssoc(POSITION& rNextPosition, KEY& rKey, VALUE& rValue) const;
  1051. // advanced features for derived classes
  1052. UINT GetHashTableSize() const;
  1053. void InitHashTable(UINT hashSize, BOOL bAllocNow = TRUE);
  1054. // Implementation
  1055. protected:
  1056. CAssoc** m_pHashTable;
  1057. UINT m_nHashTableSize;
  1058. int m_nCount;
  1059. CAssoc* m_pFreeList;
  1060. struct CPlex* m_pBlocks;
  1061. int m_nBlockSize;
  1062. CAssoc* NewAssoc();
  1063. void FreeAssoc(CAssoc*);
  1064. CAssoc* GetAssocAt(ARG_KEY, UINT&) const;
  1065. public:
  1066. ~CMap();
  1067. void Serialize(CArchive&);
  1068. #ifdef _DEBUG
  1069. void Dump(CDumpContext&) const;
  1070. void AssertValid() const;
  1071. #endif
  1072. };
  1073. /////////////////////////////////////////////////////////////////////////////
  1074. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> inline functions
  1075. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1076. inline int CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetCount() const
  1077. { return m_nCount; }
  1078. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1079. inline BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::IsEmpty() const
  1080. { return m_nCount == 0; }
  1081. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1082. inline void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::SetAt(ARG_KEY key, ARG_VALUE newValue)
  1083. { (*this)[key] = newValue; }
  1084. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1085. inline POSITION CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetStartPosition() const
  1086. { return (m_nCount == 0) ? NULL : BEFORE_START_POSITION; }
  1087. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1088. inline UINT CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetHashTableSize() const
  1089. { return m_nHashTableSize; }
  1090. /////////////////////////////////////////////////////////////////////////////
  1091. // CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> out-of-line functions
  1092. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1093. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMap(int nBlockSize)
  1094. {
  1095. ASSERT(nBlockSize > 0);
  1096. m_pHashTable = NULL;
  1097. m_nHashTableSize = 17; // default size
  1098. m_nCount = 0;
  1099. m_pFreeList = NULL;
  1100. m_pBlocks = NULL;
  1101. m_nBlockSize = nBlockSize;
  1102. }
  1103. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1104. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::InitHashTable(
  1105. UINT nHashSize, BOOL bAllocNow)
  1106. //
  1107. // Used to force allocation of a hash table or to override the default
  1108. // hash table size of (which is fairly small)
  1109. {
  1110. ASSERT_VALID(this);
  1111. ASSERT(m_nCount == 0);
  1112. ASSERT(nHashSize > 0);
  1113. if (m_pHashTable != NULL)
  1114. {
  1115. // free hash table
  1116. delete[] m_pHashTable;
  1117. m_pHashTable = NULL;
  1118. }
  1119. if (bAllocNow)
  1120. {
  1121. m_pHashTable = new CAssoc* [nHashSize];
  1122. memset(m_pHashTable, 0, sizeof(CAssoc*) * nHashSize);
  1123. }
  1124. m_nHashTableSize = nHashSize;
  1125. }
  1126. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1127. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveAll()
  1128. {
  1129. ASSERT_VALID(this);
  1130. if (m_pHashTable != NULL)
  1131. {
  1132. // destroy elements (values and keys)
  1133. for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
  1134. {
  1135. CAssoc* pAssoc;
  1136. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
  1137. pAssoc = pAssoc->pNext)
  1138. {
  1139. DestructElements(&pAssoc->value, 1);
  1140. DestructElements(&pAssoc->key, 1);
  1141. }
  1142. }
  1143. // free hash table
  1144. delete[] m_pHashTable;
  1145. m_pHashTable = NULL;
  1146. }
  1147. m_nCount = 0;
  1148. m_pFreeList = NULL;
  1149. if (m_pBlocks)
  1150. {
  1151. m_pBlocks->FreeDataChain();
  1152. m_pBlocks = NULL;
  1153. }
  1154. }
  1155. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1156. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::~CMap()
  1157. {
  1158. if (m_nCount)
  1159. {
  1160. RemoveAll();
  1161. }
  1162. ASSERT(m_nCount == 0);
  1163. }
  1164. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1165. typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
  1166. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::NewAssoc()
  1167. {
  1168. if (m_pFreeList == NULL)
  1169. {
  1170. // add another block
  1171. CPlex* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CMap::CAssoc));
  1172. // chain them into free list
  1173. CMap::CAssoc* pAssoc = (CMap::CAssoc*) newBlock->data();
  1174. // free in reverse order to make it easier to debug
  1175. pAssoc += m_nBlockSize - 1;
  1176. for (int i = m_nBlockSize-1; i >= 0; i--, pAssoc--)
  1177. {
  1178. pAssoc->pNext = m_pFreeList;
  1179. m_pFreeList = pAssoc;
  1180. }
  1181. }
  1182. ASSERT(m_pFreeList != NULL); // we must have something
  1183. CMap::CAssoc* pAssoc = m_pFreeList;
  1184. m_pFreeList = m_pFreeList->pNext;
  1185. m_nCount++;
  1186. ASSERT(m_nCount > 0); // make sure we don't overflow
  1187. ConstructElements(&pAssoc->key, 1);
  1188. ConstructElements(&pAssoc->value, 1); // special construct values
  1189. return pAssoc;
  1190. }
  1191. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1192. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::FreeAssoc(CAssoc* pAssoc)
  1193. {
  1194. DestructElements(&pAssoc->value, 1);
  1195. DestructElements(&pAssoc->key, 1);
  1196. pAssoc->pNext = m_pFreeList;
  1197. m_pFreeList = pAssoc;
  1198. m_nCount--;
  1199. ASSERT(m_nCount >= 0); // make sure we don't underflow
  1200. // if no more elements, cleanup completely
  1201. if (m_nCount == 0)
  1202. RemoveAll();
  1203. }
  1204. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1205. typename CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::CAssoc*
  1206. CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAssocAt(ARG_KEY key, UINT& nHash) const
  1207. // find association (or return NULL)
  1208. {
  1209. nHash = HashKey(key) % m_nHashTableSize;
  1210. if (m_pHashTable == NULL)
  1211. return NULL;
  1212. // see if it exists
  1213. CAssoc* pAssoc;
  1214. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
  1215. {
  1216. if (CompareElements(&pAssoc->key, &key))
  1217. return pAssoc;
  1218. }
  1219. return NULL;
  1220. }
  1221. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1222. BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Lookup(ARG_KEY key, VALUE& rValue) const
  1223. {
  1224. ASSERT_VALID(this);
  1225. UINT nHash;
  1226. CAssoc* pAssoc = GetAssocAt(key, nHash);
  1227. if (pAssoc == NULL)
  1228. return FALSE; // not in map
  1229. rValue = pAssoc->value;
  1230. return TRUE;
  1231. }
  1232. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1233. VALUE& CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator[](ARG_KEY key)
  1234. {
  1235. ASSERT_VALID(this);
  1236. UINT nHash;
  1237. CAssoc* pAssoc;
  1238. if ((pAssoc = GetAssocAt(key, nHash)) == NULL)
  1239. {
  1240. if (m_pHashTable == NULL)
  1241. InitHashTable(m_nHashTableSize);
  1242. // it doesn't exist, add a new Association
  1243. pAssoc = NewAssoc();
  1244. pAssoc->nHashValue = nHash;
  1245. pAssoc->key = key;
  1246. // 'pAssoc->value' is a constructed object, nothing more
  1247. // put into hash table
  1248. pAssoc->pNext = m_pHashTable[nHash];
  1249. m_pHashTable[nHash] = pAssoc;
  1250. }
  1251. return pAssoc->value; // return new reference
  1252. }
  1253. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1254. BOOL CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::RemoveKey(ARG_KEY key)
  1255. // remove key - return TRUE if removed
  1256. {
  1257. ASSERT_VALID(this);
  1258. if (m_pHashTable == NULL)
  1259. return FALSE; // nothing in the table
  1260. CAssoc** ppAssocPrev;
  1261. ppAssocPrev = &m_pHashTable[HashKey(key) % m_nHashTableSize];
  1262. CAssoc* pAssoc;
  1263. for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
  1264. {
  1265. if (CompareElements(&pAssoc->key, &key))
  1266. {
  1267. // remove it
  1268. *ppAssocPrev = pAssoc->pNext; // remove from list
  1269. FreeAssoc(pAssoc);
  1270. return TRUE;
  1271. }
  1272. ppAssocPrev = &pAssoc->pNext;
  1273. }
  1274. return FALSE; // not found
  1275. }
  1276. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1277. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetNextAssoc(POSITION& rNextPosition,
  1278. KEY& rKey, VALUE& rValue) const
  1279. {
  1280. ASSERT_VALID(this);
  1281. ASSERT(m_pHashTable != NULL); // never call on empty map
  1282. CAssoc* pAssocRet = (CAssoc*)rNextPosition;
  1283. ASSERT(pAssocRet != NULL);
  1284. if (pAssocRet == (CAssoc*) BEFORE_START_POSITION)
  1285. {
  1286. // find the first association
  1287. for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
  1288. if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
  1289. break;
  1290. ASSERT(pAssocRet != NULL); // must find something
  1291. }
  1292. // find next association
  1293. ASSERT(AfxIsValidAddress(pAssocRet, sizeof(CAssoc)));
  1294. CAssoc* pAssocNext;
  1295. if ((pAssocNext = pAssocRet->pNext) == NULL)
  1296. {
  1297. // go to next bucket
  1298. for (UINT nBucket = pAssocRet->nHashValue + 1;
  1299. nBucket < m_nHashTableSize; nBucket++)
  1300. if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
  1301. break;
  1302. }
  1303. rNextPosition = (POSITION) pAssocNext;
  1304. // fill in return data
  1305. rKey = pAssocRet->key;
  1306. rValue = pAssocRet->value;
  1307. }
  1308. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1309. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Serialize(CArchive& ar)
  1310. {
  1311. ASSERT_VALID(this);
  1312. #ifndef unix
  1313. // UNIX found dedcl commented out in coll.hxx
  1314. CObject::Serialize(ar);
  1315. #endif /* unix */
  1316. if (ar.IsStoring())
  1317. {
  1318. ar.WriteCount(m_nCount);
  1319. if (m_nCount == 0)
  1320. return; // nothing more to do
  1321. ASSERT(m_pHashTable != NULL);
  1322. for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
  1323. {
  1324. CAssoc* pAssoc;
  1325. for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
  1326. pAssoc = pAssoc->pNext)
  1327. {
  1328. SerializeElements(ar, &pAssoc->key, 1);
  1329. SerializeElements(ar, &pAssoc->value, 1);
  1330. }
  1331. }
  1332. }
  1333. else
  1334. {
  1335. DWORD nNewCount = ar.ReadCount();
  1336. KEY newKey;
  1337. VALUE newValue;
  1338. while (nNewCount--)
  1339. {
  1340. SerializeElements(ar, &newKey, 1);
  1341. SerializeElements(ar, &newValue, 1);
  1342. SetAt(newKey, newValue);
  1343. }
  1344. }
  1345. }
  1346. #ifdef _DEBUG
  1347. #ifndef unix
  1348. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1349. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::Dump(CDumpContext& dc) const
  1350. {
  1351. CObject::Dump(dc);
  1352. dc << "with " << m_nCount << " elements";
  1353. if (dc.GetDepth() > 0)
  1354. {
  1355. // Dump in format "[key] -> value"
  1356. KEY key;
  1357. VALUE val;
  1358. POSITION pos = GetStartPosition();
  1359. while (pos != NULL)
  1360. {
  1361. GetNextAssoc(pos, key, val);
  1362. dc << "\n\t[";
  1363. DumpElements(dc, &key, 1);
  1364. dc << "] = ";
  1365. DumpElements(dc, &val, 1);
  1366. }
  1367. }
  1368. dc << "\n";
  1369. }
  1370. #endif /* unix */
  1371. template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
  1372. void CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::AssertValid() const
  1373. {
  1374. CObject::AssertValid();
  1375. ASSERT(m_nHashTableSize > 0);
  1376. ASSERT(m_nCount == 0 || m_pHashTable != NULL);
  1377. // non-empty map should have hash table
  1378. }
  1379. #endif //_DEBUG
  1380. /////////////////////////////////////////////////////////////////////////////
  1381. // CTypedPtrArray<BASE_CLASS, TYPE>
  1382. template<class BASE_CLASS, class TYPE>
  1383. class CTypedPtrArray : public BASE_CLASS
  1384. {
  1385. public:
  1386. // Accessing elements
  1387. TYPE GetAt(int nIndex) const
  1388. { return (TYPE)BASE_CLASS::GetAt(nIndex); }
  1389. TYPE& ElementAt(int nIndex)
  1390. { return (TYPE&)BASE_CLASS::ElementAt(nIndex); }
  1391. void SetAt(int nIndex, TYPE ptr)
  1392. { BASE_CLASS::SetAt(nIndex, ptr); }
  1393. // Potentially growing the array
  1394. void SetAtGrow(int nIndex, TYPE newElement)
  1395. { BASE_CLASS::SetAtGrow(nIndex, newElement); }
  1396. int Add(TYPE newElement)
  1397. { return BASE_CLASS::Add(newElement); }
  1398. int Append(const CTypedPtrArray<BASE_CLASS, TYPE>& src)
  1399. { return BASE_CLASS::Append(src); }
  1400. void Copy(const CTypedPtrArray<BASE_CLASS, TYPE>& src)
  1401. { BASE_CLASS::Copy(src); }
  1402. // Operations that move elements around
  1403. void InsertAt(int nIndex, TYPE newElement, int nCount = 1)
  1404. { BASE_CLASS::InsertAt(nIndex, newElement, nCount); }
  1405. void InsertAt(int nStartIndex, CTypedPtrArray<BASE_CLASS, TYPE>* pNewArray)
  1406. { BASE_CLASS::InsertAt(nStartIndex, pNewArray); }
  1407. // overloaded operator helpers
  1408. TYPE operator[](int nIndex) const
  1409. { return (TYPE)BASE_CLASS::operator[](nIndex); }
  1410. TYPE& operator[](int nIndex)
  1411. { return (TYPE&)BASE_CLASS::operator[](nIndex); }
  1412. };
  1413. /////////////////////////////////////////////////////////////////////////////
  1414. // CTypedPtrList<BASE_CLASS, TYPE>
  1415. template<class BASE_CLASS, class TYPE>
  1416. class CTypedPtrList : public BASE_CLASS
  1417. {
  1418. public:
  1419. // Construction
  1420. CTypedPtrList(int nBlockSize = 10)
  1421. : BASE_CLASS(nBlockSize) { }
  1422. // peek at head or tail
  1423. TYPE& GetHead()
  1424. { return (TYPE&)BASE_CLASS::GetHead(); }
  1425. TYPE GetHead() const
  1426. { return (TYPE)BASE_CLASS::GetHead(); }
  1427. TYPE& GetTail()
  1428. { return (TYPE&)BASE_CLASS::GetTail(); }
  1429. TYPE GetTail() const
  1430. { return (TYPE)BASE_CLASS::GetTail(); }
  1431. // get head or tail (and remove it) - don't call on empty list!
  1432. TYPE RemoveHead()
  1433. { return (TYPE)BASE_CLASS::RemoveHead(); }
  1434. TYPE RemoveTail()
  1435. { return (TYPE)BASE_CLASS::RemoveTail(); }
  1436. // add before head or after tail
  1437. POSITION AddHead(TYPE newElement)
  1438. { return BASE_CLASS::AddHead(newElement); }
  1439. POSITION AddTail(TYPE newElement)
  1440. { return BASE_CLASS::AddTail(newElement); }
  1441. // add another list of elements before head or after tail
  1442. void AddHead(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
  1443. { BASE_CLASS::AddHead(pNewList); }
  1444. void AddTail(CTypedPtrList<BASE_CLASS, TYPE>* pNewList)
  1445. { BASE_CLASS::AddTail(pNewList); }
  1446. // iteration
  1447. TYPE& GetNext(POSITION& rPosition)
  1448. { return (TYPE&)BASE_CLASS::GetNext(rPosition); }
  1449. TYPE GetNext(POSITION& rPosition) const
  1450. { return (TYPE)BASE_CLASS::GetNext(rPosition); }
  1451. TYPE& GetPrev(POSITION& rPosition)
  1452. { return (TYPE&)BASE_CLASS::GetPrev(rPosition); }
  1453. TYPE GetPrev(POSITION& rPosition) const
  1454. { return (TYPE)BASE_CLASS::GetPrev(rPosition); }
  1455. // getting/modifying an element at a given position
  1456. TYPE& GetAt(POSITION position)
  1457. { return (TYPE&)BASE_CLASS::GetAt(position); }
  1458. TYPE GetAt(POSITION position) const
  1459. { return (TYPE)BASE_CLASS::GetAt(position); }
  1460. void SetAt(POSITION pos, TYPE newElement)
  1461. { BASE_CLASS::SetAt(pos, newElement); }
  1462. };
  1463. /////////////////////////////////////////////////////////////////////////////
  1464. // CTypedPtrMap<BASE_CLASS, KEY, VALUE>
  1465. template<class BASE_CLASS, class KEY, class VALUE>
  1466. class CTypedPtrMap : public BASE_CLASS
  1467. {
  1468. public:
  1469. // Construction
  1470. CTypedPtrMap(int nBlockSize = 10)
  1471. : BASE_CLASS(nBlockSize) { }
  1472. // Lookup
  1473. BOOL Lookup(typename BASE_CLASS::BASE_ARG_KEY key, VALUE& rValue) const
  1474. { return BASE_CLASS::Lookup(key, (BASE_CLASS::BASE_VALUE&)rValue); }
  1475. // Lookup and add if not there
  1476. VALUE& operator[](typename BASE_CLASS::BASE_ARG_KEY key)
  1477. { return (VALUE&)BASE_CLASS::operator[](key); }
  1478. // add a new key (key, value) pair
  1479. void SetAt(KEY key, VALUE newValue)
  1480. { BASE_CLASS::SetAt(key, newValue); }
  1481. // removing existing (key, ?) pair
  1482. BOOL RemoveKey(KEY key)
  1483. { return BASE_CLASS::RemoveKey(key); }
  1484. // iteration
  1485. void GetNextAssoc(POSITION& rPosition, KEY& rKey, VALUE& rValue) const
  1486. { BASE_CLASS::GetNextAssoc(rPosition, (BASE_CLASS::BASE_KEY&)rKey,
  1487. (BASE_CLASS::BASE_VALUE&)rValue); }
  1488. };
  1489. /////////////////////////////////////////////////////////////////////////////
  1490. #undef THIS_FILE
  1491. #define THIS_FILE __FILE__
  1492. #undef new
  1493. #ifdef _REDEF_NEW
  1494. #define new DEBUG_NEW
  1495. #undef _REDEF_NEW
  1496. #endif
  1497. #ifdef _AFX_PACKING
  1498. #pragma pack(pop)
  1499. #endif
  1500. #ifdef _AFX_MINREBUILD
  1501. #pragma component(minrebuild, on)
  1502. #endif
  1503. #ifndef _AFX_FULLTYPEINFO
  1504. #pragma component(mintypeinfo, off)
  1505. #endif
  1506. #endif //__AFXTEMPL_H__
  1507. /////////////////////////////////////////////////////////////////////////////