Leaked source code of windows server 2003
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.
 
 
 
 
 
 

300 lines
8.0 KiB

/**************************************************************************\
*
* Copyright (c) 1998 Microsoft Corporation
*
* Module Name:
*
* dynarray.hpp
*
* Abstract:
*
* Dynamic array template classes. See DynamicArrays.doc in the Specs
* directory.
*
* DynArray is a container which keeps its contents in a contiguous buffer,
* reallocating memory as necessary. It accepts an optional initial
* allocation, which is used unless it is too small to accommodate the
* elements.
*
* DynArrayIA is a cosmetic wrapper which encapsulates the intial allocation,
* allowing the dynamic array to be treated like a normal class.
*
* Revision History:
*
* 12/02/1998 davidx
* Created it.
* 02/26/1999 agodfrey
* Revamped it to use an implementation class (DynArrayImpl).
* Now the template part of it can compile to nothing, or be small enough
* to inline efficiently, so that using the template with many different
* types doesn't cause code bloat.
*
* Also, I added a version (DynArrayIA) which makes using an initial
* allocation much easier.
*
* 06/10/1999 t-wehunt
* Added AddXXAt, DeletXXAt, and InsertAt methods.
*
* Notes:
*
* 12/02/1998 davidx
* Changes from the previous version in gdiplus prototype:
* + getData: Use &dynarr[index] instead.
* + increaseCount: Use addMultiple instead (2nd variation).
* + replace: Use dynarr[index] = newItem.
* + attachData: Use dynarr.replaceWith(dynarr2).
* + constructor: No longer takes initialCapacity, use ReserveSpace instead
* + new constructor: Takes a stack array which is used for buffer (faster).
*
* 02/26/1999 agodfrey
* + Use the 'implementation class' to avoid code bloat for out-of-line
* functions.
* + GetCapacity: Unused, not useful - removed.
* + Reset: Added 'shrink' flag (default true). If it's false, Reset sets the
* count to zero but doesn't free the memory. This is preferable to
* SetCount(0).
* + Made ShrinkToSize() reuse the initial allocation. This also makes the
* growing and shrinking logic simpler - 'no initial allocation' is treated
* like an initial allocation of size zero (at memory location 'NULL').
*
* 06/10/1999 t-wehunt
* + AddXXAt, DeletXXAt, and InsertAt methods shift elements around in memory
* to keep the array contiguous.
* + CAUTION: This could cause a big performance hit if the array is very large.
* Use care when calling these methods!!!
*
\**************************************************************************/
#ifndef _DYNARRAY_HPP
#define _DYNARRAY_HPP
#include "dynArrayImpl.hpp"
template <class T> class DynArray : public DynArrayImpl
{
public:
// Constructor
//
// initalAllocation - the initial allocation, which can be global,
// static or dynamic memory (or NULL)
// allocSize - size of the initial allocation
// (0 if there is none)
// count - the initial count
//
DynArray(
T *initialAllocation,
UINT allocSize,
UINT count = 0):
DynArrayImpl(initialAllocation, allocSize, count)
{
}
// Constructor (no initial allocation)
//
DynArray(void):
DynArrayImpl(NULL, 0, 0)
{
}
// Destructor
~DynArray()
{
if (DataBuffer != InitialAllocation)
{
GpFree(DataBuffer);
}
}
// Return a pointer to the array data
// NOTE: We intentionally avoid type conversion operator here
// to reduce the chances for confusion.
T *GetDataBuffer() const
{
return static_cast<T *>(DataBuffer);
}
// Index operator
T &operator[](INT n) const
{
ASSERT(n >= 0 && (UINT)n < Count);
return GetDataBuffer()[n];
}
// First/last element of the array
T &First() const
{
ASSERT(Count > 0);
return GetDataBuffer()[0];
}
T &Last() const
{
ASSERT(Count > 0);
return GetDataBuffer()[Count-1];
}
// Number of elements in the array
INT GetCount() const
{
return Count;
}
UINT GetCapacity() const
{
return Capacity;
}
// Reset the dynamic array to empty state
//
// shrink - If FALSE, don't free the current buffer.
VOID Reset(BOOL shrink=TRUE)
{
Count = 0;
if (shrink)
{
ShrinkToSize();
}
}
// Shrink the dynamic array capacity to be just big enough
// for the number of existing elements in the array.
//
// This reuses the initial allocation if possible.
VOID ShrinkToSize()
{
DynArrayImpl::ShrinkToSize(sizeof(T));
}
// Add a new element to the end of the dynamic array
GpStatus Add(const T& newItem)
{
return DynArrayImpl::AddMultiple(sizeof(T), 1, &newItem);
}
// Add multiple items to the end of the dynamic array
GpStatus AddMultiple(const T* newItems, INT n)
{
return DynArrayImpl::AddMultiple(sizeof(T), n, newItems);
}
// Another variation of addMultiple above
//
// In this case, the data for the new elements are
// not available. Instead, we'll do the following:
// (1) reserve the space for additional elements
// (2) increase the Count by the number of additional elements
// (3) return a pointer to the first new elements
T *AddMultiple(INT n)
{
return static_cast<T *>(DynArrayImpl::AddMultiple(sizeof(T), n));
}
// Detach the data buffer from the dynamic array
// Allocates the buffer to detatch if it is the initial allocation.
GpStatus DetachData(T **buffer)
{
return DynArrayImpl::DetachData(sizeof(T), (void **)buffer);
}
// Detatch the buffer from another array, and set this array
// to point to it. NOTE: This modifies the other array.
GpStatus ReplaceWith(DynArray<T> *dynarr)
{
if (DataBuffer != InitialAllocation)
{
GpFree(DataBuffer);
}
Count = dynarr->Count;
Capacity = dynarr->Capacity;
GpStatus status = dynarr->DetachData((T**)(&DataBuffer));
if(Ok != status)
{
Count = 0;
Capacity = 0;
}
return status;
}
// More dangerous interface:
//
// These functions are alternatives to Add/AddMultiple.
// They can be used to reduce overhead, but you have to know what
// you're doing.
//
// AdjustCount/SetCount - modify the count directly, without growing or
// shrinking the array.
// ReserveSpace - grow the buffer, but don't actually add any elements to
// the array.
VOID AdjustCount(UINT addElts)
{
Count += addElts;
ASSERT(Count <= Capacity);
}
VOID SetCount(UINT count)
{
ASSERT(Count <= Capacity);
Count = count;
}
GpStatus ReserveSpace(UINT newElements, BOOL exact = FALSE)
{
return Grow(sizeof(T), newElements, exact);
}
};
// DynArrayIA: A version of DynArray which encapsulates the initial allocation.
//
// For example:
//
// DynArrayIA<MyType, 10> array;
//
// This declares a DynArray of MyType objects, with an initial allocation of
// 10 elements. Such a declaration can be used on the stack or in another
// object.
template <class T, int ALLOCSIZE> class DynArrayIA : public DynArray<T>
{
public:
// Constructor
//
DynArrayIA(void):
DynArray<T>(InitialAllocationBuffer, ALLOCSIZE, 0)
{
}
DynArrayIA(T * initialAllocationBuffer, UINT initialAllocationSize, UINT count = 0) :
DynArray<T>(initialAllocationBuffer, initialAllocationSize, count)
{
}
private:
T InitialAllocationBuffer[ALLOCSIZE];
};
#endif // !_DYNARRAY_HPP