home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / MFC / SRC / ARRAY_S.CP_ / ARRAY_S.CP
Encoding:
Text File  |  1993-02-08  |  7.1 KB  |  322 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(CStringArray, 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. #include "elements.h"  // used for special creation
  34.  
  35. static void NEAR ConstructElements(CString* pNewData, int nCount)
  36. {
  37.     ASSERT(nCount >= 0);
  38.  
  39.     while (nCount--)
  40.     {
  41.         ConstructElement(pNewData);
  42.         pNewData++;
  43.     }
  44. }
  45.  
  46. static void NEAR DestructElements(CString* pOldData, int nCount)
  47. {
  48.     ASSERT(nCount >= 0);
  49.  
  50.     while (nCount--)
  51.     {
  52.         pOldData->Empty();
  53.         pOldData++;
  54.     }
  55. }
  56.  
  57. /////////////////////////////////////////////////////////////////////////////
  58.  
  59. CStringArray::CStringArray()
  60. {
  61.     m_pData = NULL;
  62.     m_nSize = m_nMaxSize = m_nGrowBy = 0;
  63. }
  64.  
  65. CStringArray::~CStringArray()
  66. {
  67.     ASSERT_VALID(this);
  68.  
  69.  
  70.     DestructElements(m_pData, m_nSize);
  71.     delete [] (BYTE*)m_pData;
  72. }
  73.  
  74. void CStringArray::SetSize(int nNewSize, int nGrowBy /* = -1 */)
  75. {
  76.     ASSERT_VALID(this);
  77.     ASSERT(nNewSize >= 0);
  78.  
  79.     if (nGrowBy != -1)
  80.         m_nGrowBy = nGrowBy;  // set new size
  81.  
  82.     if (nNewSize == 0)
  83.     {
  84.         // shrink to nothing
  85.  
  86.         DestructElements(m_pData, m_nSize);
  87.         delete [] (BYTE*)m_pData;
  88.         m_pData = NULL;
  89.         m_nSize = m_nMaxSize = 0;
  90.     }
  91.     else if (m_pData == NULL)
  92.     {
  93.         // create one with exact size
  94. #ifdef SIZE_T_MAX
  95.         ASSERT((long)nNewSize * sizeof(CString) <= SIZE_T_MAX);  // no overflow
  96. #endif
  97.         m_pData = (CString*) new BYTE[nNewSize * sizeof(CString)];
  98.  
  99.         ConstructElements(m_pData, nNewSize);
  100.  
  101.         m_nSize = m_nMaxSize = nNewSize;
  102.     }
  103.     else if (nNewSize <= m_nMaxSize)
  104.     {
  105.         // it fits
  106.         if (nNewSize > m_nSize)
  107.         {
  108.             // initialize the new elements
  109.  
  110.             ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize);
  111.  
  112.         }
  113.  
  114.         else if (m_nSize > nNewSize)  // destroy the old elements
  115.             DestructElements(&m_pData[nNewSize], m_nSize-nNewSize);
  116.  
  117.         m_nSize = nNewSize;
  118.     }
  119.     else
  120.     {
  121.         // Otherwise grow array
  122.         int nNewMax;
  123.         if (nNewSize < m_nMaxSize + m_nGrowBy)
  124.             nNewMax = m_nMaxSize + m_nGrowBy;  // granularity
  125.         else
  126.             nNewMax = nNewSize;  // no slush
  127.  
  128. #ifdef SIZE_T_MAX
  129.         ASSERT((long)nNewMax * sizeof(CString) <= SIZE_T_MAX);  // no overflow
  130. #endif
  131.         CString* pNewData = (CString*) new BYTE[nNewMax * sizeof(CString)];
  132.  
  133.         // copy new data from old
  134.         memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  135.  
  136.         // construct remaining elements
  137.         ASSERT(nNewSize > m_nSize);
  138.  
  139.         ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize);
  140.  
  141.  
  142.         // get rid of old stuff (note: no destructors called)
  143.         delete [] (BYTE*)m_pData;
  144.         m_pData = pNewData;
  145.         m_nSize = nNewSize;
  146.         m_nMaxSize = nNewMax;
  147.     }
  148. }
  149.  
  150. void CStringArray::FreeExtra()
  151. {
  152.     ASSERT_VALID(this);
  153.  
  154.     if (m_nSize != m_nMaxSize)
  155.     {
  156.         // shrink to desired size
  157. #ifdef SIZE_T_MAX
  158.         ASSERT((long)m_nSize * sizeof(CString) <= SIZE_T_MAX);  // no overflow
  159. #endif
  160.         CString* pNewData = NULL;
  161.         if (m_nSize != 0)
  162.         {
  163.             pNewData = (CString*) new BYTE[m_nSize * sizeof(CString)];
  164.             // copy new data from old
  165.             memcpy(pNewData, m_pData, m_nSize * sizeof(CString));
  166.         }
  167.  
  168.         // get rid of old stuff (note: no destructors called)
  169.         delete [] (BYTE*)m_pData;
  170.         m_pData = pNewData;
  171.         m_nMaxSize = m_nSize;
  172.     }
  173. }
  174.  
  175. /////////////////////////////////////////////////////////////////////////////
  176.  
  177. void CStringArray::SetAtGrow(int nIndex, const char* newElement)
  178. {
  179.     ASSERT_VALID(this);
  180.     ASSERT(nIndex >= 0);
  181.  
  182.     if (nIndex >= m_nSize)
  183.         SetSize(nIndex+1);
  184.     m_pData[nIndex] = newElement;
  185. }
  186.  
  187. void CStringArray::InsertAt(int nIndex, const char* newElement, int nCount /*=1*/)
  188. {
  189.     ASSERT_VALID(this);
  190.     ASSERT(nIndex >= 0);    // will expand to meet need
  191.     ASSERT(nCount > 0);     // zero or negative size not allowed
  192.  
  193.     if (nIndex >= m_nSize)
  194.     {
  195.         // adding after the end of the array
  196.         SetSize(nIndex + nCount);  // grow so nIndex is valid
  197.     }
  198.     else
  199.     {
  200.         // inserting in the middle of the array
  201.         int nOldSize = m_nSize;
  202.         SetSize(m_nSize + nCount);  // grow it to new size
  203.         // shift old data up to fill gap
  204.         memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
  205.             (nOldSize-nIndex) * sizeof(CString));
  206.  
  207.         // re-init slots we copied from
  208.  
  209.         ConstructElements(&m_pData[nIndex], nCount);
  210.  
  211.     }
  212.  
  213.     // insert new value in the gap
  214.     ASSERT(nIndex + nCount <= m_nSize);
  215.     while (nCount--)
  216.         m_pData[nIndex++] = newElement;
  217. }
  218.  
  219. void CStringArray::RemoveAt(int nIndex, int nCount /* = 1 */)
  220. {
  221.     ASSERT_VALID(this);
  222.     ASSERT(nIndex >= 0);
  223.     ASSERT(nCount >= 0);
  224.     ASSERT(nIndex + nCount <= m_nSize);
  225.  
  226.     // just remove a range
  227.     int nMoveCount = m_nSize - (nIndex + nCount);
  228.  
  229.     DestructElements(&m_pData[nIndex], nCount);
  230.  
  231.     if (nMoveCount)
  232.         memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
  233.             nMoveCount * sizeof(CString));
  234.     m_nSize -= nCount;
  235. }
  236.  
  237. void CStringArray::InsertAt(int nStartIndex, CStringArray* pNewArray)
  238. {
  239.     ASSERT_VALID(this);
  240.     ASSERT(pNewArray != NULL);
  241.     ASSERT(pNewArray->IsKindOf(RUNTIME_CLASS(CStringArray)));
  242.     ASSERT_VALID(pNewArray);
  243.     ASSERT(nStartIndex >= 0);
  244.  
  245.     if (pNewArray->GetSize() > 0)
  246.     {
  247.         InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
  248.         for (int i = 0; i < pNewArray->GetSize(); i++)
  249.             SetAt(nStartIndex + i, pNewArray->GetAt(i));
  250.     }
  251. }
  252.  
  253. /////////////////////////////////////////////////////////////////////////////
  254. // Serialization
  255.  
  256.  
  257. void CStringArray::Serialize(CArchive& ar)
  258. {
  259.     ASSERT_VALID(this);
  260.  
  261.     CObject::Serialize(ar);
  262.  
  263.     if (ar.IsStoring())
  264.     {
  265.         ar << (WORD) m_nSize;
  266.         for (int i = 0; i < m_nSize; i++)
  267.             ar << m_pData[i];
  268.     }
  269.     else
  270.     {
  271.         WORD nOldSize;
  272.         ar >> nOldSize;
  273.         SetSize(nOldSize);
  274.  
  275.         for (int i = 0; i < m_nSize; i++)
  276.             ar >> m_pData[i];
  277.     }
  278. }
  279.  
  280. /////////////////////////////////////////////////////////////////////////////
  281. // Diagnostics
  282.  
  283. #ifdef _DEBUG
  284. void CStringArray::Dump(CDumpContext& dc) const
  285. {
  286.     ASSERT_VALID(this);
  287.  
  288. #define MAKESTRING(x) #x
  289.     AFX_DUMP1(dc, "a " MAKESTRING(CStringArray) " with ", m_nSize);
  290.     AFX_DUMP0(dc, " elements");
  291. #undef MAKESTRING
  292.     if (dc.GetDepth() > 0)
  293.     {
  294.         AFX_DUMP0(dc, "\n");
  295.         for (int i = 0; i < m_nSize; i++)
  296.         {
  297.             AFX_DUMP1(dc, "\n\t[", i);
  298.             AFX_DUMP1(dc, "] = ", m_pData[i]);
  299.         }
  300.     }
  301. }
  302.  
  303. void CStringArray::AssertValid() const
  304. {
  305.     CObject::AssertValid();
  306.     if (m_pData == NULL)
  307.     {
  308.         ASSERT(m_nSize == 0);
  309.         ASSERT(m_nMaxSize == 0);
  310.     }
  311.     else
  312.     {
  313.         ASSERT(m_nSize >= 0);
  314.         ASSERT(m_nMaxSize >= 0);
  315.         ASSERT(m_nSize <= m_nMaxSize);
  316.         ASSERT(AfxIsValidAddress(m_pData, m_nMaxSize * sizeof(CString)));
  317.     }
  318. }
  319. #endif //_DEBUG
  320.  
  321. /////////////////////////////////////////////////////////////////////////////
  322.