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.
 
 
 
 
 
 

259 lines
6.6 KiB

/*
* s r t a r r a y . cpp
*
* Author: Greg Friedman
*
* Purpose: Sorted array that grows dynamically. Sorting is
* deferred until an array element is accessed.
*
* Copyright (C) Microsoft Corp. 1998.
*/
#include "pch.hxx"
#include "srtarray.h"
const long c_DefaultCapacity = 16;
//--------------------------------------------------------------------------
// CSortedArray
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// CSortedArray::Create
//--------------------------------------------------------------------------
HRESULT CSortedArray::Create(PFNSORTEDARRAYCOMPARE pfnCompare,
PFNSORTEDARRAYFREEITEM pfnFreeItem,
CSortedArray **ppArray)
{
HRESULT hr = S_OK;
if (NULL == ppArray)
return E_INVALIDARG;
CSortedArray *pArray = new CSortedArray(pfnCompare, pfnFreeItem);
if (NULL == pArray)
hr = E_OUTOFMEMORY;
else
*ppArray = pArray;
return hr;
}
//--------------------------------------------------------------------------
// CSortedArray::CSortedArray
//--------------------------------------------------------------------------
CSortedArray::CSortedArray(PFNSORTEDARRAYCOMPARE pfnCompare, PFNSORTEDARRAYFREEITEM pfnFreeItem) :
m_lLength(0),
m_lCapacity(0),
m_data(NULL),
m_pfnCompare(pfnCompare),
m_pfnFreeItem(pfnFreeItem),
m_fSorted(TRUE)
{
// nothing to do
}
//--------------------------------------------------------------------------
// CSortedArray::~CSortedArray
//--------------------------------------------------------------------------
CSortedArray::~CSortedArray(void)
{
if (NULL != m_pfnFreeItem && NULL != m_data)
{
for (long i = 0; i < m_lLength; i++)
(*m_pfnFreeItem)(m_data[i]);
}
SafeMemFree(m_data);
}
//--------------------------------------------------------------------------
// CSortedArray::GetLength
//--------------------------------------------------------------------------
long CSortedArray::GetLength(void) const
{
return m_lLength;
}
//--------------------------------------------------------------------------
// CSortedArray::GetItemAt
//--------------------------------------------------------------------------
void *CSortedArray::GetItemAt(long lIndex) const
{
if (lIndex >= m_lLength || lIndex < 0)
return NULL;
else
{
if (!m_fSorted)
_Sort();
return m_data[lIndex];
}
}
//--------------------------------------------------------------------------
// CSortedArray::Find
//--------------------------------------------------------------------------
BOOL CSortedArray::Find(void* pItem, long *plIndex) const
{
if (!m_fSorted)
_Sort();
if (NULL == plIndex || NULL == pItem)
return FALSE;
*plIndex = 0;
if (0 == m_lLength)
return FALSE;
long lLow = 0;
int result = (*m_pfnCompare)(&pItem, &m_data[lLow]);
if (result < 0)
return FALSE;
if (result == 0)
return TRUE;
long lHigh = m_lLength - 1;
*plIndex = lHigh;
result = (*m_pfnCompare)(&pItem, &m_data[lHigh]);
if (result == 0)
return TRUE;
if (result > 0)
{
*plIndex = lHigh + 1;
return FALSE;
}
while (lLow + 1 < lHigh)
{
long lMid = (lLow + lHigh) / 2;
result = (*m_pfnCompare)(&pItem, &m_data[lMid]);
if (result == 0)
{
*plIndex = lMid;
return TRUE;
}
else
{
if (result < 0)
lHigh = lMid;
else
lLow = lMid;
}
}
*plIndex = lLow + 1;
return FALSE;
}
//--------------------------------------------------------------------------
// CSortedArray::Add
//--------------------------------------------------------------------------
HRESULT CSortedArray::Add(void *pItem)
{
HRESULT hr = S_OK;
if (NULL == pItem)
return E_INVALIDARG;
if (m_lLength == m_lCapacity)
{
if (FAILED(hr = _Grow()))
goto exit;
}
// append the item to the end of the collection,
// and mark the collection as unsorted.
m_data[m_lLength++] = pItem;
m_fSorted = FALSE;
exit:
return hr;
}
//--------------------------------------------------------------------------
// CSortedArray::Remove
//--------------------------------------------------------------------------
HRESULT CSortedArray::Remove(long lIndex)
{
if (lIndex >= m_lLength)
return E_INVALIDARG;
if (!m_fSorted)
_Sort();
--m_lLength;
if (lIndex < m_lLength)
{
memcpy(&m_data[lIndex],
&m_data[lIndex + 1],
(m_lLength - lIndex) * sizeof(void*));
}
return S_OK;
}
//--------------------------------------------------------------------------
// CSortedArray::Remove
//--------------------------------------------------------------------------
HRESULT CSortedArray::Remove(void *pItem)
{
HRESULT hr = S_OK;
long lIndex = 0;
if (NULL == pItem)
return E_INVALIDARG;
if (!m_fSorted)
_Sort();
BOOL fFound = Find(pItem, &lIndex);
if (!fFound)
{
hr = E_FAIL;
goto exit;
}
hr = Remove(lIndex);
exit:
return hr;
}
//--------------------------------------------------------------------------
// CSortedArray::_Grow
//--------------------------------------------------------------------------
HRESULT CSortedArray::_Grow(void) const
{
BOOL fSuccess = FALSE;
if (0 == m_lCapacity)
{
fSuccess = MemAlloc((LPVOID*)&m_data, c_DefaultCapacity * sizeof(void*));
if (fSuccess)
m_lCapacity = c_DefaultCapacity;
}
else
{
long lNewCapacity = m_lCapacity * 2;
fSuccess = MemRealloc((LPVOID*)&m_data, lNewCapacity * sizeof(void*));
if (fSuccess)
m_lCapacity = lNewCapacity;
}
return fSuccess ? S_OK : E_OUTOFMEMORY;;
}
//--------------------------------------------------------------------------
// CSortedArray::_Sort
//--------------------------------------------------------------------------
void CSortedArray::_Sort(void) const
{
if (!m_fSorted && m_lLength > 1 && NULL != m_pfnCompare)
qsort(m_data, m_lLength, sizeof(void*), m_pfnCompare);
m_fSorted = TRUE;
return;
}