home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / ARRAY_W.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  7.6 KB  |  342 lines

  1.  
  2. // This is a part of the Microsoft Foundation Classes C++ library.
  3. // Copyright (C) 1992-1997 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. CWordArray::CWordArray()
  38. {
  39.     m_pData = NULL;
  40.     m_nSize = m_nMaxSize = m_nGrowBy = 0;
  41. }
  42.  
  43. CWordArray::~CWordArray()
  44. {
  45.     ASSERT_VALID(this);
  46.  
  47.     delete[] (BYTE*)m_pData;
  48. }
  49.  
  50. void CWordArray::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(WORD));    // no overflow
  70. #endif
  71.         m_pData = (WORD*) new BYTE[nNewSize * sizeof(WORD)];
  72.  
  73.         memset(m_pData, 0, nNewSize * sizeof(WORD));  // 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(WORD));
  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(WORD)); // no overflow
  109. #endif
  110.         WORD* pNewData = (WORD*) new BYTE[nNewMax * sizeof(WORD)];
  111.  
  112.         // copy new data from old
  113.         memcpy(pNewData, m_pData, m_nSize * sizeof(WORD));
  114.  
  115.         // construct remaining elements
  116.         ASSERT(nNewSize > m_nSize);
  117.  
  118.         memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(WORD));
  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 CWordArray::Append(const CWordArray& 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(WORD));
  138.  
  139.     return nOldSize;
  140. }
  141.  
  142. void CWordArray::Copy(const CWordArray& 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(WORD));
  150.  
  151. }
  152.  
  153. void CWordArray::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(WORD)); // no overflow
  162. #endif
  163.         WORD* pNewData = NULL;
  164.         if (m_nSize != 0)
  165.         {
  166.             pNewData = (WORD*) new BYTE[m_nSize * sizeof(WORD)];
  167.             // copy new data from old
  168.             memcpy(pNewData, m_pData, m_nSize * sizeof(WORD));
  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 CWordArray::SetAtGrow(int nIndex, WORD 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. void CWordArray::InsertAt(int nIndex, WORD newElement, int nCount)
  191. {
  192.     ASSERT_VALID(this);
  193.     ASSERT(nIndex >= 0);    // will expand to meet need
  194.     ASSERT(nCount > 0);     // zero or negative size not allowed
  195.  
  196.     if (nIndex >= m_nSize)
  197.     {
  198.         // adding after the end of the array
  199.         SetSize(nIndex + nCount);  // grow so nIndex is valid
  200.     }
  201.     else
  202.     {
  203.         // inserting in the middle of the array
  204.         int nOldSize = m_nSize;
  205.         SetSize(m_nSize + nCount);  // grow it to new size
  206.         // shift old data up to fill gap
  207.         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  208.             (nOldSize-nIndex) * sizeof(WORD));
  209.  
  210.         // re-init slots we copied from
  211.  
  212.         memset(&m_pData[nIndex], 0, nCount * sizeof(WORD));
  213.  
  214.     }
  215.  
  216.     // insert new value in the gap
  217.     ASSERT(nIndex + nCount <= m_nSize);
  218.     while (nCount--)
  219.         m_pData[nIndex++] = newElement;
  220. }
  221.  
  222. void CWordArray::RemoveAt(int nIndex, int nCount)
  223. {
  224.     ASSERT_VALID(this);
  225.     ASSERT(nIndex >= 0);
  226.     ASSERT(nCount >= 0);
  227.     ASSERT(nIndex + nCount <= m_nSize);
  228.  
  229.     // just remove a range
  230.     int nMoveCount = m_nSize - (nIndex + nCount);
  231.  
  232.     if (nMoveCount)
  233.         memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  234.             nMoveCount * sizeof(WORD));
  235.     m_nSize -= nCount;
  236. }
  237.  
  238. void CWordArray::InsertAt(int nStartIndex, CWordArray* pNewArray)
  239. {
  240.     ASSERT_VALID(this);
  241.     ASSERT(pNewArray != NULL);
  242.     ASSERT_KINDOF(CWordArray, pNewArray);
  243.     ASSERT_VALID(pNewArray);
  244.     ASSERT(nStartIndex >= 0);
  245.  
  246.     if (pNewArray->GetSize() > 0)
  247.     {
  248.         InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  249.         for (int i = 0; i < pNewArray->GetSize(); i++)
  250.             SetAt(nStartIndex + i, pNewArray->GetAt(i));
  251.     }
  252. }
  253.  
  254.  
  255.  
  256.  
  257. /////////////////////////////////////////////////////////////////////////////
  258. // Serialization
  259.  
  260. void CWordArray::Serialize(CArchive& ar)
  261. {
  262.     ASSERT_VALID(this);
  263.  
  264.     CObject::Serialize(ar);
  265.  
  266.     if (ar.IsStoring())
  267.     {
  268.         ar.WriteCount(m_nSize);
  269. #ifdef _MAC
  270.         if (!ar.IsByteSwapping())
  271. #endif
  272.         ar.Write(m_pData, m_nSize * sizeof(WORD));
  273. #ifdef _MAC
  274.         else
  275.         {
  276.             // write each item individually so that it will be byte-swapped
  277.             for (int i = 0; i < m_nSize; i++)
  278.                 ar << m_pData[i];
  279.         }
  280. #endif
  281.     }
  282.     else
  283.     {
  284.         DWORD nOldSize = ar.ReadCount();
  285.         SetSize(nOldSize);
  286.         ar.Read(m_pData, m_nSize * sizeof(WORD));
  287. #ifdef _MAC
  288.         if (ar.IsByteSwapping())
  289.         {
  290.             for (int i = 0; i < m_nSize; i++)
  291.                 _AfxByteSwap(m_pData[i], (BYTE*)&m_pData[i]);
  292.         }
  293. #endif
  294.     }
  295. }
  296.  
  297. /////////////////////////////////////////////////////////////////////////////
  298. // Diagnostics
  299.  
  300. #ifdef _DEBUG
  301. void CWordArray::Dump(CDumpContext& dc) const
  302. {
  303.     CObject::Dump(dc);
  304.  
  305.     dc << "with " << m_nSize << " elements";
  306.     if (dc.GetDepth() > 0)
  307.     {
  308.         for (int i = 0; i < m_nSize; i++)
  309.             dc << "\n\t[" << i << "] = " << m_pData[i];
  310.     }
  311.  
  312.     dc << "\n";
  313. }
  314.  
  315. void CWordArray::AssertValid() const
  316. {
  317.     CObject::AssertValid();
  318.  
  319.     if (m_pData == NULL)
  320.     {
  321.         ASSERT(m_nSize == 0);
  322.         ASSERT(m_nMaxSize == 0);
  323.     }
  324.     else
  325.     {
  326.         ASSERT(m_nSize >= 0);
  327.         ASSERT(m_nMaxSize >= 0);
  328.         ASSERT(m_nSize <= m_nMaxSize);
  329.         ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(WORD)));
  330.     }
  331. }
  332. #endif //_DEBUG
  333.  
  334. #ifdef AFX_INIT_SEG
  335. #pragma code_seg(AFX_INIT_SEG)
  336. #endif
  337.  
  338.  
  339. IMPLEMENT_SERIAL(CWordArray, CObject, 0)
  340.  
  341. /////////////////////////////////////////////////////////////////////////////
  342.