home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK10 / MFC / SRC / ARRAY_S.CP$ / array_s
Encoding:
Text File  |  1992-03-03  |  6.9 KB  |  323 lines

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