//*************************************************************************** // // Copyright (c) Microsoft Corporation. All rights reserved. // // FLEXARRY.CPP // // CFlexArray implementation (non-arena). // // 15-Jul-97 raymcc Created. // 8-Jun-98 bobw cleaned up for WBEMPERF usage // //*************************************************************************** #include "wpheader.h" #include //*************************************************************************** // // CFlexArray::CFlexArray // // Constructs the array. // // Parameters: // The starting preallocated size of the array. // The amount to grow by when the array fills up. // // Size() returns the number of elements in use, not the 'true' size. // //*************************************************************************** // ok CFlexArray::CFlexArray( int nSize, int nGrowBy ) { m_nExtent = nSize; m_nSize = 0; m_nGrowBy = nGrowBy; m_hHeap = GetProcessHeap(); // call this once and save heap handle locally m_pArray = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, sizeof(void *) * nSize); if( NULL == m_pArray ){ assert(FALSE); m_nExtent = 0; } } //*************************************************************************** // // CFlexArray::~CFlexArray // //*************************************************************************** // ok CFlexArray::~CFlexArray() { FREEMEM(m_hHeap, 0, m_pArray); } //*************************************************************************** // // Copy constructor. // // Copies the pointers, not their contents. // //*************************************************************************** // ok CFlexArray::CFlexArray(CFlexArray &Src) { m_pArray = 0; m_nSize = 0; m_nExtent = 0; m_nGrowBy = 0; *this = Src; } //*************************************************************************** // // operator = // // Assignment operator. // // Arenas are not copied. This allows transfer of arrays between arenas. // Arrays are copied by pointer only. // //*************************************************************************** // ok CFlexArray& CFlexArray::operator=(CFlexArray &Src) { m_nSize = Src.m_nSize; m_nExtent = Src.m_nExtent; m_nGrowBy = Src.m_nGrowBy; FREEMEM (m_hHeap, 0, m_pArray); m_pArray = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, sizeof(void *) * m_nExtent); if (m_pArray) { memcpy(m_pArray, Src.m_pArray, sizeof(void *) * m_nExtent); } return *this; } //*************************************************************************** // // CFlexArray::RemoveAt // // Removes the element at the specified location. Does not // actually delete the pointer. Shrinks the array over the top of // the 'doomed' element. // // Parameters: // The location of the element. // // Return value: // range_error The index is not legal. // no_error Success. // //*************************************************************************** // ok int CFlexArray::RemoveAt(int nIndex) { int i; if (nIndex >= m_nSize) { return range_error; } for (i = nIndex; i < m_nSize - 1; i++) { m_pArray[i] = m_pArray[i + 1]; } m_nSize--; m_pArray[m_nSize] = 0; return no_error; } int CFlexArray::Remove( void* p ) { for (int i = 0; i < m_nSize; i++) { if( m_pArray[i] == p ){ return RemoveAt( i ); } } return failed; } //*************************************************************************** // // CFlexArray::InsertAt // // Inserts a new element at the specified location. The pointer is copied. // // Parameters: // The 0-origin location at which to insert the new element. // The pointer to copy. (contents are not copied). // // Return value: // array_full // out_of_memory // no_error // //*************************************************************************** // ok int CFlexArray::InsertAt(int nIndex, void *pSrc) { void **pTmp; // pointer to new array int nReturn = no_error; LONG lOldSize; LONG lNewSize; // If the array is full, we need to expand it. // =========================================== if (m_nSize == m_nExtent) { if (m_nGrowBy == 0) { nReturn = array_full; } else { // compute sizes lOldSize = sizeof(void *) * m_nExtent; m_nExtent += m_nGrowBy; lNewSize = sizeof(void *) * m_nExtent; // allocate new array pTmp = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, lNewSize); if (!pTmp) { nReturn = out_of_memory; } else { // move bits from old array to new array memcpy (pTmp, m_pArray, lOldSize); // toss old arrya FREEMEM (m_hHeap, 0, m_pArray); // save pointer to new array m_pArray = pTmp; } } } if( nIndex > m_nSize ){ nReturn = range_error; } // Special case of appending. This is so frequent // compared to true insertion that we want to optimize. // ==================================================== if (nReturn == no_error) { if (nIndex == m_nSize) { m_pArray[m_nSize++] = pSrc; } else { // If here, we are inserting at some random location. // We start at the end of the array and copy all the elements // one position farther to the end to make a 'hole' for // the new element. // ========================================================== for (int i = m_nSize; i > nIndex; i--) { m_pArray[i] = m_pArray[i - 1]; } m_pArray[nIndex] = pSrc; m_nSize++; } } return nReturn; } //*************************************************************************** // // CFlexArray::Compress // // Removes NULL elements by moving all non-NULL pointers to the beginning // of the array. The array "Size" changes, but the extent is untouched. // //*************************************************************************** // ok void CFlexArray::Compress() { int nLeftCursor = 0, nRightCursor = 0; while (nLeftCursor < m_nSize - 1) { if (m_pArray[nLeftCursor]) { nLeftCursor++; continue; } else { nRightCursor = nLeftCursor + 1; while (m_pArray[nRightCursor] == 0 && nRightCursor < m_nSize) nRightCursor++; if (nRightCursor == m_nSize) break; // Short circuit, no more nonzero elements. m_pArray[nLeftCursor] = m_pArray[nRightCursor]; m_pArray[nRightCursor] = 0; } } while (m_pArray[m_nSize - 1] == 0 && m_nSize > 0) m_nSize--; } //*************************************************************************** // // CFlexArray::Empty // // Clears the array of all pointers (does not deallocate them) and sets // its apparent size to zero. // //*************************************************************************** // ok void CFlexArray::Empty() { FREEMEM(m_hHeap, 0, m_pArray); m_pArray = (void **) ALLOCMEM(m_hHeap, HEAP_ZERO_MEMORY, sizeof(void *) * m_nGrowBy); m_nSize = 0; m_nExtent = m_nGrowBy; }