home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / MFC / SRC / ARRAY_D.CP_ / ARRAY_D.CP
Encoding:
Text File  |  1993-02-08  |  6.4 KB  |  289 lines

  1.  
  2. /////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Implementation of parameterized Array
  5. //
  6. /////////////////////////////////////////////////////////////////////////////
  7. // NOTE: we allocate an array of 'm_nMaxSize' elements, but only
  8. //  the current size 'm_nSize' contains properly constructed
  9. //  objects.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_COLL_SEG
  14. #pragma code_seg(AFX_COLL_SEG)
  15. #endif
  16.  
  17. #include <limits.h>
  18. #define SIZE_T_MAX  UINT_MAX            /* max size for a size_t */
  19.  
  20.  
  21. IMPLEMENT_SERIAL(CDWordArray, CObject, 0)
  22.  
  23. #ifdef _DEBUG
  24. #undef THIS_FILE
  25. static char BASED_CODE THIS_FILE[] = __FILE__;
  26. #endif
  27.  
  28. #define new DEBUG_NEW
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31.  
  32.  
  33. /////////////////////////////////////////////////////////////////////////////
  34.  
  35. CDWordArray::CDWordArray()
  36. {
  37.     m_pData = NULL;
  38.     m_nSize = m_nMaxSize = m_nGrowBy = 0;
  39. }
  40.  
  41. CDWordArray::~CDWordArray()
  42. {
  43.     ASSERT_VALID(this);
  44.  
  45.     delete [] (BYTE*)m_pData;
  46. }
  47.  
  48. void CDWordArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  49. {
  50.     ASSERT_VALID(this);
  51.     ASSERT(nNewSize >= 0);
  52.  
  53.     if (nGrowBy != -1)
  54.         m_nGrowBy = nGrowBy;  // set new size
  55.  
  56.     if (nNewSize == 0)
  57.     {
  58.         // shrink to nothing
  59.         delete [] (BYTE*)m_pData;
  60.         m_pData = NULL;
  61.         m_nSize = m_nMaxSize = 0;
  62.     }
  63.     else if (m_pData == NULL)
  64.     {
  65.         // create one with exact size
  66. #ifdef SIZE_T_MAX
  67.         ASSERT((long)nNewSize * sizeof(DWORD) <= SIZE_T_MAX);  // no overflow
  68. #endif
  69.         m_pData = (DWORD*) new BYTE[nNewSize * sizeof(DWORD)];
  70.  
  71.         memset(m_pData, 0, nNewSize * sizeof(DWORD));  // zero fill
  72.  
  73.         m_nSize = m_nMaxSize = nNewSize;
  74.     }
  75.     else if (nNewSize <= m_nMaxSize)
  76.     {
  77.         // it fits
  78.         if (nNewSize > m_nSize)
  79.         {
  80.             // initialize the new elements
  81.  
  82.             memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(DWORD));
  83.  
  84.         }
  85.  
  86.         m_nSize = nNewSize;
  87.     }
  88.     else
  89.     {
  90.         // Otherwise grow array
  91.         int nNewMax;
  92.         if (nNewSize < m_nMaxSize + m_nGrowBy)
  93.             nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  94.         else
  95.             nNewMax = nNewSize;  // no slush
  96.  
  97. #ifdef SIZE_T_MAX
  98.         ASSERT((long)nNewMax * sizeof(DWORD) <= SIZE_T_MAX);  // no overflow
  99. #endif
  100.         DWORD* pNewData = (DWORD*) new BYTE[nNewMax * sizeof(DWORD)];
  101.  
  102.         // copy new data from old
  103.         memcpy(pNewData, m_pData, m_nSize * sizeof(DWORD));
  104.  
  105.         // construct remaining elements
  106.         ASSERT(nNewSize > m_nSize);
  107.  
  108.         memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(DWORD));
  109.  
  110.  
  111.         // get rid of old stuff (note: no destructors called)
  112.         delete [] (BYTE*)m_pData;
  113.         m_pData = pNewData;
  114.         m_nSize = nNewSize;
  115.         m_nMaxSize = nNewMax;
  116.     }
  117. }
  118.  
  119. void CDWordArray::FreeExtra()
  120. {
  121.     ASSERT_VALID(this);
  122.  
  123.     if (m_nSize != m_nMaxSize)
  124.     {
  125.         // shrink to desired size
  126. #ifdef SIZE_T_MAX
  127.         ASSERT((long)m_nSize * sizeof(DWORD) <= SIZE_T_MAX);  // no overflow
  128. #endif
  129.         DWORD* pNewData = NULL;
  130.         if (m_nSize != 0)
  131.         {
  132.             pNewData = (DWORD*) new BYTE[m_nSize * sizeof(DWORD)];
  133.             // copy new data from old
  134.             memcpy(pNewData, m_pData, m_nSize * sizeof(DWORD));
  135.         }
  136.  
  137.         // get rid of old stuff (note: no destructors called)
  138.         delete [] (BYTE*)m_pData;
  139.         m_pData = pNewData;
  140.         m_nMaxSize = m_nSize;
  141.     }
  142. }
  143.  
  144. /////////////////////////////////////////////////////////////////////////////
  145.  
  146. void CDWordArray::SetAtGrow(int nIndex, DWORD newElement)
  147. {
  148.     ASSERT_VALID(this);
  149.     ASSERT(nIndex >= 0);
  150.  
  151.     if (nIndex >= m_nSize)
  152.         SetSize(nIndex+1);
  153.     m_pData[nIndex] = newElement;
  154. }
  155.  
  156. void CDWordArray::InsertAt(int nIndex, DWORD newElement, int nCount /*=1*/)
  157. {
  158.     ASSERT_VALID(this);
  159.     ASSERT(nIndex >= 0);    // will expand to meet need
  160.     ASSERT(nCount > 0);     // zero or negative size not allowed
  161.  
  162.     if (nIndex >= m_nSize)
  163.     {
  164.         // adding after the end of the array
  165.         SetSize(nIndex + nCount);  // grow so nIndex is valid
  166.     }
  167.     else
  168.     {
  169.         // inserting in the middle of the array
  170.         int nOldSize = m_nSize;
  171.         SetSize(m_nSize + nCount);  // grow it to new size
  172.         // shift old data up to fill gap
  173.         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  174.             (nOldSize-nIndex) * sizeof(DWORD));
  175.  
  176.         // re-init slots we copied from
  177.  
  178.         memset(&m_pData[nIndex], 0, nCount * sizeof(DWORD));
  179.  
  180.     }
  181.  
  182.     // insert new value in the gap
  183.     ASSERT(nIndex + nCount <= m_nSize);
  184.     while (nCount--)
  185.         m_pData[nIndex++] = newElement;
  186. }
  187.  
  188. void CDWordArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  189. {
  190.     ASSERT_VALID(this);
  191.     ASSERT(nIndex >= 0);
  192.     ASSERT(nCount >= 0);
  193.     ASSERT(nIndex + nCount <= m_nSize);
  194.  
  195.     // just remove a range
  196.     int nMoveCount = m_nSize - (nIndex + nCount);
  197.  
  198.     if (nMoveCount)
  199.         memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  200.             nMoveCount * sizeof(DWORD));
  201.     m_nSize -= nCount;
  202. }
  203.  
  204. void CDWordArray::InsertAt(int nStartIndex, CDWordArray* pNewArray)
  205. {
  206.     ASSERT_VALID(this);
  207.     ASSERT(pNewArray != NULL);
  208.     ASSERT(pNewArray->IsKindOf(RUNTIME_CLASS(CDWordArray)));
  209.     ASSERT_VALID(pNewArray);
  210.     ASSERT(nStartIndex >= 0);
  211.  
  212.     if (pNewArray->GetSize() > 0)
  213.     {
  214.         InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  215.         for (int i = 0; i < pNewArray->GetSize(); i++)
  216.             SetAt(nStartIndex + i, pNewArray->GetAt(i));
  217.     }
  218. }
  219.  
  220. /////////////////////////////////////////////////////////////////////////////
  221. // Serialization
  222.  
  223.  
  224. void CDWordArray::Serialize(CArchive& ar)
  225. {
  226.     ASSERT_VALID(this);
  227.  
  228.     CObject::Serialize(ar);
  229.  
  230.     if (ar.IsStoring())
  231.     {
  232.         ar << (WORD) m_nSize;
  233.         for (int i = 0; i < m_nSize; i++)
  234.             ar << m_pData[i];
  235.     }
  236.     else
  237.     {
  238.         WORD nOldSize;
  239.         ar >> nOldSize;
  240.         SetSize(nOldSize);
  241.  
  242.         for (int i = 0; i < m_nSize; i++)
  243.             ar >> m_pData[i];
  244.     }
  245. }
  246.  
  247. /////////////////////////////////////////////////////////////////////////////
  248. // Diagnostics
  249.  
  250. #ifdef _DEBUG
  251. void CDWordArray::Dump(CDumpContext& dc) const
  252. {
  253.     ASSERT_VALID(this);
  254.  
  255. #define MAKESTRING(x) #x
  256.     AFX_DUMP1(dc, "a " MAKESTRING(CDWordArray) " with ", m_nSize);
  257.     AFX_DUMP0(dc, " elements");
  258. #undef MAKESTRING
  259.     if (dc.GetDepth() > 0)
  260.     {
  261.         AFX_DUMP0(dc, "\n");
  262.         for (int i = 0; i < m_nSize; i++)
  263.         {
  264.             AFX_DUMP1(dc, "\n\t[", i);
  265.             AFX_DUMP1(dc, "] = ", m_pData[i]);
  266.         }
  267.     }
  268. }
  269.  
  270. void CDWordArray::AssertValid() const
  271. {
  272.     CObject::AssertValid();
  273.     if (m_pData == NULL)
  274.     {
  275.         ASSERT(m_nSize == 0);
  276.         ASSERT(m_nMaxSize == 0);
  277.     }
  278.     else
  279.     {
  280.         ASSERT(m_nSize >= 0);
  281.         ASSERT(m_nMaxSize >= 0);
  282.         ASSERT(m_nSize <= m_nMaxSize);
  283.         ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(DWORD)));
  284.     }
  285. }
  286. #endif //_DEBUG
  287.  
  288. /////////////////////////////////////////////////////////////////////////////
  289.