home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / utility / templdef / array.ctt < prev    next >
Encoding:
Text File  |  1998-03-27  |  17.9 KB  |  711 lines

  1. ////////////////////////////////////////////////////////////////////////////
  2. // class CArray<TYPE, ARG_TYPE> - an array containing 'TYPE' elements,
  3. // passed in parameters as ARG_TYPE
  4. //
  5. // optional definitions:
  6. //  IS_SERIAL       - include serialization (see below for types)
  7. //  IS_RAW_SERIAL   - use CArchive::Write and Read for serialization
  8. //  IS_ARCHIVE_SERIAL - use CArchive insersion, extraction for serialization
  9. //  HAS_CREATE      - call constructors and destructors
  10. //
  11. // This is a part of the Microsoft Foundation Classes C++ library.
  12. // Copyright (C) 1994-1998 Microsoft Corporation
  13. // All rights reserved.
  14. //
  15. // This source code is only intended as a supplement to the
  16. // Microsoft Foundation Classes Reference and related
  17. // electronic documentation provided with the library.
  18. // See these sources for detailed information regarding the
  19. // Microsoft Foundation Classes product.
  20. ////////////////////////////////////////////////////////////////////////////
  21.  
  22. //$DECLARE_TEMPLATE
  23. ////////////////////////////////////////////////////////////////////////////
  24. template<class TYPE, class ARG_TYPE>
  25. class CArray : public CObject
  26. {
  27. $ifdef IS_SERIAL
  28.     DECLARE_SERIAL(CArray)
  29. $else
  30.     DECLARE_DYNAMIC(CArray)
  31. $endif  //!IS_SERIAL
  32. public:
  33.  
  34. // Construction
  35.     CArray();
  36.  
  37. // Attributes
  38.     int GetSize() const;
  39.     int GetUpperBound() const;
  40.     void SetSize(int nNewSize, int nGrowBy = -1);
  41.  
  42. // Operations
  43.     // Clean up
  44.     void FreeExtra();
  45.     void RemoveAll();
  46.  
  47.     // Accessing elements
  48.     TYPE GetAt(int nIndex) const;
  49.     void SetAt(int nIndex, ARG_TYPE newElement);
  50. $ifdef INCLUDE_TYPEREF
  51.     void SetAt(int nIndex, const TYPE& newElement);
  52. $endif
  53.     TYPE& ElementAt(int nIndex);
  54.  
  55.     // Direct Access to the element data (may return NULL)
  56.     const TYPE* GetData() const;
  57.     TYPE* GetData();
  58.  
  59.     // Potentially growing the array
  60.     void SetAtGrow(int nIndex, ARG_TYPE newElement);
  61. $ifdef INCLUDE_TYPEREF
  62.     void SetAtGrow(int nIndex, const TYPE& newElement);
  63. $endif
  64.     int Add(ARG_TYPE newElement);
  65. $ifdef INCLUDE_TYPEREF
  66.     int Add(const TYPE& newElement);
  67. $endif
  68.     int Append(const CArray& src);
  69.     void Copy(const CArray& src);
  70.  
  71.     // overloaded operator helpers
  72.     TYPE operator[](int nIndex) const;
  73.     TYPE& operator[](int nIndex);
  74.  
  75.     // Operations that move elements around
  76.     void InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);
  77. $ifdef INCLUDE_TYPEREF
  78.     void InsertAt(int nIndex, const TYPE& newElement, int nCount = 1);
  79. $endif
  80.     void RemoveAt(int nIndex, int nCount = 1);
  81.     void InsertAt(int nStartIndex, CArray* pNewArray);
  82.  
  83. // Implementation
  84. protected:
  85.     TYPE* m_pData;   // the actual array of data
  86.     int m_nSize;     // # of elements (upperBound - 1)
  87.     int m_nMaxSize;  // max allocated
  88.     int m_nGrowBy;   // grow amount
  89. $ifdef INCLUDE_TYPEREF
  90.     void InsertEmpty(int nIndex, int nCount);
  91. $endif
  92.  
  93. public:
  94.     ~CArray();
  95. $ifdef IS_SERIAL
  96.     void Serialize(CArchive&);
  97. $endif  //IS_SERIAL
  98. #ifdef _DEBUG
  99.     void Dump(CDumpContext&) const;
  100.     void AssertValid() const;
  101. #endif
  102.  
  103. protected:
  104.     // local typedefs for class templates
  105.     typedef TYPE BASE_TYPE;
  106.     typedef ARG_TYPE BASE_ARG_TYPE;
  107. };
  108.  
  109. //$IMPLEMENT_TEMPLATE_INLINES
  110. ////////////////////////////////////////////////////////////////////////////
  111.  
  112. template<class TYPE, class ARG_TYPE>
  113. _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::GetSize() const
  114.     { return m_nSize; }
  115. template<class TYPE, class ARG_TYPE>
  116. _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::GetUpperBound() const
  117.     { return m_nSize-1; }
  118. template<class TYPE, class ARG_TYPE>
  119. _AFXCOLL_INLINE void CArray<TYPE, ARG_TYPE>::RemoveAll()
  120.     { SetSize(0); }
  121. template<class TYPE, class ARG_TYPE>
  122. _AFXCOLL_INLINE TYPE CArray<TYPE, ARG_TYPE>::GetAt(int nIndex) const
  123.     { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  124.         return m_pData[nIndex]; }
  125. template<class TYPE, class ARG_TYPE>
  126. _AFXCOLL_INLINE void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, ARG_TYPE newElement)
  127.     { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  128.         m_pData[nIndex] = newElement; }
  129. $ifdef INCLUDE_TYPEREF
  130. template<class TYPE, class ARG_TYPE>
  131. _AFXCOLL_INLINE void CArray<TYPE, ARG_TYPE>::SetAt(int nIndex, const TYPE& newElement)
  132.     { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  133.         m_pData[nIndex] = newElement; }
  134. $endif
  135. template<class TYPE, class ARG_TYPE>
  136. _AFXCOLL_INLINE TYPE& CArray<TYPE, ARG_TYPE>::ElementAt(int nIndex)
  137.     { ASSERT(nIndex >= 0 && nIndex < m_nSize);
  138.         return m_pData[nIndex]; }
  139. template<class TYPE, class ARG_TYPE>
  140. _AFXCOLL_INLINE const TYPE* CArray<TYPE, ARG_TYPE>::GetData() const
  141.     { return (const TYPE*)m_pData; }
  142. template<class TYPE, class ARG_TYPE>
  143. _AFXCOLL_INLINE TYPE* CArray<TYPE, ARG_TYPE>::GetData()
  144.     { return (TYPE*)m_pData; }
  145. template<class TYPE, class ARG_TYPE>
  146. _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)
  147.     { int nIndex = m_nSize;
  148.         SetAtGrow(nIndex, newElement);
  149.         return nIndex; }
  150. $ifdef INCLUDE_TYPEREF
  151. template<class TYPE, class ARG_TYPE>
  152. _AFXCOLL_INLINE int CArray<TYPE, ARG_TYPE>::Add(const TYPE& newElement)
  153.     { int nIndex = m_nSize;
  154.         SetAtGrow(nIndex, newElement);
  155.         return nIndex; }
  156. $endif
  157. template<class TYPE, class ARG_TYPE>
  158. _AFXCOLL_INLINE TYPE CArray<TYPE, ARG_TYPE>::operator[](int nIndex) const
  159.     { return GetAt(nIndex); }
  160. template<class TYPE, class ARG_TYPE>
  161. _AFXCOLL_INLINE TYPE& CArray<TYPE, ARG_TYPE>::operator[](int nIndex)
  162.     { return ElementAt(nIndex); }
  163.  
  164. //$IMPLEMENT_TEMPLATE
  165. // This is a part of the Microsoft Foundation Classes C++ library.
  166. // Copyright (C) 1992-1997 Microsoft Corporation
  167. // All rights reserved.
  168. //
  169. // This source code is only intended as a supplement to the
  170. // Microsoft Foundation Classes Reference and related
  171. // electronic documentation provided with the library.
  172. // See these sources for detailed information regarding the
  173. // Microsoft Foundation Classes product.
  174.  
  175. /////////////////////////////////////////////////////////////////////////////
  176. //
  177. // Implementation of parameterized Array
  178. //
  179. /////////////////////////////////////////////////////////////////////////////
  180. // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
  181. //  the current size 'm_nSize' contains properly constructed
  182. //  objects.
  183.  
  184. #include "stdafx.h"
  185.  
  186. #ifdef AFX_COLL_SEG
  187. #pragma code_seg(AFX_COLL_SEG)
  188. #endif
  189.  
  190. #ifdef _DEBUG
  191. #undef THIS_FILE
  192. static char THIS_FILE[] = __FILE__;
  193. #endif
  194.  
  195. #define new DEBUG_NEW
  196.  
  197. $ifdef HAS_CREATE
  198. /////////////////////////////////////////////////////////////////////////////
  199.  
  200. #include "elements.h"  // used for special creation
  201.  
  202. static void ConstructElements(TYPE* pNewData, int nCount)
  203. {
  204.     ASSERT(nCount >= 0);
  205.  
  206.     while (nCount--)
  207.     {
  208.         ConstructElement(pNewData);
  209.         pNewData++;
  210.     }
  211. }
  212.  
  213. static void DestructElements(TYPE* pOldData, int nCount)
  214. {
  215.     ASSERT(nCount >= 0);
  216.  
  217.     while (nCount--)
  218.     {
  219.         DestructElement(pOldData);
  220.         pOldData++;
  221.     }
  222. }
  223.  
  224. static void CopyElements(TYPE* pDest, TYPE* pSrc, int nCount)
  225. {
  226.     ASSERT(nCount >= 0);
  227.  
  228.     while (nCount--)
  229.     {
  230.         *pDest = *pSrc;
  231.         ++pDest;
  232.         ++pSrc;
  233.     }
  234. }
  235. $endif //HAS_CREATE
  236.  
  237. /////////////////////////////////////////////////////////////////////////////
  238.  
  239. template<class TYPE, class ARG_TYPE>
  240. CArray<TYPE, ARG_TYPE>::CArray()
  241. {
  242.     m_pData = NULL;
  243.     m_nSize = m_nMaxSize = m_nGrowBy = 0;
  244. }
  245.  
  246. template<class TYPE, ARG_TYPE>
  247. CArray<TYPE, ARG_TYPE>::~CArray()
  248. {
  249.     ASSERT_VALID(this);
  250.  
  251. $ifdef HAS_CREATE
  252.     DestructElements(m_pData, m_nSize);
  253. $endif //HAS_CREATE
  254.     delete[] (BYTE*)m_pData;
  255. }
  256.  
  257. template<class TYPE, class ARG_TYPE>
  258. void CArray<TYPE, ARG_TYPE>::SetSize(int nNewSize, int nGrowBy)
  259. {
  260.     ASSERT_VALID(this);
  261.     ASSERT(nNewSize >= 0);
  262.  
  263.     if (nGrowBy != -1)
  264.         m_nGrowBy = nGrowBy;  // set new size
  265.  
  266.     if (nNewSize == 0)
  267.     {
  268.         // shrink to nothing
  269. $ifdef HAS_CREATE
  270.         DestructElements(m_pData, m_nSize);
  271. $endif //HAS_CREATE
  272.         delete[] (BYTE*)m_pData;
  273.         m_pData = NULL;
  274.         m_nSize = m_nMaxSize = 0;
  275.     }
  276.     else if (m_pData == NULL)
  277.     {
  278.         // create one with exact size
  279. #ifdef SIZE_T_MAX
  280.         ASSERT(nNewSize <= SIZE_T_MAX/sizeof(TYPE));    // no overflow
  281. #endif
  282.         m_pData = (TYPE*) new BYTE[nNewSize * sizeof(TYPE)];
  283. $ifdef HAS_CREATE
  284.         ConstructElements(m_pData, nNewSize);
  285. $else
  286.         memset(m_pData, 0, nNewSize * sizeof(TYPE));  // zero fill
  287. $endif
  288.         m_nSize = m_nMaxSize = nNewSize;
  289.     }
  290.     else if (nNewSize <= m_nMaxSize)
  291.     {
  292.         // it fits
  293.         if (nNewSize > m_nSize)
  294.         {
  295.             // initialize the new elements
  296. $ifdef HAS_CREATE
  297.             ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  298. $else
  299.             memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(TYPE));
  300. $endif
  301.         }
  302. $ifdef HAS_CREATE
  303.         else if (m_nSize > nNewSize)  // destroy the old elements
  304.             DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  305. $endif
  306.         m_nSize = nNewSize;
  307.     }
  308.     else
  309.     {
  310.         // otherwise, grow array
  311.         int nGrowBy = m_nGrowBy;
  312.         if (nGrowBy == 0)
  313.         {
  314.             // heuristically determine growth when nGrowBy == 0
  315.             //  (this avoids heap fragmentation in many situations)
  316.             nGrowBy = min(1024, max(4, m_nSize / 8));
  317.         }
  318.         int nNewMax;
  319.         if (nNewSize < m_nMaxSize + nGrowBy)
  320.             nNewMax = m_nMaxSize + nGrowBy;  // granularity
  321.         else
  322.             nNewMax = nNewSize;  // no slush
  323.  
  324.         ASSERT(nNewMax >= m_nMaxSize);  // no wrap around
  325. #ifdef SIZE_T_MAX
  326.         ASSERT(nNewMax <= SIZE_T_MAX/sizeof(TYPE)); // no overflow
  327. #endif
  328.         TYPE* pNewData = (TYPE*) new BYTE[nNewMax * sizeof(TYPE)];
  329.  
  330.         // copy new data from old
  331.         memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE));
  332.  
  333.         // construct remaining elements
  334.         ASSERT(nNewSize > m_nSize);
  335. $ifdef HAS_CREATE
  336.         ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  337. $else
  338.         memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(TYPE));
  339. $endif
  340.  
  341.         // get rid of old stuff (note: no destructors called)
  342.         delete[] (BYTE*)m_pData;
  343.         m_pData = pNewData;
  344.         m_nSize = nNewSize;
  345.         m_nMaxSize = nNewMax;
  346.     }
  347. }
  348.  
  349. template<class TYPE, class ARG_TYPE>
  350. int CArray<TYPE, ARG_TYPE>::Append(const CArray& src)
  351. {
  352.     ASSERT_VALID(this);
  353.     ASSERT(this != &src);   // cannot append to itself
  354.  
  355.     int nOldSize = m_nSize;
  356.     SetSize(m_nSize + src.m_nSize);
  357. $ifdef HAS_CREATE
  358.     CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);
  359. $else
  360.     memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(TYPE));
  361. $endif
  362.     return nOldSize;
  363. }
  364.  
  365. template<class TYPE, class ARG_TYPE>
  366. void CArray<TYPE, ARG_TYPE>::Copy(const CArray& src)
  367. {
  368.     ASSERT_VALID(this);
  369.     ASSERT(this != &src);   // cannot append to itself
  370.  
  371.     SetSize(src.m_nSize);
  372. $ifdef HAS_CREATE
  373.     CopyElements(m_pData, src.m_pData, src.m_nSize);
  374. $else
  375.     memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(TYPE));
  376. $endif
  377. }
  378.  
  379. template<class TYPE, class ARG_TYPE>
  380. void CArray<TYPE, ARG_TYPE>::FreeExtra()
  381. {
  382.     ASSERT_VALID(this);
  383.  
  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.  
  398.         // get rid of old stuff (note: no destructors called)
  399.         delete[] (BYTE*)m_pData;
  400.         m_pData = pNewData;
  401.         m_nMaxSize = m_nSize;
  402.     }
  403. }
  404.  
  405. /////////////////////////////////////////////////////////////////////////////
  406.  
  407. template<class TYPE, class ARG_TYPE>
  408. void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, ARG_TYPE newElement)
  409. {
  410.     ASSERT_VALID(this);
  411.     ASSERT(nIndex >= 0);
  412.  
  413.     if (nIndex >= m_nSize)
  414.         SetSize(nIndex+1);
  415.     m_pData[nIndex] = newElement;
  416. }
  417.  
  418. $ifdef INCLUDE_TYPEREF
  419. template<class TYPE, class ARG_TYPE>
  420. void CArray<TYPE, ARG_TYPE>::SetAtGrow(int nIndex, const TYPE& newElement)
  421. {
  422.     ASSERT_VALID(this);
  423.     ASSERT(nIndex >= 0);
  424.  
  425.     if (nIndex >= m_nSize)
  426.         SetSize(nIndex+1);
  427.     m_pData[nIndex] = newElement;
  428. }
  429. $endif
  430.  
  431. $ifdef INCLUDE_TYPEREF
  432. template<class TYPE, class ARG_TYPE>
  433. void CArray<TYPE, ARG_TYPE>::InsertEmpty(int nIndex, int nCount)
  434. {
  435.     ASSERT_VALID(this);
  436.     ASSERT(nIndex >= 0);    // will expand to meet need
  437.     ASSERT(nCount > 0);     // zero or negative size not allowed
  438.  
  439.     if (nIndex >= m_nSize)
  440.     {
  441.         // adding after the end of the array
  442.         SetSize(nIndex + nCount);  // grow so nIndex is valid
  443.     }
  444.     else
  445.     {
  446.         // inserting in the middle of the array
  447.         int nOldSize = m_nSize;
  448.         SetSize(m_nSize + nCount);  // grow it to new size
  449.         // shift old data up to fill gap
  450.         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  451.             (nOldSize-nIndex) * sizeof(TYPE));
  452.  
  453.         // re-init slots we copied from
  454. $ifdef HAS_CREATE
  455.         ConstructElements(&m_pData[nIndex], nCount);
  456. $else
  457.         memset(&m_pData[nIndex], 0, nCount * sizeof(TYPE));
  458. $endif
  459.     }
  460.  
  461.     // insert new value in the gap
  462.     ASSERT(nIndex + nCount <= m_nSize);
  463. }
  464. $endif
  465.  
  466. template<class TYPE, class ARG_TYPE>
  467. void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, ARG_TYPE newElement, int nCount)
  468. {
  469. $ifdef INCLUDE_TYPEREF
  470.     // make room for new elements
  471.     InsertEmpty(nIndex, nCount);
  472. $else
  473.     ASSERT_VALID(this);
  474.     ASSERT(nIndex >= 0);    // will expand to meet need
  475.     ASSERT(nCount > 0);     // zero or negative size not allowed
  476.  
  477.     if (nIndex >= m_nSize)
  478.     {
  479.         // adding after the end of the array
  480.         SetSize(nIndex + nCount);  // grow so nIndex is valid
  481.     }
  482.     else
  483.     {
  484.         // inserting in the middle of the array
  485.         int nOldSize = m_nSize;
  486.         SetSize(m_nSize + nCount);  // grow it to new size
  487.         // shift old data up to fill gap
  488.         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  489.             (nOldSize-nIndex) * sizeof(TYPE));
  490.  
  491.         // re-init slots we copied from
  492. $ifdef HAS_CREATE
  493.         ConstructElements(&m_pData[nIndex], nCount);
  494. $else
  495.         memset(&m_pData[nIndex], 0, nCount * sizeof(TYPE));
  496. $endif
  497.     }
  498.  
  499.     // insert new value in the gap
  500.     ASSERT(nIndex + nCount <= m_nSize);
  501. $endif
  502.  
  503. $ifndef INCLUDE_TYPEREF
  504.     // copy elements into the empty space
  505.     while (nCount--)
  506.         m_pData[nIndex++] = newElement;
  507. $else
  508.     // copy elements into the empty space
  509.     TYPE temp = newElement;
  510.     while (nCount--)
  511.         m_pData[nIndex++] = temp;
  512. $endif
  513. }
  514.  
  515. $ifdef INCLUDE_TYPEREF
  516. template<class TYPE, class ARG_TYPE>
  517. void CArray<TYPE, ARG_TYPE>::InsertAt(int nIndex, const TYPE& newElement, int nCount)
  518. {
  519.     // make room for new elements
  520.     InsertEmpty(nIndex, nCount);
  521.  
  522.     // copy elements into the empty space
  523.     while (nCount--)
  524.         m_pData[nIndex++] = newElement;
  525. }
  526. $endif
  527.  
  528. template<class TYPE, class ARG_TYPE>
  529. void CArray<TYPE, ARG_TYPE>::RemoveAt(int nIndex, int nCount)
  530. {
  531.     ASSERT_VALID(this);
  532.     ASSERT(nIndex >= 0);
  533.     ASSERT(nCount >= 0);
  534.     ASSERT(nIndex + nCount <= m_nSize);
  535.  
  536.     // just remove a range
  537.     int nMoveCount = m_nSize - (nIndex + nCount);
  538. $ifdef HAS_CREATE
  539.     DestructElements(&m_pData[nIndex], nCount);
  540. $endif
  541.     if (nMoveCount)
  542.         memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  543.             nMoveCount * sizeof(TYPE));
  544.     m_nSize -= nCount;
  545. }
  546.  
  547. template<class TYPE, class ARG_TYPE>
  548. void CArray<TYPE, ARG_TYPE>::InsertAt(int nStartIndex, CArray* pNewArray)
  549. {
  550.     ASSERT_VALID(this);
  551.     ASSERT(pNewArray != NULL);
  552.     ASSERT_KINDOF(CArray, pNewArray);
  553.     ASSERT_VALID(pNewArray);
  554.     ASSERT(nStartIndex >= 0);
  555.  
  556.     if (pNewArray->GetSize() > 0)
  557.     {
  558.         InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  559.         for (int i = 0; i < pNewArray->GetSize(); i++)
  560.             SetAt(nStartIndex + i, pNewArray->GetAt(i));
  561.     }
  562. }
  563. $ifdef IS_ARCHIVE_SERIAL
  564.  
  565. /////////////////////////////////////////////////////////////////////////////
  566. // Serialization
  567.  
  568. template<class TYPE, class ARG_TYPE>
  569. void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
  570. {
  571.     ASSERT_VALID(this);
  572.  
  573.     CObject::Serialize(ar);
  574.  
  575.     if (ar.IsStoring())
  576.     {
  577.         ar.WriteCount(m_nSize);
  578.         for (int i = 0; i < m_nSize; i++)
  579.             ar << m_pData[i];
  580.     }
  581.     else
  582.     {
  583.         DWORD nOldSize = ar.ReadCount();
  584.         SetSize(nOldSize);
  585.         for (int i = 0; i < m_nSize; i++)
  586.             ar >> m_pData[i];
  587.     }
  588. }
  589. $endif //IS_ARCHIVE_SERIAL
  590.  
  591. $ifdef IS_RAW_SERIAL
  592.  
  593. /////////////////////////////////////////////////////////////////////////////
  594. // Serialization
  595.  
  596. template<class TYPE, class ARG_TYPE>
  597. void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
  598. {
  599.     ASSERT_VALID(this);
  600.  
  601.     CObject::Serialize(ar);
  602.  
  603.     if (ar.IsStoring())
  604.     {
  605.         ar.WriteCount(m_nSize);
  606.         ar.Write(m_pData, m_nSize * sizeof(TYPE));
  607.     }
  608.     else
  609.     {
  610.         DWORD nOldSize = ar.ReadCount();
  611.         SetSize(nOldSize);
  612.         ar.Read(m_pData, m_nSize * sizeof(TYPE));
  613.     }
  614. }
  615. $endif //IS_RAW_SERIAL
  616.  
  617. $ifdef IS_SWAP_SERIAL
  618.  
  619. /////////////////////////////////////////////////////////////////////////////
  620. // Serialization
  621.  
  622. template<class TYPE, class ARG_TYPE>
  623. void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
  624. {
  625.     ASSERT_VALID(this);
  626.  
  627.     CObject::Serialize(ar);
  628.  
  629.     if (ar.IsStoring())
  630.     {
  631.         ar.WriteCount(m_nSize);
  632. #ifdef _AFX_BYTESWAP
  633.         if (!ar.IsByteSwapping())
  634. #endif
  635.         ar.Write(m_pData, m_nSize * sizeof(TYPE));
  636. #ifdef _AFX_BYTESWAP
  637.         else
  638.         {
  639.             // write each item individually so that it will be byte-swapped
  640.             for (int i = 0; i < m_nSize; i++)
  641.                 ar << m_pData[i];
  642.         }
  643. #endif
  644.     }
  645.     else
  646.     {
  647.         DWORD nOldSize = ar.ReadCount();
  648.         SetSize(nOldSize);
  649.         ar.Read(m_pData, m_nSize * sizeof(TYPE));
  650. #ifdef _AFX_BYTESWAP
  651.         if (ar.IsByteSwapping())
  652.         {
  653.             for (int i = 0; i < m_nSize; i++)
  654.                 _AfxByteSwap(m_pData[i], (BYTE*)&m_pData[i]);
  655.         }
  656. #endif
  657.     }
  658. }
  659. $endif //IS_SWAP_SERIAL
  660.  
  661. /////////////////////////////////////////////////////////////////////////////
  662. // Diagnostics
  663.  
  664. #ifdef _DEBUG
  665. template<class TYPE, class ARG_TYPE>
  666. void CArray<TYPE, ARG_TYPE>::Dump(CDumpContext& dc) const
  667. {
  668.     CObject::Dump(dc);
  669.  
  670.     dc << "with " << m_nSize << " elements";
  671.     if (dc.GetDepth() > 0)
  672.     {
  673.         for (int i = 0; i < m_nSize; i++)
  674.             dc << "\n\t[" << i << "] = " << m_pData[i];
  675.     }
  676.  
  677.     dc << "\n";
  678. }
  679.  
  680. template<class TYPE, class ARG_TYPE>
  681. void CArray<TYPE, ARG_TYPE>::AssertValid() const
  682. {
  683.     CObject::AssertValid();
  684.  
  685.     if (m_pData == NULL)
  686.     {
  687.         ASSERT(m_nSize == 0);
  688.         ASSERT(m_nMaxSize == 0);
  689.     }
  690.     else
  691.     {
  692.         ASSERT(m_nSize >= 0);
  693.         ASSERT(m_nMaxSize >= 0);
  694.         ASSERT(m_nSize <= m_nMaxSize);
  695.         ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(TYPE)));
  696.     }
  697. }
  698. #endif //_DEBUG
  699.  
  700. #ifdef AFX_INIT_SEG
  701. #pragma code_seg(AFX_INIT_SEG)
  702. #endif
  703.  
  704. $ifdef IS_SERIAL
  705. IMPLEMENT_SERIAL(CArray, CObject, 0)
  706. $else
  707. IMPLEMENT_DYNAMIC(CArray, CObject)
  708. $endif //!IS_SERIAL
  709.  
  710. /////////////////////////////////////////////////////////////////////////////
  711.