1155 lines
32 KiB
C++
1155 lines
32 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* File: dynarray.cpp
|
||
|
|
||
|
Description: Wrapper classes around the DPA_xxxxx and DSA_xxxxx functions
|
||
|
provided by the common control's library. The classes add value by
|
||
|
providing multi-threaded protection, iterators and automatic cleanup
|
||
|
semantics.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
09/03/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
#include "pch.h" // PCH
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "dynarray.h"
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::PointerList
|
||
|
|
||
|
Description: Constructor.
|
||
|
|
||
|
Arguments:
|
||
|
cItemGrow - Number of items to grow list when expansion is required.
|
||
|
Default value is 0 which causes DPA to use 8.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exception: Throws OutOfMemory.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
09/03/96 Initial creation. BrianAu
|
||
|
02/21/97 Added cItemGrow argument. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
PointerList::PointerList(
|
||
|
INT cItemGrow
|
||
|
)
|
||
|
: m_hdpa(NULL)
|
||
|
{
|
||
|
InitializeCriticalSection(&m_cs);
|
||
|
if (NULL == (m_hdpa = DPA_CreateEx(cItemGrow, NULL)))
|
||
|
{
|
||
|
DeleteCriticalSection(&m_cs);
|
||
|
throw CAllocException();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::~PointerList
|
||
|
|
||
|
Description: Destructor. Destroys the DPA and closes the mutex handle.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
PointerList::~PointerList(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
Lock();
|
||
|
if (NULL != m_hdpa)
|
||
|
DPA_Destroy(m_hdpa);
|
||
|
|
||
|
ReleaseLock();
|
||
|
DeleteCriticalSection(&m_cs);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Count
|
||
|
|
||
|
Description: Returns the number of elements in the list.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Count of elements in list.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
UINT
|
||
|
PointerList::Count(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
UINT n = 0;
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
n = DPA_GetPtrCount(m_hdpa);
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Insert
|
||
|
|
||
|
Description: Inserts a pointer into the pointer list at a given index.
|
||
|
If the index is beyond the upper bounds of the array, the array
|
||
|
is extended by one and the item is appended to the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Pointer value to add to list.
|
||
|
|
||
|
index - List index where pointer is to be inserted. All following
|
||
|
items are shifted to one index higher. The list automatically
|
||
|
grows to accomodate as required.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: OutOfMemory.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
09/03/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
VOID
|
||
|
PointerList::Insert(
|
||
|
LPVOID pvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
|
||
|
if (DPA_InsertPtr(m_hdpa, index, pvItem) < 0)
|
||
|
{
|
||
|
throw CAllocException();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Replace
|
||
|
|
||
|
Description: Replaces a pointer in the pointer list at a given index.
|
||
|
If the index is beyond the upper bounds of the array, the array
|
||
|
is extended by one and the item is appended to the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Pointer value to add to list.
|
||
|
|
||
|
index - List index where pointer is to be replaced.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Invalid index or empty container.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::Replace(
|
||
|
LPVOID pvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
|
||
|
return DPA_SetPtr(m_hdpa, index, pvItem);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Append
|
||
|
|
||
|
Description: Appends a pointer to the end of the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Pointer value to add to list.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: OutOfMemory.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
09/03/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
VOID
|
||
|
PointerList::Append(
|
||
|
LPVOID pvItem
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
//
|
||
|
// Yes, this is correct. We're "inserting" an item to append something
|
||
|
// to the list. This saves a ( count - 1 ) calculation.
|
||
|
//
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
Insert(pvItem, DPA_GetPtrCount(m_hdpa));
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Remove
|
||
|
|
||
|
Description: Removes a pointer from the list at a given index.
|
||
|
|
||
|
Arguments:
|
||
|
ppvItem - Address of variable to contain removed pointer value.
|
||
|
|
||
|
index - List index where pointer is to be removed. All following
|
||
|
items are shifted to one index lower.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FASLE - Index is invalid (or container is empty).
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::Remove(
|
||
|
LPVOID *ppvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != ppvItem));
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
*ppvItem = DPA_DeletePtr(m_hdpa, index);
|
||
|
if (NULL == *ppvItem)
|
||
|
return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::RemoveLast
|
||
|
|
||
|
Description: Removes the last pointer from the list.
|
||
|
|
||
|
Arguments:
|
||
|
ppvItem - Address of variable to contain removed pointer value.
|
||
|
All following items are shifted to one index lower.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Container is emtpy.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::RemoveLast(
|
||
|
LPVOID *ppvItem
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != ppvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
if (0 == Count())
|
||
|
return FALSE;
|
||
|
|
||
|
Remove(ppvItem, Count() - 1);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Retrieve
|
||
|
|
||
|
Description: Retrieve a pointer from the list at a given index.
|
||
|
The pointer value is merely retrieved and not removed from the list.
|
||
|
|
||
|
Arguments:
|
||
|
ppvItem - Address of variable to contain retrieved pointer value.
|
||
|
|
||
|
index - List index where pointer is to be retrieved.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Invalid index or container is empty.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::Retrieve(
|
||
|
LPVOID *ppvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != ppvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
*ppvItem = DPA_GetPtr(m_hdpa, index);
|
||
|
|
||
|
if (NULL == *ppvItem)
|
||
|
return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::RetrieveLast
|
||
|
|
||
|
Description: Retrieves the last pointer from the list.
|
||
|
|
||
|
Arguments:
|
||
|
ppvItem - Address of variable to contain retrieved pointer value.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Container is empty.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
09/03/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::RetrieveLast(
|
||
|
LPVOID *ppvItem
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != ppvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
if (0 == Count())
|
||
|
return FALSE;
|
||
|
|
||
|
Retrieve(ppvItem, Count() - 1);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::FindIndex
|
||
|
|
||
|
Description: Returns the list index associated with a given pointer
|
||
|
value. If duplicates exist, the index of the first item is returned.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Pointer value of item to be found.
|
||
|
|
||
|
pIndex - Address of index variable to hold resulting index.
|
||
|
|
||
|
Returns:
|
||
|
TRUE = Success
|
||
|
FALSE = Item not found in list.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
09/03/96 Changed returned value to BOOL. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::FindIndex(
|
||
|
LPVOID pvItem,
|
||
|
INT *pIndex
|
||
|
)
|
||
|
{
|
||
|
INT i = -1;
|
||
|
|
||
|
DBGASSERT((NULL != pIndex));
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
i = *pIndex = DPA_GetPtrIndex(m_hdpa, pvItem);
|
||
|
|
||
|
if (-1 == i)
|
||
|
return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Sort
|
||
|
|
||
|
Description: Sorts the list given a comparison function.
|
||
|
|
||
|
Arguments:
|
||
|
pfnCompare - Address of comparison callback.
|
||
|
|
||
|
lParam - 32-bit parameter passed to the callback.
|
||
|
|
||
|
Returns:
|
||
|
TRUE = Success
|
||
|
FALSE = Item not found in list.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
02/21/97 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
PointerList::Sort(
|
||
|
PFNDPACOMPARE pfnCompare,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pfnCompare));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
DBGASSERT((NULL != pfnCompare));
|
||
|
|
||
|
return DPA_Sort(m_hdpa, pfnCompare, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerList::Search
|
||
|
|
||
|
Description: Searches the list for a given item.
|
||
|
|
||
|
Arguments:
|
||
|
pvKey - Address of key item used for search.
|
||
|
|
||
|
pfnCompare - Address of comparison callback.
|
||
|
|
||
|
uOptions - Options controlling sort operation.
|
||
|
DPAS_SORTED = Array is already sorted.
|
||
|
Will use binary search.
|
||
|
DPAS_INSERTBEFORE = If no exact match is found, return index of
|
||
|
previous best match.
|
||
|
DPAS_INSERTAFTER = If no exact match is found, return index of
|
||
|
next best match.
|
||
|
|
||
|
iStart - Index of where to start search. 0 for start of list.
|
||
|
|
||
|
lParam - 32-bit parameter passed to the callback.
|
||
|
|
||
|
Returns: Index of found item or -1 if none found.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
02/21/97 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
INT
|
||
|
PointerList::Search(
|
||
|
LPVOID pvKey,
|
||
|
PFNDPACOMPARE pfnCompare,
|
||
|
UINT uOptions,
|
||
|
INT iStart,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pfnCompare));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will automatically release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdpa));
|
||
|
DBGASSERT((NULL != pvKey));
|
||
|
DBGASSERT((NULL != pfnCompare));
|
||
|
|
||
|
return DPA_Search(m_hdpa, pvKey, iStart, pfnCompare, lParam, uOptions);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerListIterator::operator =
|
||
|
|
||
|
Description: Assignment for PointerListIterator.
|
||
|
|
||
|
Arguments:
|
||
|
rhs - Reference to constant iterator that is the rhs of the assignment.
|
||
|
|
||
|
Returns:
|
||
|
Returns a reference to "this" iterator object following the assignment.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
02/27/97 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
PointerListIterator&
|
||
|
PointerListIterator::operator = (
|
||
|
const PointerListIterator& rhs
|
||
|
)
|
||
|
{
|
||
|
if (this != &rhs)
|
||
|
{
|
||
|
m_pList = rhs.m_pList;
|
||
|
m_Index = rhs.m_Index;
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: PointerListIterator::Advance
|
||
|
|
||
|
Description: Both the Next() and Prev() iterator functions call this
|
||
|
one function. It handles the actual iteration.
|
||
|
|
||
|
Arguments:
|
||
|
ppvOut - Address of pointer variable to contain the value of the
|
||
|
pointer at the "current" iterator location. The iterator is
|
||
|
advance (or retreated) after the pointer value is copied to the
|
||
|
destination.
|
||
|
|
||
|
bForward - TRUE = Advance toward end of list.
|
||
|
FALSE = Advance toward front of list.
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR - Iterator advanced. Returned pointer is valid.
|
||
|
E_FAIL - Iterator already at begining or end of list. Returned
|
||
|
pointer will be NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/14/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
PointerListIterator::Advance(
|
||
|
LPVOID *ppvOut,
|
||
|
BOOL bForward
|
||
|
)
|
||
|
{
|
||
|
LPVOID pv = NULL;
|
||
|
HRESULT hResult = NO_ERROR;
|
||
|
|
||
|
DBGASSERT((NULL != ppvOut));
|
||
|
|
||
|
m_pList->Lock();
|
||
|
if (0 < m_pList->Count() && m_Index != EndOfList)
|
||
|
{
|
||
|
//
|
||
|
// Get pointer value at index "m_Index".
|
||
|
//
|
||
|
DBGASSERT((NULL != m_pList->m_hdpa));
|
||
|
pv = DPA_GetPtr(m_pList->m_hdpa, m_Index);
|
||
|
|
||
|
if (bForward)
|
||
|
{
|
||
|
//
|
||
|
// Advance iterator index.
|
||
|
//
|
||
|
if ((UINT)(++m_Index) == m_pList->Count())
|
||
|
m_Index = EndOfList;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Retreat iterator index.
|
||
|
//
|
||
|
m_Index--; // Will be -1 (EndOfList) if currently 0.
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hResult = E_FAIL;
|
||
|
|
||
|
m_pList->ReleaseLock();
|
||
|
|
||
|
*ppvOut = pv; // Return pointer value.
|
||
|
|
||
|
return hResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::StructureList
|
||
|
|
||
|
Description: Constructor.
|
||
|
|
||
|
Arguments:
|
||
|
cbItem - Size of each item in bytes.
|
||
|
|
||
|
cItemGrow - Number of items to grow array at each expansion.
|
||
|
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: OutOfMemory
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
09/06/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
StructureList::StructureList(
|
||
|
INT cbItem,
|
||
|
INT cItemGrow
|
||
|
)
|
||
|
{
|
||
|
InitializeCriticalSection(&m_cs);
|
||
|
|
||
|
if (NULL == (m_hdsa = DSA_Create(cbItem, cItemGrow)))
|
||
|
{
|
||
|
DeleteCriticalSection(&m_cs);
|
||
|
throw CAllocException();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::~StructureList
|
||
|
|
||
|
Description: Destructor. Destroys the DSA and closes the mutex handle.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
StructureList::~StructureList(void)
|
||
|
{
|
||
|
Lock();
|
||
|
|
||
|
if (NULL != m_hdsa)
|
||
|
DSA_Destroy(m_hdsa);
|
||
|
|
||
|
ReleaseLock();
|
||
|
DeleteCriticalSection(&m_cs);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureListIterator::operator =
|
||
|
|
||
|
Description: Assignment for StructureListIterator.
|
||
|
|
||
|
Arguments:
|
||
|
rhs - Reference to constant iterator that is the rhs of the assignment.
|
||
|
|
||
|
Returns:
|
||
|
Returns a reference to "this" iterator object following the assignment.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
02/27/97 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
StructureListIterator&
|
||
|
StructureListIterator::operator = (
|
||
|
const StructureListIterator& rhs
|
||
|
)
|
||
|
{
|
||
|
if (this != &rhs)
|
||
|
{
|
||
|
m_pList = rhs.m_pList;
|
||
|
m_Index = rhs.m_Index;
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Count
|
||
|
|
||
|
Description: Returns the number of elements in the list.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Count of elements in list.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
UINT StructureList::Count(VOID)
|
||
|
{
|
||
|
UINT n = 0;
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
n = DSA_GetItemCount(m_hdsa);
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Insert
|
||
|
|
||
|
Description: Insert an item into the Structure list at a given index.
|
||
|
If the index is beyond the upper bounds of the array, the array
|
||
|
is extended by one and the item is appended to the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of item to add to list.
|
||
|
|
||
|
index - List index where item is to be inserted. All following
|
||
|
items are shifted to one index higher. The list automatically
|
||
|
grows to accomodate as required.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: OutOfMemory.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
09/06/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
VOID
|
||
|
StructureList::Insert(
|
||
|
LPVOID pvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
|
||
|
if (DSA_InsertItem(m_hdsa, index, pvItem) < 0)
|
||
|
{
|
||
|
throw CAllocException();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Replace
|
||
|
|
||
|
Description: Replaces an item in the Structure list at a given index.
|
||
|
If the index is beyond the upper bounds of the array, the array
|
||
|
is extended by one and the item is appended to the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of item to replace existing item.
|
||
|
|
||
|
index - List index where item is to be replaced.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Invalid index or empty container.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
StructureList::Replace(
|
||
|
LPVOID pvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
|
||
|
return DSA_SetItem(m_hdsa, index, pvItem);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Append
|
||
|
|
||
|
Description: Appends an item to the end of the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of item to add to list.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Exceptions: OutOfMemory.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
09/06/96 Added exception handling. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
VOID
|
||
|
StructureList::Append(
|
||
|
LPVOID pvItem
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
//
|
||
|
// Yes, this is correct. We're "inserting" an item to append something
|
||
|
// to the list. This saves a ( count - 1 ) calculation.
|
||
|
//
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
Insert(pvItem, DSA_GetItemCount(m_hdsa));
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Remove
|
||
|
|
||
|
Description: Removes an item from the list at a given index.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of buffer to receive removed item. Assumes buffer
|
||
|
is sized properly.
|
||
|
|
||
|
index - List index where item is to be removed. All following
|
||
|
items are shifted to one index lower.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Invalid index or container is empty.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
StructureList::Remove(
|
||
|
LPVOID pvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
|
||
|
if (!DSA_GetItem(m_hdsa, index, pvItem) ||
|
||
|
!DSA_DeleteItem(m_hdsa, index))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Retrieve
|
||
|
|
||
|
Description: Retrieve an item from the list at a given index.
|
||
|
The item value is merely copied and not removed from the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of buffer to receive removed item. Assumes buffer
|
||
|
is sized properly.
|
||
|
|
||
|
index - List index where item is to be retrieved.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Invalid index or empty container.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
StructureList::Retrieve(
|
||
|
LPVOID pvItem,
|
||
|
UINT index
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
|
||
|
if (!DSA_GetItem(m_hdsa, index, pvItem))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::RemoveLast
|
||
|
|
||
|
Description: Removes the last item from the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of buffer to receive removed item. Assumes buffer
|
||
|
is sized properly.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Empty container.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
StructureList::RemoveLast(
|
||
|
LPVOID pvItem
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
|
||
|
if (0 == DSA_GetItemCount(m_hdsa))
|
||
|
return FALSE;
|
||
|
|
||
|
Remove(pvItem, DSA_GetItemCount(m_hdsa) - 1);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::RetrieveLast
|
||
|
|
||
|
Description: Retrieves the last pointer from the list.
|
||
|
|
||
|
Arguments:
|
||
|
pvItem - Address of buffer to receive removed item. Assumes buffer
|
||
|
is sized properly.
|
||
|
|
||
|
Returns:
|
||
|
TRUE - Success.
|
||
|
FALSE - Empty container.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
BOOL
|
||
|
StructureList::RetrieveLast(
|
||
|
LPVOID pvItem
|
||
|
)
|
||
|
{
|
||
|
DBGASSERT((NULL != pvItem));
|
||
|
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
|
||
|
if (0 == DSA_GetItemCount(m_hdsa))
|
||
|
return FALSE;
|
||
|
|
||
|
Retrieve(pvItem, DSA_GetItemCount(m_hdsa) - 1);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureList::Clear
|
||
|
|
||
|
Description: Removes all items from the list.
|
||
|
|
||
|
Arguments: None.
|
||
|
|
||
|
Returns: Nothing.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/26/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
VOID
|
||
|
StructureList::Clear(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
AutoLockCs lock(m_cs); // Get lock on container. Will auto-release.
|
||
|
|
||
|
DBGASSERT((NULL != m_hdsa));
|
||
|
DSA_DeleteAllItems(m_hdsa);
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
/* Function: StructureListIterator::Advance
|
||
|
|
||
|
Description: Both the Next() and Prev() iterator functions call this
|
||
|
one function. It handles the actual iteration.
|
||
|
|
||
|
Arguments:
|
||
|
ppvOut - Address of pointer variable to receive the address of the
|
||
|
item at the "current" iterator location. The iterator is
|
||
|
advance (or retreated) after the pointer value is copied to the
|
||
|
destination.
|
||
|
|
||
|
bForward - TRUE = Advance toward end of list.
|
||
|
FALSE = Advance toward front of list.
|
||
|
|
||
|
Returns:
|
||
|
NO_ERROR - Iterator advanced. Returned pointer is valid.
|
||
|
E_FAIL - Iterator already at begining or end of list. Returned
|
||
|
pointer will be NULL.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Date Description Programmer
|
||
|
-------- --------------------------------------------------- ----------
|
||
|
06/24/96 Initial creation. BrianAu
|
||
|
*/
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
HRESULT
|
||
|
StructureListIterator::Advance(
|
||
|
LPVOID *ppvOut,
|
||
|
BOOL bForward
|
||
|
)
|
||
|
{
|
||
|
LPVOID pv = NULL;
|
||
|
HRESULT hResult = NO_ERROR;
|
||
|
|
||
|
DBGASSERT((NULL != ppvOut));
|
||
|
|
||
|
m_pList->Lock();
|
||
|
if (0 < m_pList->Count() && m_Index != EndOfList)
|
||
|
{
|
||
|
//
|
||
|
// Get address of item at index "m_Index".
|
||
|
//
|
||
|
DBGASSERT((NULL != m_pList->m_hdsa));
|
||
|
pv = DSA_GetItemPtr(m_pList->m_hdsa, m_Index);
|
||
|
|
||
|
if (bForward)
|
||
|
{
|
||
|
//
|
||
|
// Advance iterator index.
|
||
|
//
|
||
|
if ((UINT)(++m_Index) == m_pList->Count())
|
||
|
m_Index = EndOfList;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Retreat iterator index.
|
||
|
//
|
||
|
m_Index--; // Will be -1 (EndOfList) if currently 0.
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hResult = E_FAIL;
|
||
|
|
||
|
m_pList->ReleaseLock();
|
||
|
*ppvOut = pv; // Return pointer value.
|
||
|
|
||
|
return hResult;
|
||
|
}
|