/*========================================================================== * * Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved. * * File: AutoArray.h * Content: CAutoArray / CAutoPtrArray Declarations * * History: * Date By Reason * ====== == ====== * 12-12-2001 simonpow Created ***************************************************************************/ #ifndef __AUTOARRAY_H__ #define __AUTOARRAY_H__ #include "dndbg.h" /* * CAutoArray class * Provides automatic memory management for an array. As elements * are added to it or moved within it the array will automatically * grow to hold them. * The growth policy is dictated by a size multiple value, with the * array size always being an exact multiple of a pre-defined value. * e.g. If the size multiple is set to 32 then possible array sizes * are 32, 64, 96, 128, etc. * In this scenario setting element 100 on array that is currently * only 32 elements big will cause the array to grow to 128 elemments. * i.e. The next largest multiple to hold the required value * * For arrays of pointers use the specialisation CAutoPtrArray * declared below CAutoArray */ template class CAutoArray { public: //provide the type of entries stored in array typedef T Entry; /* * Construction and destruction */ //array is by default zero size, and grows in multiples //of 16 elements at a time CAutoArray(DWORD dwSizeMultiple=16) { DNASSERT(dwSizeMultiple); m_dwSize=0; m_dwSizeMultiple=dwSizeMultiple; m_pData=(T * ) 0; }; //delete array and data ~CAutoArray() { if (m_pData) delete[] m_pData; }; /* * Memory management */ //resets the array (deleting any allocated data) //ands set a new size multiple value. //Pass 0 for dwSizeMultiple to leave existing value unchanged void Reset(DWORD dwSizeMultiple=16) { if (dwSizeMultiple) m_dwSizeMultiple=dwSizeMultiple; m_dwSize=0; if (m_pData) { delete[] m_pData; m_pData=(T * ) NULL; } }; //ensure the array has space for at least 'numElements'. //This is useful if you know your about to grow the array, as it //allows you to minimise the number of memory allocations //Returns FALSE is a memory allocation fails BOOL AllocAtLeast(DWORD dwNumElements) { if (dwNumElements>m_dwSize) return GrowToAtLeast(dwNumElements-1); return TRUE; } //returns number of bytes currently allocated to array //This will always be a multiple of 'dwSizeMultiple' passed to //constructor or Reset method DWORD GetCurrentSize() { return m_dwSize; }; /* * Moving elements */ //move the block of 'dwNum' elements starting at 'dwIndex' to the //'dwNewIndex'. The new location can be either beyond or before //the current index. The array will be grown automatically if needed //If 'bCopySemantics' is FALSE then the data in the source block location (dwIndex to //dwIndex+dwNumElements) will be left undefined. Otherwise it'll be preserved in //its original form (except where/if its overwritten by the destination block). //Returns FALSE is a memory allocation fails BOOL MoveElements(DWORD dwIndex, DWORD dwNumElements, DWORD dwNewIndex, BOOL bCopySemantics); /* * Setting elements */ //set a block of 'dwNumElem' elements starting at 'dwIndex' to the //values provided in 'pElemData'. If any of the locations set are //beyond the current array size the array will be automatically //grown. Returns FALSE is a memory allocation fails BOOL SetElements(DWORD dwIndex, const T * pElemData, DWORD dwNumElem); //set the single element at 'dwIndex' to value 'data' //array will automatically grow if necessary //Returns FALSE is a memory allocation fails BOOL SetElement(DWORD dwIndex, const T& elem) { if (dwIndex>=m_dwSize && GrowToAtLeast(dwIndex)==FALSE) return FALSE; m_pData[dwIndex]=elem; return TRUE; }; //set the value of an existing element. This doesn't try to //grow array so its up to the caller to ensure dwIndex is in range void SetExistingElement(DWORD dwIndex, const T& elem) { DNASSERT(dwIndex=m_dwSize already! BOOL GrowToAtLeast(DWORD dwIndex); //return the size of array needed to hold index, based on current size multiple DWORD GetArraySize(DWORD dwIndex) { return ((dwIndex/m_dwSizeMultiple)+1)*m_dwSizeMultiple; }; //array of data T * m_pData; //size of the array of data DWORD m_dwSize; //multiple for size DWORD m_dwSizeMultiple; }; /* * Specialisation of CAutoArray designed for handling pointers. * Whatever the type of pointer stored, this class will always * use a CAutoArray underneath, hence ensuring the same * code is reused between all CAutoPtrArray types */ template class CAutoPtrArray : public CAutoArray { public: typedef T Entry; typedef CAutoArray Base; CAutoPtrArray(DWORD dwSizeMultiple=16) : CAutoArray(dwSizeMultiple) {}; BOOL SetElements(DWORD dwIndex, const T * pElemData, DWORD dwNumElem) { return Base::SetElements(dwIndex, (void **) pElemData, dwNumElem); }; BOOL SetElement(DWORD dwIndex, T elem) { return Base::SetElement(dwIndex, elem); }; void SetExistingElement(DWORD dwIndex, T elem) { DNASSERT(dwIndex