windows-nt/Source/XPSP1/NT/enduser/windows.com/wuv3/inc/varray.h
2020-09-26 16:20:57 +08:00

191 lines
5 KiB
C++

// Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
#ifndef _INC_ARRAY_TEMPLATE
//If the Version 3 catalog standard library has been included then use its
//memory allocation definations as these types include the correct error
//handling.
#define LOCALMALLOC(size) V3_calloc(1, size)
#define LOCALREALLOC(memblock, size) V3_realloc(memblock, size)
#define LOCALFREE(p) V3_free(p)
/*
* Variable Array Template
*
* This header defines a variable element array. This allows run time arrays
* of any size to be used with having to worry about managing the internal
* memory.
*
* For example:
*
* To use an array of longs declair Varray<long> x;
*
* You can then say x[50] = 5L; and the array will size itself to provide space for at least
* 50 longs.
*
* You can also specify an initial size in the constructor. So to create a variable array of
* class type Cfoo with an initial size of 50 you would declair Varray<Cfoo> x(50);
*
* To access the array simply use the array symbols in the first example you would write
* long ll = x[5]; to get the sixth element.
*
* Note: The array is 0 based.
*
* Also when memory for the template's internal storage is allocted it is not initialize in
* any manner. This means that a classes constructor is not called. It is the responsibility
* of the caller to have any classes that are placed into the array to already be initialized.
*
*/
template <class TYPE> class Varray
{
public:
Varray(int iInitialSize = 1);
~Varray<TYPE>();
inline TYPE &operator[]( int index );
inline TYPE &Insert(int insertAt, int iElements);
inline int SIZEOF(void);
inline int LastUsed(void);
//inline TYPE *operator &(); Note: To pass a pointer to the beginning
//of the array simply use &array[0].
private:
TYPE *m_pArray;
int m_iMaxArray;
int m_iMinAllocSize;
int m_iLastUsedArray;
};
/*
* Varray class constructor
*
* Constructs a dynamic size class array of the specified type.
*
* The array is initialized to have space for 1 element.
*
*/
template <class TYPE> Varray<TYPE>::Varray(int iInitialSize)
{
if ( iInitialSize <= 0 )
iInitialSize = 1;
m_pArray = (TYPE *)LOCALMALLOC(iInitialSize * sizeof(TYPE));
m_iMaxArray = 1;
m_iMinAllocSize = 1;
m_iLastUsedArray = -1;
}
/*
* Varray class destructor
*
* frees up the space used by a Varray
*
*/
template <class TYPE>Varray<TYPE>::~Varray()
{
if ( m_pArray )
LOCALFREE( m_pArray );
m_iMaxArray = 0;
m_iMinAllocSize = 1;
}
/*
* Varray operator [] handler
*
* Allows one to access the elements of a Varray. The array is resized
* as necessary to accomidate the number of elements needed.
*
*
* There are three cases that need to be handled by the allocation scheme.
* Sequential allocation this is where the caller is initializing an array
* in a sequential manner. We want to keep new requests to the memory
* allocator to a mimimum. Two is where the client asks for an array element
* far outside the currently allocated block size. Three when the client is
* using an element that is allready allocated.
*
* This class's solution is to keep a block size count and double it. This
* keeps going up to a fixed size limit. The allocation occurs every time
* a new array allocation is required.
*/
template <class TYPE> inline TYPE &Varray<TYPE>::operator[]( int index )
{
int iCurrentSize;
int nextAllocSize;
if ( index >= m_iMaxArray )
{
nextAllocSize = m_iMinAllocSize;
if ( nextAllocSize < 512 )
nextAllocSize = m_iMinAllocSize * 2;
iCurrentSize = m_iMaxArray;
if ( index - m_iMaxArray >= nextAllocSize )
m_iMaxArray = index + 1;
else
{
m_iMaxArray = m_iMaxArray + nextAllocSize;
m_iMinAllocSize = nextAllocSize;
}
m_pArray = (TYPE *)LOCALREALLOC(m_pArray, m_iMaxArray * sizeof(TYPE));
//clear out new cells
memset(m_pArray+iCurrentSize, 0, (m_iMaxArray-iCurrentSize) * sizeof(TYPE));
}
if ( index > m_iLastUsedArray )
m_iLastUsedArray = index;
return (*((TYPE*) &m_pArray[index]));
}
template <class TYPE> inline TYPE &Varray<TYPE>::Insert(int insertAt, int iElements)
{
int i;
int iCurrentSize;
iCurrentSize = m_iMaxArray;
m_iMaxArray += iElements+1;
m_pArray = (TYPE *)LOCALREALLOC(m_pArray, m_iMaxArray * sizeof(TYPE));
for(i=iCurrentSize; i>=insertAt; i--)
memcpy(&m_pArray[i+iElements], &m_pArray[i], sizeof(TYPE));
//clear out new cells
memset(m_pArray+insertAt, 0, iElements * sizeof(TYPE));
return (*((TYPE*) &m_pArray[insertAt]));
}
/*
* Varray SIZEOF method
*
* The SIZEOF method returns the currently allocated size of the
* internal array.
*/
template <class TYPE> inline int Varray<TYPE>::SIZEOF(void)
{
return m_iMaxArray;
}
//Note: This method will be invalid after elements are inserted into the
//varray. So use with caution.
template <class TYPE> inline int Varray<TYPE>::LastUsed(void)
{
return m_iLastUsedArray;
}
#define _INC_ARRAY_TEMPLATE
#endif