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.
 
 
 
 
 
 

589 lines
15 KiB

/***************************************************************************\
*
* File: Array.inl
*
* History:
* 1/04/2000: JStall: Created
*
* Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
#if !defined(BASE__Array_inl__INCLUDED)
#define BASE__Array_inl__INCLUDED
#include "SimpleHeap.h"
/***************************************************************************\
*
* class GArrayS
*
\***************************************************************************/
//------------------------------------------------------------------------------
template <class T, class heap>
inline
GArrayS<T, heap>::GArrayS() : m_aT(NULL)
{
//
// All elements in GArrayS<T, heap> must be at least sizeof(int) large. This is
// because of the design that stores the size in the element preceeding the
// data for the array.
//
AssertMsg(sizeof(T) >= sizeof(int), "Ensure minimum element size");
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline
GArrayS<T, heap>::~GArrayS()
{
RemoveAll();
}
//------------------------------------------------------------------------------
template <class T, class heap>
BOOL
GArrayS<T, heap>::IsEmpty() const
{
return m_aT == NULL;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline void *
GArrayS<T, heap>::GetRawData(BOOL fCheckNull) const
{
if (fCheckNull) {
//
// Need to check if array is allocated
//
if (m_aT != NULL) {
return (void *) (&m_aT[-1]);
} else {
return NULL;
}
} else {
//
// Blindly return the size
//
AssertMsg(m_aT != NULL, "Array must be allocated if not checking");
return &m_aT[-1];
}
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline void
GArrayS<T, heap>::SetRawSize(int cNewItems)
{
//
// Store the size before the array data. This function should only be
// called when an array is allocated (and thus have a non-zero size).
//
AssertMsg(cNewItems > 0, "Must specify a positive number of items");
AssertMsg(m_aT != NULL, "Must allocate range to set number of items");
int * pnSize = (int *) GetRawData(FALSE);
*pnSize = cNewItems;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline int
GArrayS<T, heap>::GetSize() const
{
if (m_aT != NULL) {
int * pnSize = (int *) GetRawData(FALSE);
int cItems = *pnSize;
AssertMsg(cItems >= 1, "Must have at least one item");
return cItems;
} else {
return 0;
}
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayS<T, heap>::SetSize(int cItems)
{
AssertMsg(cItems >= 0, "Must have valid size");
int cSize = GetSize();
if (cSize == cItems) {
return TRUE;
}
if (cItems == 0) {
RemoveAll();
return TRUE;
} else {
return Resize(cItems, cSize);
}
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline int
GArrayS<T, heap>::Add(const T & t)
{
int idxAdd = GetSize();
if (!Resize(idxAdd + 1, idxAdd)) {
return -1;
}
SetAtIndex(idxAdd, t);
return idxAdd;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayS<T, heap>::InsertAt(int idxItem, const T & t)
{
AssertMsg(idxItem <= GetSize(), "Check index");
// Actually may need to increase the size by one and shift everything
// down
int idxAdd = GetSize();
if (!Resize(idxAdd + 1, idxAdd)) {
return FALSE;
}
int cbMove = (idxAdd - idxItem) * sizeof(T);
if (cbMove > 0) {
MoveMemory(&m_aT[idxItem + 1], &m_aT[idxItem], cbMove);
}
SetAtIndex(idxItem, t);
return TRUE;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayS<T, heap>::Remove(const T & t)
{
int idxItem = Find(t);
if(idxItem == -1) {
return FALSE;
}
return RemoveAt(idxItem);
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayS<T, heap>::RemoveAt(int idxItem)
{
int cItems = GetSize();
AssertMsg((idxItem < cItems) && (cItems >= 0), "Ensure valid index");
m_aT[idxItem].~T();
cItems--;
if (cItems > 0) {
//
// Found the element, so we need to splice it out of the array. We
// can not just Realloc() the buffer b/c we need to slide all
// property data after this down one. This means that we have to
// allocate a new buffer. If we are unable to allocate a temporary
// buffer, we can go ahead and just use the existing buffer, but we
// won't be able to free any memory.
//
if (idxItem < cItems) {
MoveMemory((void*)&m_aT[idxItem], (void*)&m_aT[idxItem + 1], (cItems - idxItem) * sizeof(T));
}
T * rgNewData = (T *) ContextRealloc(heap::GetHeap(), GetRawData(FALSE), (cItems + 1) * sizeof(T));
if (rgNewData != NULL) {
m_aT = &rgNewData[1];
}
SetRawSize(cItems);
} else {
ContextFree(heap::GetHeap(), GetRawData(FALSE));
m_aT = NULL;
}
return TRUE;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline void
GArrayS<T, heap>::RemoveAll()
{
if(m_aT != NULL) {
int cItems = GetSize();
for(int i = 0; i < cItems; i++) {
m_aT[i].~T();
}
ContextFree(heap::GetHeap(), GetRawData(FALSE));
m_aT = NULL;
}
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline T &
GArrayS<T, heap>::operator[] (int idxItem) const
{
Assert(idxItem >= 0 && idxItem < GetSize());
return m_aT[idxItem];
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline T *
GArrayS<T, heap>::GetData() const
{
return m_aT;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline void
GArrayS<T, heap>::SetAtIndex(int idxItem, const T & t)
{
Assert(idxItem >= 0 && (idxItem < GetSize()));
placement_copynew(&m_aT[idxItem], T, t);
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline int
GArrayS<T, heap>::Find(const T & t) const
{
int cItems = GetSize();
for(int i = 0; i < cItems; i++) {
if(m_aT[i] == t) {
return i;
}
}
return -1; // not found
}
/***************************************************************************\
*
* GArrayS<T, heap>::Resize()
*
* Resize() changes the size of the array to a non-zero number of elements.
*
* NOTE: This function has been specifically written for the GArrayS<T, heap>
* class and has slightly different behavior that GArrayF<T, heap>::Resize().
*
\***************************************************************************/
template <class T, class heap>
inline BOOL
GArrayS<T, heap>::Resize(
IN int cItems, // New number of items
IN int cSize) // Current size
{
AssertMsg(cItems > 0, "Must have non-zero and positive number of items");
AssertMsg(cItems != cSize, "Must have a different size");
if (cItems < cSize) {
//
// Making the array smaller, so need to destruct the objects we are
// getting rid of.
//
AssertMsg(m_aT != NULL, "Should have data allocated");
for(int i = cItems; i < cSize; i++) {
m_aT[i].~T();
}
}
//
// Resize the array and store the new size.
//
T * aT;
aT = (T *) ContextRealloc(heap::GetHeap(), GetRawData(TRUE), (cItems + 1) * sizeof(T));
if(aT == NULL) {
AssertMsg(cItems >= cSize, "Should never fail when shrinking");
return FALSE;
}
m_aT = &aT[1];
SetRawSize(cItems);
return TRUE;
}
/***************************************************************************\
*
* class GArrayBase
*
\***************************************************************************/
//------------------------------------------------------------------------------
template <class T, class heap>
inline
GArrayF<T, heap>::GArrayF() : m_aT(NULL), m_nSize(0), m_nAllocSize(0)
{
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline
GArrayF<T, heap>::~GArrayF()
{
RemoveAll();
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayF<T, heap>::IsEmpty() const
{
//
// GArrayF may have a non-NULL m_aT but a m_nSize if only Add() and Remove()
// are used, treating the array like a stack. Therefore, we must use
// m_nSize to determine if the array is "empty". To free all memory
// allocated by the array, use RemoveAll().
//
return m_nSize <= 0;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline int
GArrayF<T, heap>::GetSize() const
{
return m_nSize;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayF<T, heap>::SetSize(int cItems)
{
AssertMsg(cItems >= 0, "Must have valid size");
if (!Resize(cItems)) {
return FALSE;
}
m_nSize = cItems;
return TRUE;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline int
GArrayF<T, heap>::Add(const T & t)
{
if(m_nSize == m_nAllocSize) {
int nNewAllocSize = (m_nAllocSize == 0) ? 8 : (m_nAllocSize * 2);
if (!Resize(nNewAllocSize)) {
return -1;
}
}
int idxAdd = m_nSize;
m_nSize++;
SetAtIndex(idxAdd, t);
return idxAdd;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayF<T, heap>::InsertAt(int idxItem, const T & t)
{
AssertMsg(idxItem <= m_nSize, "Check index");
// Actually may need to increase the size by one and shift everything
// down
if (!Resize(m_nSize + 1)) {
return FALSE;
}
int cbMove = (m_nSize - idxItem) * sizeof(T);
if (cbMove > 0) {
MoveMemory(&m_aT[idxItem + 1], &m_aT[idxItem], cbMove);
}
m_nSize++;
SetAtIndex(idxItem, t);
return TRUE;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayF<T, heap>::Remove(const T & t)
{
int idxItem = Find(t);
if(idxItem == -1) {
return FALSE;
}
return RemoveAt(idxItem);
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline BOOL
GArrayF<T, heap>::RemoveAt(int idxItem)
{
AssertMsg((idxItem < m_nSize) && (idxItem >= 0), "Must specify a valid index");
if(idxItem != (m_nSize - 1)) {
m_aT[idxItem].~T();
MoveMemory((void*)&m_aT[idxItem], (void*)&m_aT[idxItem + 1], (m_nSize - (idxItem + 1)) * sizeof(T));
}
m_nSize--;
return TRUE;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline void
GArrayF<T, heap>::RemoveAll()
{
if(m_aT != NULL) {
for(int i = 0; i < m_nSize; i++) {
m_aT[i].~T();
}
ContextFree(heap::GetHeap(), m_aT);
m_aT = NULL;
}
m_nSize = 0;
m_nAllocSize = 0;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline T &
GArrayF<T, heap>::operator[] (int idxItem) const
{
AssertMsg((idxItem < m_nSize) && (idxItem >= 0), "Must specify a valid index");
return m_aT[idxItem];
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline T *
GArrayF<T, heap>::GetData() const
{
return m_aT;
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline void
GArrayF<T, heap>::SetAtIndex(int idxItem, const T & t)
{
AssertMsg((idxItem < m_nSize) && (idxItem >= 0), "Must specify a valid index");
placement_copynew(&m_aT[idxItem], T, t);
}
//------------------------------------------------------------------------------
template <class T, class heap>
inline int
GArrayF<T, heap>::Find(const T & t) const
{
for(int i = 0; i < m_nSize; i++) {
if(m_aT[i] == t) {
return i;
}
}
return -1; // not found
}
/***************************************************************************\
*
* GArrayF<T, heap>::Resize()
*
* Resize() changes the size of the array.
*
* NOTE: This function has been specifically written for the GArrayF<T, heap>
* class and has slightly different behavior that GArrayS<T, heap>::Resize().
*
\***************************************************************************/
template <class T, class heap>
inline BOOL
GArrayF<T, heap>::Resize(int cItems)
{
if (cItems == 0) {
RemoveAll();
} else {
AssertMsg(m_nAllocSize >= m_nSize, "Ensure legal sizes");
if (cItems < m_nSize) {
//
// Making the array smaller, so need to destruct the objects we are
// getting rid of.
//
if(m_aT != NULL) {
for(int i = cItems; i < m_nSize; i++) {
m_aT[i].~T();
}
}
}
//
// Resize the array, but don't update m_nSize b/c that is the caller's
// responsibility.
//
T * aT;
aT = (T *) ContextRealloc(heap::GetHeap(), m_aT, cItems * sizeof(T));
if(aT == NULL) {
return FALSE;
}
m_nAllocSize = cItems;
m_aT = aT;
}
return TRUE;
}
#endif // BASE__Array_inl__INCLUDED