windows-nt/Source/XPSP1/NT/admin/pchealth/client/common/pfcommon/pfarray.cpp
2020-09-26 16:20:57 +08:00

319 lines
7.3 KiB
C++

/********************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
PFArray.cpp
Abstract:
dynamic array implementation. This dynamic array is NOT thread
safe.
Revision History:
DerekM modified 03/14/00
********************************************************************/
#include "stdafx.h"
#include "pfarray.h"
/////////////////////////////////////////////////////////////////////////////
// tracing
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
/////////////////////////////////////////////////////////////////////////////
// CPFArrayBase initialization & deinitialization
// **************************************************************************
CPFArrayBase::CPFArrayBase(void)
{
m_pfnAlloc = NULL;
m_pfnDelete = NULL;
m_rgpv = NULL;
m_cSlots = 0;
m_iHighest = (DWORD)-1;
}
// **************************************************************************
CPFArrayBase::~CPFArrayBase(void)
{
this->CompressArray(0, (DWORD)-1);
if (m_rgpv != NULL)
MyFree(m_rgpv, g_hPFPrivateHeap);
}
/////////////////////////////////////////////////////////////////////////////
// CAUOPropDB internal methods
// ***************************************************************************
inline HRESULT CPFArrayBase::Grow(DWORD iMinLast)
{
USE_TRACING("CPFArrayBase::SetItem");
HRESULT hr = NOERROR;
if (iMinLast >= m_cSlots || m_rgpv == NULL)
{
LPVOID *rgpv = NULL;
DWORD cSlots;
cSlots = MyMax(iMinLast + 1, 8);
cSlots = MyMax(m_cSlots * 2, cSlots);
rgpv = (LPVOID *)MyAlloc(cSlots * sizeof(LPVOID), g_hPFPrivateHeap);
VALIDATEEXPR(hr, (rgpv == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
goto done;
if (m_rgpv != NULL)
{
CopyMemory(rgpv, m_rgpv, m_cSlots * sizeof(LPVOID));
MyFree(m_rgpv);
}
m_rgpv = rgpv;
m_cSlots = cSlots;
}
done:
return hr;
}
// ***************************************************************************
inline HRESULT CPFArrayBase::CompressArray(DWORD iStart, DWORD iEnd)
{
USE_TRACING("CPFArrayBase::CompressArray");
_ASSERT(iStart < iEnd);
// don't need to do anything cuz we're already empty
if (m_iHighest == (DWORD)-1)
return NOERROR;
if (iStart <= m_iHighest)
{
DWORD i;
// note that this will also catch passing -1 for iEnd cuz (DWORD)-1
// is greater than any other DWORD value... Of course, this
// assumes that we don't have 2^32 - 1 elements. While it is
// theoretically possible to have an array that big on ia64, this
// class can't be used for it.
if (iEnd > m_iHighest + 1)
iEnd = m_iHighest + 1;
for(i = iStart; i < iEnd; i++)
{
if (m_rgpv[i] != NULL)
this->DeleteItem(m_rgpv[i]);
}
// no point in doing a move if we're not going to be moving anything
if (iEnd <= m_iHighest)
{
MoveMemory(&m_rgpv[iStart], &m_rgpv[iEnd],
(m_iHighest - iEnd + 1) * sizeof(LPVOID));
}
}
m_iHighest -= (iEnd - iStart);
return NOERROR;
}
// ***************************************************************************
HRESULT CPFArrayBase::internalCopyFrom(CPFArrayBase *prg)
{
USE_TRACING("CPFArrayBase::CopyFrom");
HRESULT hr = NOERROR;
DWORD i;
// if it's at -1, then we've deleted everything already...
if (prg->m_iHighest == (DWORD)-1)
goto done;
TESTHR(hr, this->Grow(prg->m_iHighest + 1));
if (FAILED(hr))
goto done;
for(i = 0; i < prg->m_iHighest + 1; i++)
{
m_rgpv[i] = prg->AllocItemCopy(prg->m_rgpv[i]);
VALIDATEEXPR(hr, (m_rgpv[i] == NULL), E_OUTOFMEMORY);
if (FAILED(hr))
{
this->RemoveAll();
goto done;
}
}
done:
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// CPFArrayBase exposed methods / properties
// ***************************************************************************
HRESULT CPFArrayBase::Init(DWORD cSlots)
{
USE_TRACING("CPFArrayBase::Init");
HRESULT hr = NOERROR;
VALIDATEEXPR(hr, (m_rgpv != NULL), E_FAIL);
if (FAILED(hr))
goto done;
TESTHR(hr, this->Grow(cSlots - 1));
if (FAILED(hr))
goto done;
done:
return hr;
}
// ***************************************************************************
LPVOID &CPFArrayBase::operator [](DWORD iItem)
{
USE_TRACING("CPFArrayBase::operator []");
if (iItem >= m_cSlots || m_rgpv == NULL)
{
HRESULT hr;
TESTHR(hr, this->Grow(iItem));
_ASSERT(SUCCEEDED(hr));
}
// since we have to return a reference, we can't do much about Grow failing
// which means of course that we could fault...
return m_rgpv[iItem];
}
// ***************************************************************************
HRESULT CPFArrayBase::get_Item(DWORD iItem, LPVOID *ppv)
{
USE_TRACING("CPFArrayBase::get_Item");
HRESULT hr = NOERROR;
VALIDATEPARM(hr, (ppv == NULL))
if (FAILED(hr))
goto done;
if (iItem >= m_cSlots || m_rgpv == NULL)
{
TESTHR(hr, this->Grow(iItem));
if (FAILED(hr))
goto done;
}
if (ppv != NULL)
*ppv = m_rgpv[iItem];
done:
return hr;
}
// ***************************************************************************
HRESULT CPFArrayBase::put_Item(DWORD iItem, LPVOID pv, LPVOID *ppvOld)
{
USE_TRACING("CPFArrayBase::put_Item");
HRESULT hr = NOERROR;
if (iItem >= m_cSlots || m_rgpv == NULL)
{
TESTHR(hr, this->Grow(m_iHighest + 1));
if (FAILED(hr))
goto done;
}
if (ppvOld != NULL)
*ppvOld = m_rgpv[iItem];
else if (m_rgpv[iItem] != NULL)
this->DeleteItem(m_rgpv[iItem]);
m_rgpv[iItem] = pv;
if (iItem > m_iHighest)
m_iHighest = iItem;
done:
return hr;
}
// ***************************************************************************
HRESULT CPFArrayBase::Append(LPVOID pv)
{
USE_TRACING("CPFArrayBase::Append");
HRESULT hr = NOERROR;
if (pv == NULL)
pv = NULL;
if (m_iHighest + 1 >= m_cSlots || m_rgpv == NULL)
{
TESTHR(hr, this->Grow(m_iHighest + 1));
if (FAILED(hr))
goto done;
}
m_iHighest++;
m_rgpv[m_iHighest] = pv;
done:
return hr;
}
// ***************************************************************************
HRESULT CPFArrayBase::Remove(DWORD iItem, LPVOID *ppvOld)
{
USE_TRACING("CPFArrayBase::Remove");
HRESULT hr = NOERROR;
if (iItem > m_iHighest)
goto done;
if (ppvOld != NULL)
*ppvOld = m_rgpv[iItem];
TESTHR(hr, this->CompressArray(iItem, iItem + 1));
if (FAILED(hr))
return hr;
done:
return hr;
}
// ***************************************************************************
HRESULT CPFArrayBase::RemoveAll(void)
{
USE_TRACING("CPFArrayBase::RemoveAll");
HRESULT hr = NOERROR;
// if it's at -1, then we've deleted everything already...
if (m_iHighest == (DWORD)-1)
goto done;
TESTHR(hr, this->CompressArray(0, (DWORD)-1));
if (FAILED(hr))
return hr;
done:
return hr;
}