You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
882 lines
24 KiB
882 lines
24 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// DynamicArray.h
|
|
//
|
|
// Description:
|
|
// This file contains an array template that doesn't throw exceptions.
|
|
//
|
|
// Documentation:
|
|
//
|
|
// Implementation Files:
|
|
// None.
|
|
//
|
|
// Maintained By:
|
|
// John Franco (jfranco) 22-AUG-2001
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Make sure that this file is included only once per compile path.
|
|
#pragma once
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Include Files
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Constant Declarations
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Template Declarations
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment > template
|
|
//
|
|
// Description:
|
|
// DynamicArray stores a variable number of Items in a contiguous block
|
|
// of memory. It intends to be similar to std::vector, with the main
|
|
// difference being that it handles errors through return values rather
|
|
// than exceptions.
|
|
//
|
|
// Template Arguments:
|
|
// Item - the type of the elements in the array.
|
|
// requirements for Item:
|
|
// - default constructor
|
|
//
|
|
// Assignment
|
|
// The function that overwrites one Item with another; default is
|
|
// one that assumes Item has an assignment operator that never fails.
|
|
//
|
|
// requirements for Assignment:
|
|
// - default constructor
|
|
// - HRESULT operator()( Item &, const Item & ) const;
|
|
// or, PredecessorFunction can be a pointer to a function
|
|
// taking two Item references and returning an HRESULT.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace Generics
|
|
{
|
|
|
|
template < class Item >
|
|
struct DefaultAssignment
|
|
{
|
|
HRESULT operator()( Item& rItemDestInOut, const Item& crItemSourceIn ) const
|
|
{
|
|
rItemDestInOut = crItemSourceIn;
|
|
return S_OK;
|
|
}
|
|
};
|
|
|
|
|
|
template < class Item, class Assignment = DefaultAssignment<Item> >
|
|
class DynamicArray
|
|
{
|
|
public:
|
|
|
|
typedef Item* Iterator;
|
|
typedef const Item* ConstIterator;
|
|
|
|
DynamicArray( void );
|
|
~DynamicArray( void );
|
|
|
|
HRESULT HrReserve( size_t cNewCapacityIn );
|
|
HRESULT HrResize( size_t cNewSizeIn, const Item& crItemFillerIn = Item() );
|
|
HRESULT HrPushBack( const Item& crItemToPushIn );
|
|
HRESULT HrPopBack( void );
|
|
HRESULT HrRemove( Iterator ItemToRemoveIn );
|
|
HRESULT HrCompact( void );
|
|
void Clear( void );
|
|
void Swap( DynamicArray& rOtherInOut );
|
|
|
|
size_t CCapacity( void ) const;
|
|
size_t Count( void ) const;
|
|
bool BEmpty( void ) const;
|
|
|
|
Iterator ItBegin( void );
|
|
ConstIterator ItBegin( void ) const;
|
|
|
|
Iterator ItEnd( void );
|
|
ConstIterator ItEnd( void ) const;
|
|
|
|
Item& operator[]( size_t idxItemIn );
|
|
const Item& operator[]( size_t idxItemIn ) const;
|
|
|
|
private:
|
|
|
|
DynamicArray( const DynamicArray& );
|
|
DynamicArray& operator=( const DynamicArray& );
|
|
|
|
HRESULT HrRaiseCapacity( size_t cAmountIn );
|
|
|
|
Item* m_prgItems;
|
|
size_t m_cItems;
|
|
size_t m_cCapacity;
|
|
Assignment m_opAssign;
|
|
}; //*** class DynamicArray< Item, Assignment >
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::DynamicArray
|
|
//
|
|
// Description:
|
|
// Initializes the array as empty.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// None.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
DynamicArray< Item, Assignment >::DynamicArray( void ):
|
|
m_prgItems( NULL ), m_cItems( 0 ), m_cCapacity( 0 ), m_opAssign() {}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::~DynamicArray
|
|
//
|
|
// Description:
|
|
// Frees any memory held by the array, invoking destructors of any
|
|
// objects within the array.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// None.
|
|
//
|
|
// Remarks:
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
DynamicArray< Item, Assignment >::~DynamicArray( void )
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrPushBack
|
|
//
|
|
// Description:
|
|
// Appends a copy of an object onto the end of the array,
|
|
// growing the array if necessary.
|
|
//
|
|
// Arguments:
|
|
// crItemToPushIn - The object to copy onto the end of the array.
|
|
//
|
|
// Return Values:
|
|
// S_OK - The array has added a copy of the object to its end.
|
|
//
|
|
// Failure - Something went wrong, and the array's size is unchanged.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::push_back.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline HRESULT DynamicArray< Item, Assignment >::HrPushBack( const Item& crItemToPushIn )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Raise capacity if necessary.
|
|
if ( m_cCapacity == 0 )
|
|
{
|
|
hr = HrRaiseCapacity( 1 );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else if ( m_cItems == m_cCapacity )
|
|
{
|
|
hr = HrRaiseCapacity( m_cCapacity );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Copy crItemToPushIn into space just after any current contents.
|
|
hr = m_opAssign( m_prgItems[ m_cItems ], crItemToPushIn );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
m_cItems += 1;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrPushBack
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrPopBack
|
|
//
|
|
// Description:
|
|
// Discards the last element of the array, if one exists.
|
|
//
|
|
// Arguments:
|
|
// crItemToPushIn - The object to copy onto the end of the array.
|
|
//
|
|
// Return Values:
|
|
// S_OK - The array has added a copy of the object to its end.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::pop_back.
|
|
//
|
|
// This does not destroy the last object in the array; it merely marks
|
|
// that position as unused. To free the resources associated with the
|
|
// popped object, call HrCompact.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline HRESULT DynamicArray< Item, Assignment >::HrPopBack( void )
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if ( m_cItems > 0 )
|
|
{
|
|
m_cItems -= 1;
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrPopBack
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrResize
|
|
//
|
|
// Description:
|
|
// Change the effective size of the array.
|
|
//
|
|
// Arguments:
|
|
// cNewSizeIn
|
|
// The array's new size.
|
|
//
|
|
// crItemFillerIn
|
|
// If the array is growing, copy this item into the spaces after the
|
|
// array's current contents.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Subsequent calls to Count will return cNewSizeIn, and indexing
|
|
// into the array with any value from zero up to cNewSizeIn - 1
|
|
// will return a valid object reference.
|
|
//
|
|
// Failure
|
|
// Something went wrong and the size is unchanged.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::resize.
|
|
//
|
|
// If cNewSizeIn is not greater than the array's capacity, the array
|
|
// performs no memory reallocations. To force the array to consume only
|
|
// the memory necessary to contain the new size, call HrCompact.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
HRESULT DynamicArray< Item, Assignment >::HrResize( size_t cNewSizeIn, const Item& crItemFillerIn )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
size_t idx = 0;
|
|
|
|
// Raise capacity if necessary.
|
|
if ( cNewSizeIn > m_cCapacity )
|
|
{
|
|
hr = HrRaiseCapacity( cNewSizeIn - m_cCapacity );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Fill any empty spaces with crItemFillerIn.
|
|
for ( idx = m_cItems; idx < cNewSizeIn; ++idx )
|
|
{
|
|
hr = m_opAssign( m_prgItems[ idx ], crItemFillerIn );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
m_cItems = cNewSizeIn;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrResize
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrReserve
|
|
//
|
|
// Description:
|
|
// Set a lower bound for the array's capacity.
|
|
//
|
|
// Arguments:
|
|
// cNewCapacityIn
|
|
// The desired lower bound for the array's capacity.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// Subsequent operations that change the array's size--HrResize,
|
|
// HrPushBack, HrPopBack, HrRemove--will not cause a memory
|
|
// reallocation as long as the size does not exceed cNewCapacityIn.
|
|
// Also, subsequent calls to CCapacity will return a value not less
|
|
// than cNewCapacityIn.
|
|
//
|
|
// (Calling Clear does reset the capacity to zero, however.)
|
|
//
|
|
// Failure
|
|
// Something went wrong, and the capacity is unchanged.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::reserve.
|
|
//
|
|
// If cNewCapacityIn is not greater than the array's capacity, the array's
|
|
// capacity does not change. To force the array to consume only
|
|
// the memory necessary to contain the current size, call HrCompact.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline HRESULT DynamicArray< Item, Assignment >::HrReserve( size_t cNewCapacityIn )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( cNewCapacityIn > m_cCapacity )
|
|
{
|
|
hr = HrRaiseCapacity( cNewCapacityIn - m_cCapacity );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrReserve
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrRemove
|
|
//
|
|
// Description:
|
|
// Eliminate a particular element from the array.
|
|
//
|
|
// Arguments:
|
|
// ItemToRemoveIn
|
|
// A pointer to the element to remove.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// The array's size has decreased by one, and the given element is
|
|
// gone.
|
|
//
|
|
// E_INVALIDARG
|
|
// The given pointer was not within the array's valid range.
|
|
//
|
|
// Other failures
|
|
// Something went wrong; those items preceding that given are
|
|
// unchanged, but others may have been overwritten by their successors.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::erase.
|
|
//
|
|
// This moves all successors to the element up by one, taking linear time.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
HRESULT DynamicArray< Item, Assignment >::HrRemove( Iterator ItemToRemoveIn )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
Iterator it;
|
|
|
|
if ( ( ItemToRemoveIn < m_prgItems ) || ( ItemToRemoveIn >= ItEnd() ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Move all items after ItemToRemoveIn forward by one, overwriting *ItemToRemoveIn.
|
|
for ( it = ItemToRemoveIn + 1; it != ItEnd(); ++it )
|
|
{
|
|
hr = m_opAssign( *( it - 1 ), *it );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
m_cItems -= 1;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrRemove
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrCompact
|
|
//
|
|
// Description:
|
|
// Force the array to consume just enough memory to hold its current
|
|
// contents, performing a reallocation if necessary.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// S_OK - The array's size is now the same as its capacity.
|
|
//
|
|
// Failure - Something went wrong; the array is unchanged.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// No analogue in std::vector.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
HRESULT DynamicArray< Item, Assignment >::HrCompact( void )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
Item* prgNewArray = NULL;
|
|
|
|
if ( m_cItems < m_cCapacity ) // Otherwise, it's already compact.
|
|
{
|
|
if ( m_cItems > 0 )
|
|
{
|
|
size_t idx = 0;
|
|
|
|
// Allocate just enough memory to hold the current contents.
|
|
prgNewArray = new Item[ m_cItems ];
|
|
if ( prgNewArray == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Copy the current contents into the newly allocated memory.
|
|
for ( idx = 0; idx < m_cItems; ++idx )
|
|
{
|
|
hr = m_opAssign( prgNewArray[ idx ], m_prgItems[ idx ] );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Take ownership of the new memory and discard the old.
|
|
delete[] m_prgItems;
|
|
m_prgItems = prgNewArray;
|
|
prgNewArray = NULL;
|
|
m_cCapacity = m_cItems;
|
|
}
|
|
else // No current contents, so just dump everything.
|
|
{
|
|
Clear();
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if ( prgNewArray != NULL )
|
|
{
|
|
delete[] prgNewArray;
|
|
}
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrCompact
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::Clear
|
|
//
|
|
// Description:
|
|
// Reset the array to its original, empty state, and release any
|
|
// currently allocated memory.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// None.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::clear.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
void DynamicArray< Item, Assignment >::Clear( void )
|
|
{
|
|
if ( m_prgItems != NULL )
|
|
{
|
|
delete[] m_prgItems;
|
|
m_prgItems = NULL;
|
|
m_cItems = 0;
|
|
m_cCapacity = 0;
|
|
}
|
|
} //*** DynamicArray< Item, Assignment >::Clear
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::Swap
|
|
//
|
|
// Description:
|
|
// Swaps the contents of this array with another.
|
|
//
|
|
// Arguments:
|
|
// rOtherInOut - The array with which to swap.
|
|
//
|
|
// Return Values:
|
|
// None.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::swap.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
void DynamicArray< Item, Assignment >::Swap( DynamicArray& rOtherInOut )
|
|
{
|
|
if ( this != &rOtherInOut )
|
|
{
|
|
Item* prgItemStash = m_prgItems;
|
|
size_t cCountStash = m_cItems;
|
|
size_t cCapacityStash = m_cCapacity;
|
|
|
|
m_prgItems = rOtherInOut.m_prgItems;
|
|
rOtherInOut.m_prgItems = prgItemStash;
|
|
|
|
m_cItems = rOtherInOut.m_cItems;
|
|
rOtherInOut.m_cItems = cCountStash;
|
|
|
|
m_cCapacity = rOtherInOut.m_cCapacity;
|
|
rOtherInOut.m_cCapacity = cCapacityStash;
|
|
}
|
|
} //*** DynamicArray< Item, Assignment >::Swap
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::CCapacity
|
|
//
|
|
// Description:
|
|
// Provide the array's current capacity.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// The array's current capacity.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::capacity.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline size_t DynamicArray< Item, Assignment >::CCapacity( void ) const
|
|
{
|
|
return m_cCapacity;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::Count
|
|
//
|
|
// Description:
|
|
// Provide the array's current size.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// The array's current size.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::size.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline size_t DynamicArray< Item, Assignment >::Count( void ) const
|
|
{
|
|
return m_cItems;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::BEmpty
|
|
//
|
|
// Description:
|
|
// Report whether the array contains anything.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// true - The array contains nothing.
|
|
// false - The array contains something.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::empty. Synonymous with Count() == 0.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline bool DynamicArray< Item, Assignment >::BEmpty( void ) const
|
|
{
|
|
return ( m_cItems == 0 );
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::ItBegin
|
|
//
|
|
// Description:
|
|
// Provide a pointer to the array's first element.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// A pointer to the array's first element if one exists, ItEnd() if not.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::begin.
|
|
//
|
|
// The const overload provides a read-only pointer.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline __TYPENAME DynamicArray< Item, Assignment >::Iterator DynamicArray< Item, Assignment >::ItBegin( void )
|
|
{
|
|
return m_prgItems;
|
|
}
|
|
|
|
template < class Item, class Assignment >
|
|
inline __TYPENAME DynamicArray< Item, Assignment >::ConstIterator DynamicArray< Item, Assignment >::ItBegin( void ) const
|
|
{
|
|
return m_prgItems;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::ItEnd
|
|
//
|
|
// Description:
|
|
// Provide a "one past end" pointer to the array's contents.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Values:
|
|
// A "one past end" pointer to the array's contents if any exist,
|
|
// ItBegin() if not.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::end.
|
|
//
|
|
// A "one past end" pointer allows enumeration of all the array's
|
|
// contents by the common loop,
|
|
// for (it = a.ItBegin(); it != a.ItEnd(); ++it).
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline __TYPENAME DynamicArray< Item, Assignment >::Iterator DynamicArray< Item, Assignment >::ItEnd( void )
|
|
{
|
|
return ( m_prgItems + m_cItems );
|
|
}
|
|
|
|
template < class Item, class Assignment >
|
|
inline __TYPENAME DynamicArray< Item, Assignment >::ConstIterator DynamicArray< Item, Assignment >::ItEnd( void ) const
|
|
{
|
|
return ( m_prgItems + m_cItems );
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::operator[]
|
|
//
|
|
// Description:
|
|
// Provide subscripted, constant-time access to the array's contents.
|
|
//
|
|
// Arguments:
|
|
// idxItemIn - The zero-based index of the item desired.
|
|
//
|
|
// Return Values:
|
|
// A reference to the item at the given position.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// Analogous to std::vector::operator[].
|
|
// The const overload provides read-only access.
|
|
// This makes no attempt at range-checking; the caller should use
|
|
// Count() to determine whether the index is valid.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
inline Item& DynamicArray< Item, Assignment >::operator[]( size_t idxItemIn )
|
|
{
|
|
return m_prgItems[ idxItemIn ];
|
|
}
|
|
|
|
template < class Item, class Assignment >
|
|
inline const Item& DynamicArray< Item, Assignment >::operator[]( size_t idxItemIn ) const
|
|
{
|
|
return m_prgItems[ idxItemIn ];
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// DynamicArray< Item, Assignment >::HrRaiseCapacity
|
|
//
|
|
// Description:
|
|
// Increase the array's capacity.
|
|
//
|
|
// Arguments:
|
|
// cAmountIn - The amount by which to increase the array's capacity.
|
|
//
|
|
// Return Values:
|
|
// S_OK
|
|
// The array has enough memory to hold an additional cAmountIn items.
|
|
//
|
|
// Failure
|
|
// Something went wrong, and the capacity is unchanged.
|
|
//
|
|
// Remarks:
|
|
//
|
|
// No analogue in std::vector; this is a private function.
|
|
//
|
|
//--
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
template < class Item, class Assignment >
|
|
HRESULT DynamicArray< Item, Assignment >::HrRaiseCapacity( size_t cAmountIn )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
size_t idx = 0;
|
|
Item* prgNewArray = NULL;
|
|
|
|
if ( cAmountIn == 0 ) // Nothing to do.
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Allocate enough space for the new capacity
|
|
prgNewArray = new Item[ m_cCapacity + cAmountIn ];
|
|
if ( prgNewArray == NULL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Copy the current contents into the new space.
|
|
for ( idx = 0; idx < m_cItems; ++idx )
|
|
{
|
|
hr = m_opAssign( prgNewArray[ idx ], m_prgItems[ idx ] );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// Take ownership of the new space.
|
|
if ( m_prgItems != NULL )
|
|
{
|
|
delete[] m_prgItems;
|
|
}
|
|
|
|
m_prgItems = prgNewArray;
|
|
prgNewArray = NULL;
|
|
m_cCapacity += cAmountIn;
|
|
|
|
Cleanup:
|
|
|
|
if ( prgNewArray != NULL )
|
|
{
|
|
delete[] prgNewArray;
|
|
}
|
|
|
|
return hr;
|
|
} //*** DynamicArray< Item, Assignment >::HrRaiseCapacity
|
|
|
|
|
|
} //*** Generics namespace
|
|
|