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
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;
|
|
}
|