279 lines
7.6 KiB
C++
279 lines
7.6 KiB
C++
|
//***************************************************************************
|
|||
|
//
|
|||
|
// 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 <stdio.h>
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
//
|
|||
|
// CFlexArray::CFlexArray
|
|||
|
//
|
|||
|
// Constructs the array.
|
|||
|
//
|
|||
|
// Parameters:
|
|||
|
// <nSize> The starting preallocated size of the array.
|
|||
|
// <nGrowBy> 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:
|
|||
|
// <nIndex> 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:
|
|||
|
// <nIndex> The 0-origin location at which to insert the new element.
|
|||
|
// <pSrc> 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;
|
|||
|
}
|
|||
|
|