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