home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / array_d.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  8KB  |  354 lines

  1.  
  2. // This is a part of the Microsoft Foundation Classes C++ library.
  3. // Copyright (C) 1992-1998 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // This source code is only intended as a supplement to the
  7. // Microsoft Foundation Classes Reference and related
  8. // electronic documentation provided with the library.
  9. // See these sources for detailed information regarding the
  10. // Microsoft Foundation Classes product.
  11.  
  12. /////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Implementation of parameterized Array
  15. //
  16. /////////////////////////////////////////////////////////////////////////////
  17. // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
  18. //  the current size 'm_nSize' contains properly constructed
  19. //  objects.
  20.  
  21. #include "stdafx.h"
  22.  
  23. #ifdef AFX_COLL_SEG
  24. #pragma code_seg(AFX_COLL_SEG)
  25. #endif
  26.  
  27. #ifdef _DEBUG
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31.  
  32. #define new DEBUG_NEW
  33.  
  34.  
  35. /////////////////////////////////////////////////////////////////////////////
  36.  
  37. CDWordArray::CDWordArray()
  38. {
  39.     m_pData = NULL;
  40.     m_nSize = m_nMaxSize = m_nGrowBy = 0;
  41. }
  42.  
  43. CDWordArray::~CDWordArray()
  44. {
  45.     ASSERT_VALID(this);
  46.  
  47.     delete[] (BYTE*)m_pData;
  48. }
  49.  
  50. void CDWordArray::SetSize(int nNewSize, int nGrowBy)
  51. {
  52.     ASSERT_VALID(this);
  53.     ASSERT(nNewSize >= 0);
  54.  
  55.     if (nGrowBy != -1)
  56.         m_nGrowBy = nGrowBy;  // set new size
  57.  
  58.     if (nNewSize == 0)
  59.     {
  60.         // shrink to nothing
  61.         delete[] (BYTE*)m_pData;
  62.         m_pData = NULL;
  63.         m_nSize = m_nMaxSize = 0;
  64.     }
  65.     else if (m_pData == NULL)
  66.     {
  67.         // create one with exact size
  68. #ifdef SIZE_T_MAX
  69.         ASSERT(nNewSize <= SIZE_T_MAX/sizeof(DWORD));    // no overflow
  70. #endif
  71.         m_pData = (DWORD*) new BYTE[nNewSize * sizeof(DWORD)];
  72.  
  73.         memset(m_pData, 0, nNewSize * sizeof(DWORD));  // zero fill
  74.  
  75.         m_nSize = m_nMaxSize = nNewSize;
  76.     }
  77.     else if (nNewSize <= m_nMaxSize)
  78.     {
  79.         // it fits
  80.         if (nNewSize > m_nSize)
  81.         {
  82.             // initialize the new elements
  83.  
  84.             memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(DWORD));
  85.  
  86.         }
  87.  
  88.         m_nSize = nNewSize;
  89.     }
  90.     else
  91.     {
  92.         // otherwise, grow array
  93.         int nGrowBy = m_nGrowBy;
  94.         if (nGrowBy == 0)
  95.         {
  96.             // heuristically determine growth when nGrowBy == 0
  97.             //  (this avoids heap fragmentation in many situations)
  98.             nGrowBy = min(1024, max(4, m_nSize / 8));
  99.         }
  100.         int nNewMax;
  101.         if (nNewSize < m_nMaxSize + nGrowBy)
  102.             nNewMax = m_nMaxSize + nGrowBy;  // granularity
  103.         else
  104.             nNewMax = nNewSize;  // no slush
  105.  
  106.         ASSERT(nNewMax >= m_nMaxSize);  // no wrap around
  107. #ifdef SIZE_T_MAX
  108.         ASSERT(nNewMax <= SIZE_T_MAX/sizeof(DWORD)); // no overflow
  109. #endif
  110.         DWORD* pNewData = (DWORD*) new BYTE[nNewMax * sizeof(DWORD)];
  111.  
  112.         // copy new data from old
  113.         memcpy(pNewData, m_pData, m_nSize * sizeof(DWORD));
  114.  
  115.         // construct remaining elements
  116.         ASSERT(nNewSize > m_nSize);
  117.  
  118.         memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(DWORD));
  119.  
  120.  
  121.         // get rid of old stuff (note: no destructors called)
  122.         delete[] (BYTE*)m_pData;
  123.         m_pData = pNewData;
  124.         m_nSize = nNewSize;
  125.         m_nMaxSize = nNewMax;
  126.     }
  127. }
  128.  
  129. int CDWordArray::Append(const CDWordArray& src)
  130. {
  131.     ASSERT_VALID(this);
  132.     ASSERT(this != &src);   // cannot append to itself
  133.  
  134.     int nOldSize = m_nSize;
  135.     SetSize(m_nSize + src.m_nSize);
  136.  
  137.     memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(DWORD));
  138.  
  139.     return nOldSize;
  140. }
  141.  
  142. void CDWordArray::Copy(const CDWordArray& src)
  143. {
  144.     ASSERT_VALID(this);
  145.     ASSERT(this != &src);   // cannot append to itself
  146.  
  147.     SetSize(src.m_nSize);
  148.  
  149.     memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(DWORD));
  150.  
  151. }
  152.  
  153. void CDWordArray::FreeExtra()
  154. {
  155.     ASSERT_VALID(this);
  156.  
  157.     if (m_nSize != m_nMaxSize)
  158.     {
  159.         // shrink to desired size
  160. #ifdef SIZE_T_MAX
  161.         ASSERT(m_nSize <= SIZE_T_MAX/sizeof(DWORD)); // no overflow
  162. #endif
  163.         DWORD* pNewData = NULL;
  164.         if (m_nSize != 0)
  165.         {
  166.             pNewData = (DWORD*) new BYTE[m_nSize * sizeof(DWORD)];
  167.             // copy new data from old
  168.             memcpy(pNewData, m_pData, m_nSize * sizeof(DWORD));
  169.         }
  170.  
  171.         // get rid of old stuff (note: no destructors called)
  172.         delete[] (BYTE*)m_pData;
  173.         m_pData = pNewData;
  174.         m_nMaxSize = m_nSize;
  175.     }
  176. }
  177.  
  178. /////////////////////////////////////////////////////////////////////////////
  179.  
  180. void CDWordArray::SetAtGrow(int nIndex, DWORD newElement)
  181. {
  182.     ASSERT_VALID(this);
  183.     ASSERT(nIndex >= 0);
  184.  
  185.     if (nIndex >= m_nSize)
  186.         SetSize(nIndex+1);
  187.     m_pData[nIndex] = newElement;
  188. }
  189.  
  190.  
  191.  
  192.  
  193.  
  194. void CDWordArray::InsertAt(int nIndex, DWORD newElement, int nCount)
  195. {
  196.  
  197.     ASSERT_VALID(this);
  198.     ASSERT(nIndex >= 0);    // will expand to meet need
  199.     ASSERT(nCount > 0);     // zero or negative size not allowed
  200.  
  201.     if (nIndex >= m_nSize)
  202.     {
  203.         // adding after the end of the array
  204.         SetSize(nIndex + nCount);  // grow so nIndex is valid
  205.     }
  206.     else
  207.     {
  208.         // inserting in the middle of the array
  209.         int nOldSize = m_nSize;
  210.         SetSize(m_nSize + nCount);  // grow it to new size
  211.         // shift old data up to fill gap
  212.         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  213.             (nOldSize-nIndex) * sizeof(DWORD));
  214.  
  215.         // re-init slots we copied from
  216.  
  217.         memset(&m_pData[nIndex], 0, nCount * sizeof(DWORD));
  218.  
  219.     }
  220.  
  221.     // insert new value in the gap
  222.     ASSERT(nIndex + nCount <= m_nSize);
  223.  
  224.  
  225.  
  226.     // copy elements into the empty space
  227.     while (nCount--)
  228.         m_pData[nIndex++] = newElement;
  229.  
  230. }
  231.  
  232.  
  233.  
  234. void CDWordArray::RemoveAt(int nIndex, int nCount)
  235. {
  236.     ASSERT_VALID(this);
  237.     ASSERT(nIndex >= 0);
  238.     ASSERT(nCount >= 0);
  239.     ASSERT(nIndex + nCount <= m_nSize);
  240.  
  241.     // just remove a range
  242.     int nMoveCount = m_nSize - (nIndex + nCount);
  243.  
  244.     if (nMoveCount)
  245.         memmove(&m_pData[nIndex], &m_pData[nIndex + nCount],
  246.             nMoveCount * sizeof(DWORD));
  247.     m_nSize -= nCount;
  248. }
  249.  
  250. void CDWordArray::InsertAt(int nStartIndex, CDWordArray* pNewArray)
  251. {
  252.     ASSERT_VALID(this);
  253.     ASSERT(pNewArray != NULL);
  254.     ASSERT_KINDOF(CDWordArray, pNewArray);
  255.     ASSERT_VALID(pNewArray);
  256.     ASSERT(nStartIndex >= 0);
  257.  
  258.     if (pNewArray->GetSize() > 0)
  259.     {
  260.         InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  261.         for (int i = 0; i < pNewArray->GetSize(); i++)
  262.             SetAt(nStartIndex + i, pNewArray->GetAt(i));
  263.     }
  264. }
  265.  
  266.  
  267.  
  268.  
  269. /////////////////////////////////////////////////////////////////////////////
  270. // Serialization
  271.  
  272. void CDWordArray::Serialize(CArchive& ar)
  273. {
  274.     ASSERT_VALID(this);
  275.  
  276.     CObject::Serialize(ar);
  277.  
  278.     if (ar.IsStoring())
  279.     {
  280.         ar.WriteCount(m_nSize);
  281. #ifdef _AFX_BYTESWAP
  282.         if (!ar.IsByteSwapping())
  283. #endif
  284.         ar.Write(m_pData, m_nSize * sizeof(DWORD));
  285. #ifdef _AFX_BYTESWAP
  286.         else
  287.         {
  288.             // write each item individually so that it will be byte-swapped
  289.             for (int i = 0; i < m_nSize; i++)
  290.                 ar << m_pData[i];
  291.         }
  292. #endif
  293.     }
  294.     else
  295.     {
  296.         DWORD nOldSize = ar.ReadCount();
  297.         SetSize(nOldSize);
  298.         ar.Read(m_pData, m_nSize * sizeof(DWORD));
  299. #ifdef _AFX_BYTESWAP
  300.         if (ar.IsByteSwapping())
  301.         {
  302.             for (int i = 0; i < m_nSize; i++)
  303.                 _AfxByteSwap(m_pData[i], (BYTE*)&m_pData[i]);
  304.         }
  305. #endif
  306.     }
  307. }
  308.  
  309. /////////////////////////////////////////////////////////////////////////////
  310. // Diagnostics
  311.  
  312. #ifdef _DEBUG
  313. void CDWordArray::Dump(CDumpContext& dc) const
  314. {
  315.     CObject::Dump(dc);
  316.  
  317.     dc << "with " << m_nSize << " elements";
  318.     if (dc.GetDepth() > 0)
  319.     {
  320.         for (int i = 0; i < m_nSize; i++)
  321.             dc << "\n\t[" << i << "] = " << m_pData[i];
  322.     }
  323.  
  324.     dc << "\n";
  325. }
  326.  
  327. void CDWordArray::AssertValid() const
  328. {
  329.     CObject::AssertValid();
  330.  
  331.     if (m_pData == NULL)
  332.     {
  333.         ASSERT(m_nSize == 0);
  334.         ASSERT(m_nMaxSize == 0);
  335.     }
  336.     else
  337.     {
  338.         ASSERT(m_nSize >= 0);
  339.         ASSERT(m_nMaxSize >= 0);
  340.         ASSERT(m_nSize <= m_nMaxSize);
  341.         ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(DWORD)));
  342.     }
  343. }
  344. #endif //_DEBUG
  345.  
  346. #ifdef AFX_INIT_SEG
  347. #pragma code_seg(AFX_INIT_SEG)
  348. #endif
  349.  
  350.  
  351. IMPLEMENT_SERIAL(CDWordArray, CObject, 0)
  352.  
  353. /////////////////////////////////////////////////////////////////////////////
  354.