944 lines
22 KiB
C++
944 lines
22 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1991 - 1998.
|
|
//
|
|
// File: DYNARRAY.HXX
|
|
//
|
|
// Contents: Dynamic Array Template
|
|
//
|
|
// Classes: CDynArray
|
|
// CCountedDynArray
|
|
// CCountedIDynArray
|
|
// CDynArrayInPlace
|
|
// CDynArrayInPlaceNST
|
|
// CDynStackInPlace
|
|
//
|
|
// History: 20-Jan-92 AmyA Created
|
|
// 05-Feb-92 BartoszM Converted to macro
|
|
// 19-Jun-92 KyleP Moved to Common
|
|
// 06-Jan-93 AmyA Split into CDynArray and CDynStack
|
|
// 17-Oct-94 BartoszM Converted to template
|
|
// 10-Mar-98 KLam Added index operator to CCountedDynArray
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include <new.h> // Global placement ::operator new
|
|
|
|
#define arraySize 16
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Class: CDynArray
|
|
//
|
|
// Purpose: Template used to hold dynamically sized arrays of objects
|
|
//
|
|
// History: 19-Aug-98 KLam Added this header
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
template<class CItem> class CDynArray
|
|
{
|
|
public:
|
|
CDynArray(unsigned size = arraySize);
|
|
|
|
void SetExactSize( unsigned size )
|
|
{
|
|
Free();
|
|
|
|
if ( 0 != size )
|
|
{
|
|
_size = size;
|
|
_aItem = new CItem *[_size];
|
|
RtlZeroMemory( _aItem, _size*sizeof(CItem *) );
|
|
}
|
|
}
|
|
|
|
CDynArray( CDynArray<CItem> & src );
|
|
|
|
~CDynArray();
|
|
|
|
void Add(CItem *newItem, unsigned position);
|
|
unsigned Size () const {return _size;}
|
|
CItem * Get (unsigned position) const;
|
|
CItem * GetItem( unsigned position ) const
|
|
{
|
|
// unlike Get(), no range-checking is done in free builds
|
|
|
|
Win4Assert( position < _size );
|
|
return _aItem[position];
|
|
}
|
|
void Clear();
|
|
|
|
void Free()
|
|
{
|
|
Clear();
|
|
delete _aItem;
|
|
_aItem = 0;
|
|
_size = 0;
|
|
}
|
|
CItem * Acquire (unsigned position);
|
|
|
|
CItem * & operator[]( unsigned position ) const
|
|
{
|
|
Win4Assert( position < _size );
|
|
return _aItem[position];
|
|
}
|
|
CItem ** GetPointer() const { return _aItem; }
|
|
|
|
CItem ** AcquireAll()
|
|
{
|
|
CItem **ppTemp = _aItem;
|
|
_size = 0;
|
|
_aItem = 0;
|
|
|
|
return ppTemp;
|
|
}
|
|
|
|
protected:
|
|
|
|
//
|
|
// _size **must** come before _aItem. See the copy constructor below
|
|
// and remember the order of member initialization...
|
|
//
|
|
|
|
unsigned _size;
|
|
CItem ** _aItem;
|
|
};
|
|
|
|
#define DECL_DYNARRAY( CMyDynArray, CItem )\
|
|
typedef CDynArray<CItem> CMyDynArray;
|
|
|
|
#define IMPL_DYNARRAY( CMyDynArray, CItem )
|
|
|
|
|
|
template<class CItem> CDynArray<CItem>::CDynArray(unsigned size)
|
|
: _size( size ), _aItem( 0 )
|
|
{
|
|
if ( 0 != _size )
|
|
{
|
|
_aItem = new CItem *[_size];
|
|
RtlZeroMemory( _aItem, _size*sizeof(CItem *) );
|
|
}
|
|
}
|
|
|
|
template<class CItem> CDynArray<CItem>::CDynArray( CDynArray<CItem> & src )
|
|
: _size( src._size ),
|
|
_aItem( src.AcquireAll() )
|
|
{
|
|
}
|
|
|
|
template<class CItem> CDynArray<CItem>::~CDynArray()
|
|
{
|
|
Clear();
|
|
delete _aItem;
|
|
}
|
|
|
|
template<class CItem> void CDynArray<CItem>::Clear()
|
|
{
|
|
for (unsigned i=0; i < _size; i++) {
|
|
delete _aItem[i];
|
|
_aItem[i] = 0;
|
|
}
|
|
}
|
|
|
|
template<class CItem> CItem* CDynArray<CItem>::Acquire(unsigned position)
|
|
{
|
|
CItem *tmp = Get(position);
|
|
if (tmp) _aItem[position] = 0;
|
|
return tmp;
|
|
}
|
|
|
|
template<class CItem> void CDynArray<CItem>::Add(CItem *newItem, unsigned position)
|
|
{
|
|
if (position >= _size)
|
|
{
|
|
unsigned newsize = _size * 2;
|
|
if ( newsize == 0 )
|
|
newsize = arraySize;
|
|
for( ; position>=newsize; newsize*=2);
|
|
|
|
CItem **aNew = new CItem *[newsize];
|
|
memcpy( aNew,
|
|
_aItem,
|
|
_size * sizeof( CItem *) );
|
|
RtlZeroMemory( aNew + _size,
|
|
(newsize-_size)*sizeof(CItem *) );
|
|
delete _aItem;
|
|
_aItem = aNew;
|
|
_size = newsize;
|
|
}
|
|
Win4Assert( _aItem[position] == 0 );
|
|
_aItem[position] = newItem;
|
|
}
|
|
|
|
template<class CItem> CItem* CDynArray<CItem>::Get(unsigned position) const
|
|
{
|
|
if ( position >= _size )
|
|
return(0);
|
|
return _aItem[position];
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Class: CCountedDynArray
|
|
//
|
|
// Purpose: Template used to hold dynamically sized arrays of objects with a count
|
|
//
|
|
// History: 19-Aug-98 KLam Added this header
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
template<class CItem> class CCountedDynArray: public CDynArray<CItem>
|
|
{
|
|
public:
|
|
CCountedDynArray(unsigned size = arraySize)
|
|
: CDynArray<CItem>( size ),
|
|
_cItem( 0 )
|
|
{
|
|
}
|
|
|
|
void Add(CItem *newItem, unsigned position)
|
|
{
|
|
CDynArray<CItem>::Add( newItem, position );
|
|
|
|
if ( position + 1 > _cItem )
|
|
_cItem = position + 1;
|
|
}
|
|
|
|
CItem * AcquireAndShrink(unsigned position)
|
|
{
|
|
XPtr<CItem> xItem( Acquire(position) );
|
|
|
|
if ( 0 != _cItem && position < (_cItem-1) )
|
|
{
|
|
Add( Acquire(_cItem-1) , position );
|
|
}
|
|
|
|
return xItem.Acquire();
|
|
}
|
|
|
|
CItem * AcquireAndShrinkAndPreserveOrder(unsigned position)
|
|
{
|
|
XPtr<CItem> xItem( Acquire(position) );
|
|
|
|
if ( 0 != _cItem && position < (_cItem-1) )
|
|
{
|
|
for ( unsigned i = position; i < (_cItem-1); i++ )
|
|
Add( Acquire(i+1) , i );
|
|
}
|
|
|
|
return xItem.Acquire();
|
|
}
|
|
|
|
unsigned Count() const { return _cItem; }
|
|
|
|
void Clear()
|
|
{
|
|
CDynArray<CItem>::Clear();
|
|
_cItem = 0;
|
|
}
|
|
|
|
void Free()
|
|
{
|
|
CDynArray<CItem>::Free();
|
|
_cItem = 0;
|
|
}
|
|
|
|
CItem * Acquire (unsigned position)
|
|
{
|
|
if ( position == (_cItem - 1) )
|
|
_cItem--;
|
|
|
|
return CDynArray<CItem>::Acquire( position );
|
|
}
|
|
|
|
CItem * & operator[]( unsigned position ) const
|
|
{
|
|
Win4Assert( position < _cItem );
|
|
return _aItem[position];
|
|
}
|
|
|
|
protected:
|
|
unsigned _cItem;
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Class: CCountedIDynArray
|
|
//
|
|
// Purpose: Maintains an array of interface pointers
|
|
//
|
|
// History: 12-Mar-98 KLam Added this header
|
|
// 12-Mar-98 KLam Added AddRef and Destructor does not assert
|
|
// released items have a ref count of 0
|
|
//
|
|
// Notes:
|
|
// The class assumes that the creator of the interface pointer has passed
|
|
// ownership (and therefore the original reference count) to this object.
|
|
// When the object is destroyed it releases each of the interface pointers
|
|
// maintained by the object.
|
|
// If you want the interfaces in this array to exist beyond the lifespan
|
|
// of this class then you must AddRef each of those interface pointers.
|
|
// Array can be sparse.
|
|
//+---------------------------------------------------------------------------
|
|
|
|
template<class CItem> class CCountedIDynArray: public CCountedDynArray<CItem>
|
|
{
|
|
public:
|
|
|
|
CCountedIDynArray(unsigned size = arraySize)
|
|
: CCountedDynArray<CItem>( size )
|
|
{
|
|
}
|
|
|
|
~CCountedIDynArray()
|
|
{
|
|
Release();
|
|
for ( unsigned i = 0; i < _size; i++ )
|
|
_aItem[ i ] = 0;
|
|
}
|
|
|
|
int Release(); // Calls Release on each interface
|
|
|
|
void ReleaseAndShrink(); // Calls Release on each interface and packs array
|
|
|
|
void AddRef(); // Calls AddRef on each interface
|
|
|
|
void Free()
|
|
{
|
|
Release();
|
|
CCountedDynArray<CItem>::Free();
|
|
}
|
|
|
|
private:
|
|
|
|
void Clear(); // not a valid method on interfaces.
|
|
|
|
};
|
|
|
|
template<class CItem> void CCountedIDynArray<CItem>::AddRef()
|
|
{
|
|
for ( unsigned i=0; i < _cItem; i++ )
|
|
if ( 0 != _aItem[i] )
|
|
_aItem[i]->AddRef();
|
|
}
|
|
|
|
// Note: Could make the array sparse(r).
|
|
// Value returned could be less than or equal to Count().
|
|
template<class CItem> int CCountedIDynArray<CItem>::Release()
|
|
{
|
|
int cItems = 0;
|
|
for (unsigned i=0; i < _cItem; i++)
|
|
{
|
|
if ( 0 != _aItem[i] )
|
|
{
|
|
if ( 0 == _aItem[i]->Release() )
|
|
{
|
|
_aItem[i] = 0;
|
|
if ( i == _cItem - 1 )
|
|
_cItem--;
|
|
}
|
|
else
|
|
++cItems;
|
|
}
|
|
}
|
|
|
|
return cItems;
|
|
}
|
|
|
|
// Note: Packs the array and preserves the order
|
|
template<class CItem> void CCountedIDynArray<CItem>::ReleaseAndShrink()
|
|
{
|
|
unsigned i=0;
|
|
while ( i < _cItem )
|
|
{
|
|
if ( 0 != _aItem[i] && 0 == _aItem[i]->Release() )
|
|
{
|
|
// This method will decrement _cItem
|
|
AcquireAndShrinkAndPreserveOrder(i);
|
|
}
|
|
else
|
|
i++;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Class: CDynArrayInPlace
|
|
//
|
|
// Purpose: Identical to CDynArray except array objects are stored in place,
|
|
// instead of storing an array of pointers.
|
|
//
|
|
// History: 19-Aug-98 KLam Added this header
|
|
//
|
|
// Note: This reduces memory allocations, but does not work for objects
|
|
// with destructors.
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
template<class CItem> class CDynArrayInPlace
|
|
{
|
|
|
|
public:
|
|
|
|
CDynArrayInPlace(unsigned size);
|
|
CDynArrayInPlace();
|
|
CDynArrayInPlace( CDynArrayInPlace const & src );
|
|
CDynArrayInPlace( CDynArrayInPlace const & src, unsigned size );
|
|
~CDynArrayInPlace();
|
|
|
|
void Add( const CItem &newItem, unsigned position);
|
|
void Insert(const CItem& newItem, unsigned position);
|
|
void Remove (unsigned position);
|
|
unsigned Size () const {return _size;}
|
|
CItem& Get (unsigned position) const;
|
|
CItem * Get() { return _aItem; }
|
|
void Clear();
|
|
unsigned Count() const { return _count; }
|
|
|
|
void SetSize(unsigned position)
|
|
{
|
|
if (position >= _size)
|
|
_GrowToSize(position);
|
|
}
|
|
|
|
void SetExactSize( unsigned size )
|
|
{
|
|
Clear();
|
|
|
|
if ( 0 != size )
|
|
{
|
|
_size = size;
|
|
_aItem = new CItem [_size];
|
|
RtlZeroMemory( _aItem, _size * sizeof(CItem) );
|
|
}
|
|
}
|
|
|
|
void Shrink()
|
|
{
|
|
// make size == count, to save memory
|
|
|
|
if ( 0 == _count )
|
|
{
|
|
Clear();
|
|
}
|
|
else if ( _count != _size )
|
|
{
|
|
CItem * p = new CItem [_count];
|
|
_size = _count;
|
|
RtlCopyMemory( p, _aItem, _count * sizeof CItem );
|
|
delete (BYTE *) _aItem;
|
|
_aItem = p;
|
|
}
|
|
}
|
|
|
|
CItem* Acquire ()
|
|
{
|
|
CItem *temp = _aItem;
|
|
_aItem = 0;
|
|
_count = 0;
|
|
_size = 0;
|
|
return temp;
|
|
}
|
|
|
|
void Duplicate( CDynArrayInPlace<CItem> & aFrom )
|
|
{
|
|
Clear();
|
|
|
|
if ( 0 != aFrom.Count() )
|
|
{
|
|
_size = _count = aFrom.Count();
|
|
_aItem = new CItem [_size];
|
|
memcpy( _aItem, aFrom._aItem, _size * sizeof( CItem ) );
|
|
}
|
|
}
|
|
|
|
CItem & operator[]( unsigned position )
|
|
{
|
|
if ( position >= _count )
|
|
{
|
|
if ( position >= _size )
|
|
_GrowToSize( position );
|
|
|
|
_count = position + 1;
|
|
}
|
|
|
|
return _aItem[position];
|
|
}
|
|
CItem & operator[]( unsigned position ) const
|
|
{
|
|
Win4Assert( position < _count );
|
|
return _aItem[position];
|
|
}
|
|
|
|
CItem const * GetPointer() { return _aItem; }
|
|
unsigned SizeOfInUse() const { return sizeof CItem * Count(); }
|
|
|
|
protected:
|
|
|
|
void _GrowToSize( unsigned position );
|
|
|
|
CItem * _aItem;
|
|
unsigned _size;
|
|
unsigned _count;
|
|
};
|
|
|
|
|
|
#define DECL_DYNARRAY_INPLACE( CMyDynArrayInPlace, CItem )\
|
|
typedef CDynArrayInPlace<CItem> CMyDynArrayInPlace;
|
|
|
|
#define IMPL_DYNARRAY_INPLACE( CMyDynArrayInPlace, CItem )
|
|
|
|
template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace(unsigned size)
|
|
: _size(size), _count(0), _aItem( 0 )
|
|
{
|
|
if ( 0 != size )
|
|
{
|
|
_aItem = new CItem [_size];
|
|
RtlZeroMemory( _aItem, _size * sizeof(CItem) );
|
|
}
|
|
}
|
|
|
|
template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace()
|
|
: _size(0), _count(0), _aItem(0)
|
|
{
|
|
}
|
|
|
|
template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace( CDynArrayInPlace const & src )
|
|
: _size( src._size ),
|
|
_count( src._count )
|
|
{
|
|
_aItem = new CItem [_size];
|
|
RtlCopyMemory( _aItem, src._aItem, _size * sizeof(_aItem[0]) );
|
|
}
|
|
|
|
template<class CItem> CDynArrayInPlace<CItem>::CDynArrayInPlace(
|
|
CDynArrayInPlace const & src,
|
|
unsigned size )
|
|
: _size( size ),
|
|
_count( src._count )
|
|
{
|
|
// this constructor is useful if the size should be larger than the
|
|
// # of items in the source array
|
|
|
|
Win4Assert( _size >= _count );
|
|
_aItem = new CItem [_size];
|
|
RtlCopyMemory( _aItem, src._aItem, _count * sizeof CItem );
|
|
}
|
|
|
|
template<class CItem> CDynArrayInPlace<CItem>::~CDynArrayInPlace()
|
|
{
|
|
delete [] _aItem;
|
|
}
|
|
|
|
template<class CItem> void CDynArrayInPlace<CItem>::Clear()
|
|
{
|
|
delete [] _aItem;
|
|
_aItem = 0;
|
|
_size = 0;
|
|
_count = 0;
|
|
}
|
|
|
|
template<class CItem> void CDynArrayInPlace<CItem>::_GrowToSize( unsigned position )
|
|
{
|
|
Win4Assert( position >= _size );
|
|
|
|
unsigned newsize = _size * 2;
|
|
if ( newsize == 0 )
|
|
newsize = arraySize;
|
|
for( ; position >= newsize; newsize *= 2)
|
|
continue;
|
|
|
|
CItem *aNew = new CItem [newsize];
|
|
if (_size > 0)
|
|
{
|
|
memcpy( aNew,
|
|
_aItem,
|
|
_size * sizeof( CItem ) );
|
|
}
|
|
RtlZeroMemory( aNew + _size,
|
|
(newsize-_size) * sizeof(CItem) );
|
|
delete (BYTE*) _aItem;
|
|
_aItem = aNew;
|
|
_size = newsize;
|
|
}
|
|
|
|
template<class CItem> void CDynArrayInPlace<CItem>::Add(const CItem &newItem,
|
|
unsigned position)
|
|
{
|
|
if (position >= _count)
|
|
{
|
|
if (position >= _size)
|
|
_GrowToSize( position );
|
|
|
|
_count = position + 1;
|
|
}
|
|
|
|
_aItem[position] = newItem;
|
|
}
|
|
|
|
template<class CItem> CItem& CDynArrayInPlace<CItem>::Get(unsigned position) const
|
|
{
|
|
Win4Assert( position < _count );
|
|
|
|
return _aItem[position];
|
|
}
|
|
|
|
template<class CItem> void CDynArrayInPlace<CItem>::Insert(const CItem& newItem, unsigned pos)
|
|
{
|
|
Win4Assert(pos <= _count);
|
|
Win4Assert(_count <= _size);
|
|
if (_count == _size)
|
|
{
|
|
unsigned newsize;
|
|
if ( _size == 0 )
|
|
newsize = arraySize;
|
|
else
|
|
newsize = _size * 2;
|
|
CItem *aNew = new CItem [newsize];
|
|
memcpy( aNew,
|
|
_aItem,
|
|
pos * sizeof( CItem ) );
|
|
memcpy( aNew + pos + 1,
|
|
_aItem + pos,
|
|
(_count - pos) * sizeof(CItem));
|
|
|
|
delete (BYTE *) _aItem;
|
|
_aItem = aNew;
|
|
_size = newsize;
|
|
}
|
|
else
|
|
{
|
|
memmove ( _aItem + pos + 1,
|
|
_aItem + pos,
|
|
(_count - pos) * sizeof(CItem));
|
|
}
|
|
_aItem[pos] = newItem;
|
|
_count++;
|
|
}
|
|
|
|
template<class CItem> void CDynArrayInPlace<CItem>::Remove(unsigned pos)
|
|
{
|
|
Win4Assert(pos < _count);
|
|
Win4Assert(_count <= _size);
|
|
if (pos < _count - 1)
|
|
{
|
|
memmove ( _aItem + pos,
|
|
_aItem + pos + 1,
|
|
(_count - pos - 1) * sizeof(CItem));
|
|
}
|
|
RtlZeroMemory( _aItem + _count - 1, sizeof(CItem) );
|
|
_count--;
|
|
if (_count == 0)
|
|
{
|
|
delete (BYTE*) _aItem;
|
|
_aItem = 0;
|
|
_size = 0;
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CDynArrayInPlaceNST
|
|
//
|
|
// Purpose: DynArrayInPlace for NonSimpleTypes
|
|
//
|
|
// History: 4-June-98 dlee Created
|
|
//
|
|
// Notes: This isn't for every class in the world; use with care.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
template<class T> class CDynArrayInPlaceNST
|
|
{
|
|
|
|
public:
|
|
|
|
CDynArrayInPlaceNST(unsigned size) :
|
|
_size( size ), _count( 0 ), _aItem( 0 )
|
|
{
|
|
if ( 0 != size )
|
|
{
|
|
unsigned cb = _size * sizeof T;
|
|
_aItem = (T *) new BYTE[ cb ];
|
|
|
|
// Just in case...
|
|
|
|
RtlZeroMemory( _aItem, cb );
|
|
|
|
// Call all the default constructors
|
|
|
|
for ( unsigned i = 0; i < _size; i++ )
|
|
new( & _aItem[i] ) T;
|
|
}
|
|
}
|
|
|
|
CDynArrayInPlaceNST() : _count(0), _size(0), _aItem(0) {}
|
|
|
|
~CDynArrayInPlaceNST() { Clear(); }
|
|
|
|
unsigned Size () const { return _size; }
|
|
unsigned Count() const { return _count; }
|
|
T const * GetPointer() { return _aItem; }
|
|
unsigned SizeOfInUse() const { return sizeof T * Count(); }
|
|
|
|
void Add( const T &newItem, unsigned position)
|
|
{
|
|
if (position >= _count)
|
|
{
|
|
if (position >= _size)
|
|
_GrowToSize( position );
|
|
|
|
_count = position + 1;
|
|
}
|
|
|
|
_aItem[position] = newItem;
|
|
}
|
|
|
|
void Insert( const T& newItem, unsigned position )
|
|
{
|
|
Win4Assert(pos <= _count);
|
|
Win4Assert(_count <= _size);
|
|
|
|
if ( _count == _size )
|
|
{
|
|
unsigned newsize;
|
|
if ( _size == 0 )
|
|
newsize = arraySize;
|
|
else
|
|
newsize = _size * 2;
|
|
|
|
unsigned cb = newSize * sizeof T;
|
|
T * aNew = (T *) new BYTE[ cb ];
|
|
RtlZeroMemory( & aNew[ newSize - 1 ], sizeof T );
|
|
new( & _aItem[ newSize - 1 ]) T;
|
|
|
|
memcpy( aNew,
|
|
_aItem,
|
|
pos * sizeof T );
|
|
memcpy( aNew + pos + 1,
|
|
_aItem + pos,
|
|
(_count - pos) * sizeof T );
|
|
|
|
delete [] (BYTE *) _aItem;
|
|
_aItem = aNew;
|
|
_size = newsize;
|
|
}
|
|
else
|
|
{
|
|
memmove( _aItem + pos + 1,
|
|
_aItem + pos,
|
|
(_count - pos) * sizeof T );
|
|
}
|
|
|
|
RtlCopyMemory( _aItem[pos], newItem, sizeof T );
|
|
_count++;
|
|
}
|
|
|
|
#if 0 // probably broken...
|
|
void Remove (unsigned position)
|
|
{
|
|
Win4Assert(pos < _count);
|
|
Win4Assert(_count <= _size);
|
|
if (pos < _count - 1)
|
|
memmove ( _aItem + pos,
|
|
_aItem + pos + 1,
|
|
(_count - pos - 1) * sizeof T );
|
|
|
|
RtlZeroMemory( _aItem + _count - 1, sizeof T );
|
|
_count--;
|
|
if ( 0 == _count )
|
|
{
|
|
delete [] (BYTE*) _aItem;
|
|
_aItem = 0;
|
|
_size = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
T & Get (unsigned position) const
|
|
{
|
|
Win4Assert( position < _count );
|
|
return _aItem[ position ];
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
for ( unsigned i = 0; i < _size; i++ )
|
|
_aItem[i].~T();
|
|
|
|
delete [] (BYTE*) _aItem;
|
|
_aItem = 0;
|
|
_size = 0;
|
|
_count = 0;
|
|
}
|
|
|
|
|
|
void SetSize(unsigned position)
|
|
{
|
|
if (position >= _size)
|
|
_GrowToSize(position);
|
|
}
|
|
|
|
void SetExactSize( unsigned size )
|
|
{
|
|
Clear();
|
|
|
|
if ( 0 != size )
|
|
{
|
|
_size = size;
|
|
|
|
unsigned cb = _size * sizeof T;
|
|
_aItem = (T *) new BYTE[ cb ];
|
|
|
|
// Just in case...
|
|
|
|
RtlZeroMemory( _aItem, cb );
|
|
|
|
// Call all the default constructors
|
|
|
|
for ( unsigned i = 0; i < _size; i++ )
|
|
new( & _aItem[i] ) T;
|
|
}
|
|
}
|
|
|
|
void Shrink()
|
|
{
|
|
// make size == count, to save memory
|
|
|
|
if ( 0 == _count )
|
|
{
|
|
Clear();
|
|
}
|
|
else if ( _count != _size )
|
|
{
|
|
unsigned cb = _size * sizeof T;
|
|
T * p = (T *) new BYTE[ cb ];
|
|
_size = _count;
|
|
RtlCopyMemory( p, _aItem, _count * sizeof T );
|
|
delete [] (BYTE *) _aItem;
|
|
_aItem = p;
|
|
}
|
|
}
|
|
|
|
T * Acquire()
|
|
{
|
|
T *temp = _aItem;
|
|
_aItem = 0;
|
|
_count = 0;
|
|
_size = 0;
|
|
return temp;
|
|
}
|
|
|
|
void Duplicate( CDynArrayInPlaceNST<T> & aFrom )
|
|
{
|
|
Clear();
|
|
|
|
if ( 0 != aFrom.Count() )
|
|
{
|
|
_size = _count = aFrom.Count();
|
|
unsigned cb = _size * sizeof T;
|
|
_aItem = (T *) new BYTE[ cb ];
|
|
memcpy( _aItem, aFrom._aItem, _size * sizeof T );
|
|
}
|
|
}
|
|
|
|
T & operator[]( unsigned position )
|
|
{
|
|
if ( position >= _count )
|
|
{
|
|
if ( position >= _size )
|
|
_GrowToSize( position );
|
|
|
|
_count = position + 1;
|
|
}
|
|
|
|
return _aItem[position];
|
|
}
|
|
|
|
T & operator[]( unsigned position ) const
|
|
{
|
|
Win4Assert( position < _count );
|
|
return _aItem[position];
|
|
}
|
|
|
|
protected:
|
|
|
|
void _GrowToSize( unsigned position )
|
|
{
|
|
Win4Assert( position >= _size );
|
|
|
|
unsigned newSize = _size * 2;
|
|
if ( newSize == 0 )
|
|
newSize = arraySize;
|
|
for( ; position >= newSize; newSize *= 2)
|
|
continue;
|
|
|
|
unsigned cb = newSize * sizeof T;
|
|
T *aNew = (T *) new BYTE[ cb ];
|
|
|
|
if (_size > 0)
|
|
memcpy( aNew,
|
|
_aItem,
|
|
_size * sizeof T );
|
|
|
|
RtlZeroMemory( aNew + _size,
|
|
(newSize - _size) * sizeof T );
|
|
|
|
for ( unsigned i = _size; i < newSize; i++ )
|
|
new( & aNew[ i ] ) T;
|
|
|
|
delete [] (BYTE*) _aItem;
|
|
_aItem = aNew;
|
|
_size = newSize;
|
|
}
|
|
|
|
T * _aItem;
|
|
unsigned _size;
|
|
unsigned _count;
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CDynStackInPlace
|
|
//
|
|
// Purpose: Identical to CDynArrayInPlace except array is accessed as a stack.
|
|
// Unlike CDynStack because the actual objects are stored, not
|
|
// pointers. Useful for simple types.
|
|
//
|
|
// History: 19-Aug-98 KLam Added this header
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
template<class T> class CDynStackInPlace : public CDynArrayInPlace<T>
|
|
{
|
|
public:
|
|
CDynStackInPlace(unsigned size = arraySize);
|
|
~CDynStackInPlace() {};
|
|
void Push(T newItem);
|
|
unsigned Count () const { return _stackSize; }
|
|
T & Pop();
|
|
|
|
private:
|
|
unsigned _stackSize;
|
|
};
|
|
|
|
template<class T> CDynStackInPlace<T>::CDynStackInPlace(unsigned size) :
|
|
CDynArrayInPlace<T>(size),
|
|
_stackSize(0)
|
|
{
|
|
}
|
|
|
|
template<class T> void CDynStackInPlace<T>::Push(T newItem)
|
|
{
|
|
Add( newItem, _stackSize );
|
|
_stackSize++;
|
|
}
|
|
|
|
template<class T> T & CDynStackInPlace<T>::Pop()
|
|
{
|
|
Win4Assert( _stackSize > 0 );
|
|
|
|
_stackSize--;
|
|
return Get(_stackSize);
|
|
}
|