ptrarray.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 6k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //+-------------------------------------------------------------------------
  2. //
  3. //  Microsoft Windows
  4. //  Copyright (C) Microsoft Corporation, 1995
  5. //
  6. //  File:       ptrarray.cpp
  7. //
  8. //  Contents:   Handles dynamic arrays of void *.  Stolen from MFC
  9. //
  10. //  History:    7-13-95  Davepl  Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "precomp.h"
  14. //
  15. // Default contstructor just invokes normal constructor, using the
  16. // current process' heap as the heap handle
  17. //
  18. CPtrArray::CPtrArray()
  19. {
  20.     CPtrArray::CPtrArray(GetProcessHeap());
  21. }
  22. //
  23. // Constructor save a handle to the heap supplied to use for future 
  24. // allocations
  25. //
  26. CPtrArray::CPtrArray(HANDLE hHeap)
  27. {
  28.     m_hHeap     = hHeap;
  29.     m_pData     = NULL;
  30.     m_nSize     = 0;
  31.     m_nMaxSize  = 0;
  32.     m_nGrowBy   = 0;
  33. }
  34. CPtrArray::~CPtrArray()
  35. {
  36.     HeapFree(m_hHeap, 0, m_pData);
  37. }
  38. BOOL CPtrArray::SetSize(int nNewSize, int nGrowBy)
  39. {
  40.     ASSERT(nNewSize >= 0);
  41.     //
  42.     // Set the new size
  43.     //
  44.     if (nGrowBy != -1)
  45.     {
  46.         m_nGrowBy = nGrowBy;
  47.     }
  48.     if (nNewSize == 0)
  49.     {
  50.         //
  51.         // Shrink to nothing
  52.         //
  53.         VERIFY( HeapFree(m_hHeap, 0, m_pData) );
  54.         m_pData = NULL;
  55.         m_nSize = m_nMaxSize = 0;
  56.     }
  57.     else if (m_pData == NULL)
  58.     {
  59.         //
  60.         // Data array doesn't exist yet, allocate it now
  61.         //
  62.         LPVOID * pnew = (LPVOID *) HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, nNewSize * sizeof(void*));
  63.         if (pnew)
  64.         {
  65.             m_pData     = pnew;
  66.             m_nSize     = nNewSize;
  67.             m_nMaxSize  = nNewSize;
  68.         }
  69.         else
  70.         {
  71.             return FALSE;
  72.         }
  73.     }
  74.     else if (nNewSize <= m_nMaxSize)
  75.     {
  76.         //
  77.         // It fits
  78.         //
  79.         if (nNewSize > m_nSize)
  80.         {
  81.             // initialize the new elements
  82.             ZeroMemory(&m_pData[m_nSize], (nNewSize-m_nSize) * sizeof(void*));
  83.         }
  84.         m_nSize = nNewSize;
  85.     }
  86.     else
  87.     {
  88.         //
  89.         //  It doesn't fit: grow the array
  90.         //
  91.         m_nGrowBy = nGrowBy;        // BUGBUG verify this
  92.         if (nGrowBy == 0)
  93.         {
  94.             //
  95.             // Heuristically determine growth when nGrowBy == 0
  96.             //  (this avoids heap fragmentation in many situations)
  97.             //
  98.             nGrowBy = min(1024, max(4, m_nSize / 8));
  99.         }
  100.         int nNewMax;
  101.         if (nNewSize < m_nMaxSize + nGrowBy)
  102.         {
  103.             nNewMax = m_nMaxSize + nGrowBy;     // granularity
  104.         }
  105.         else
  106.         {
  107.             nNewMax = nNewSize;                 // no slush
  108.         }
  109.         ASSERT(nNewMax >= m_nMaxSize);          // no wrap around
  110.         LPVOID * pNewData = (LPVOID *) HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_pData, nNewMax * sizeof(void*));
  111.         if (NULL == pNewData)
  112.         {
  113.             return FALSE;
  114.         }
  115.         ASSERT(nNewSize > m_nSize);
  116.         m_pData = pNewData;
  117.         m_nSize = nNewSize;
  118.         m_nMaxSize = nNewMax;
  119.     }
  120.     return TRUE;
  121. }
  122. BOOL CPtrArray::FreeExtra()
  123. {
  124.     if (m_nSize != m_nMaxSize)
  125.     {
  126.         //
  127.         // shrink to desired size
  128.         //
  129.         void** pNewData = NULL;
  130.         if (m_nSize != 0)
  131.         {
  132.             pNewData = (void**) HeapAlloc(m_hHeap, 0, m_nSize * sizeof(void*));
  133.             ASSERT(pNewData);
  134.             if (NULL == pNewData)
  135.             {
  136.                 return FALSE;
  137.             }
  138.             //
  139.             // copy new data from old
  140.             //
  141.             CopyMemory(pNewData, m_pData, m_nSize * sizeof(void*));
  142.         }
  143.         //
  144.         // get rid of old stuff (note: no destructors called)
  145.         //
  146.         VERIFY( HeapFree(m_hHeap, 0, m_pData) );
  147.         m_pData = pNewData;
  148.         m_nMaxSize = m_nSize;
  149.     }
  150.     return TRUE;
  151. }
  152. BOOL CPtrArray::InsertAt(int nIndex, void* newElement, int nCount)
  153. {
  154.     ASSERT(nIndex >= 0);    // will expand to meet need
  155.     ASSERT(nCount > 0);     // zero or negative size not allowed
  156.     if (nIndex >= m_nSize)
  157.     {
  158.         //
  159.         // adding after the end of the array
  160.         //
  161.         if (FALSE == SetSize(nIndex + nCount))  // grow so nIndex is valid
  162.         {
  163.             return FALSE;
  164.         }
  165.     }
  166.     else
  167.     {
  168.         //
  169.         // inserting in the middle of the array
  170.         //
  171.         int nOldSize = m_nSize;
  172.         if (FALSE == SetSize(m_nSize + nCount))  // grow it to new size
  173.         {
  174.             return FALSE;
  175.         }
  176.         //
  177.         // shift old data up to fill gap
  178.         //
  179.         MoveMemory(&m_pData[nIndex+nCount], &m_pData[nIndex], (nOldSize-nIndex) * sizeof(void*));
  180.         // re-init slots we copied from
  181.         ZeroMemory(&m_pData[nIndex], nCount * sizeof(void*));
  182.     }
  183.     // insert new value in the gap
  184.     ASSERT(nIndex + nCount <= m_nSize);
  185.     while (nCount--)
  186.     {
  187.         m_pData[nIndex++] = newElement;
  188.     }
  189.     return TRUE;
  190. }
  191. BOOL CPtrArray::InsertAt(int nStartIndex, CPtrArray* pNewArray)
  192. {
  193.     ASSERT(pNewArray != NULL);
  194.     ASSERT(nStartIndex >= 0);
  195.     if (pNewArray->GetSize() > 0)
  196.     {
  197.         if (FALSE == InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize()))
  198.         {
  199.             return FALSE;
  200.         }
  201.         for (int i = 0; i < pNewArray->GetSize(); i++)
  202.         {
  203.             SetAt(nStartIndex + i, pNewArray->GetAt(i));
  204.         }
  205.     }
  206.     return TRUE;
  207. }