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.
323 lines
7.6 KiB
323 lines
7.6 KiB
//+-------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1996.
|
|
//
|
|
// File: clist.hxx
|
|
//
|
|
// Contents: Class to create and maintain a singly linked list.
|
|
//
|
|
// History: 28-Jun-96 MacM Created
|
|
//
|
|
//--------------------------------------------------------------------
|
|
#ifndef __CLIST_HXX__
|
|
#define __CLIST_HXX__
|
|
|
|
typedef struct _CSLIST_NODE
|
|
{
|
|
PVOID pvData;
|
|
struct _CSLIST_NODE *pNext;
|
|
} CSLIST_NODE, *PCSLIST_NODE;
|
|
|
|
//
|
|
// Free function callback typedef. This function will delete the memory saved
|
|
// as the data in a list node on list destruction
|
|
//
|
|
typedef VOID (*FreeFunc)(PVOID);
|
|
|
|
//
|
|
// This function returns TRUE if the two items are the same, or FALSE if they
|
|
// are not
|
|
//
|
|
typedef BOOL (*CompFunc)(PVOID, PVOID);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CSList
|
|
//
|
|
// Synopsis: Singly linked list class, single threaded
|
|
//
|
|
// Methods: Insert
|
|
// InsertIfUnique
|
|
// Find
|
|
// Reset
|
|
// NextData
|
|
// Remove
|
|
// QueryCount
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
class CSList
|
|
{
|
|
public:
|
|
CSList(FreeFunc pfnFree) : _pfnFree (pfnFree),
|
|
_pHead (NULL),
|
|
_pCurrent (NULL),
|
|
_cItems (0)
|
|
{
|
|
};
|
|
|
|
inline ~CSList();
|
|
|
|
DWORD QueryCount(void) { return(_cItems);};
|
|
|
|
inline DWORD Insert(PVOID pvData);
|
|
|
|
inline DWORD InsertIfUnique(PVOID pvData,
|
|
CompFunc pfnComp);
|
|
|
|
inline PVOID Find(PVOID pvData,
|
|
CompFunc pfnComp);
|
|
|
|
inline PVOID NextData();
|
|
|
|
VOID Reset() {_pCurrent = _pHead;};
|
|
|
|
inline DWORD Remove(PVOID pData);
|
|
protected:
|
|
PCSLIST_NODE _pHead;
|
|
PCSLIST_NODE _pCurrent;
|
|
DWORD _cItems;
|
|
FreeFunc _pfnFree;
|
|
};
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------
|
|
//
|
|
// Member: CSList::~CSList
|
|
//
|
|
// Synopsis: Destructor for the CSList class
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: void
|
|
//
|
|
//+------------------------------------------------------------------
|
|
CSList::~CSList()
|
|
{
|
|
PCSLIST_NODE pNext = _pHead;
|
|
|
|
//
|
|
// We'll do this in 2 seperate, but almost identical loops, so that we
|
|
// don't have to check for a null free pointer in every loop iteration.
|
|
//
|
|
if(_pfnFree != NULL)
|
|
{
|
|
while(pNext != NULL)
|
|
{
|
|
pNext = _pHead->pNext;
|
|
(*_pfnFree)(_pHead->pvData);
|
|
delete _pHead;
|
|
_pHead = pNext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(pNext != NULL)
|
|
{
|
|
pNext = _pHead->pNext;
|
|
delete _pHead;
|
|
_pHead = pNext;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------
|
|
//
|
|
// Member: CSList::Insert
|
|
//
|
|
// Synopsis: Creates a new node at the begining of the list and
|
|
// inserts it into the list
|
|
//
|
|
//
|
|
// Arguments: [IN pvData] -- Data to insert
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
|
|
//
|
|
//+------------------------------------------------------------------
|
|
DWORD CSList::Insert(PVOID pvData)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
PCSLIST_NODE pNew = new CSLIST_NODE;
|
|
if(pNew == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
pNew->pvData = pvData;
|
|
pNew->pNext = _pHead;
|
|
_pHead = pNew;
|
|
_cItems++;
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------
|
|
//
|
|
// Member: CSList::InsertIfUnique
|
|
//
|
|
// Synopsis: Creates a new node at the begining of the list and
|
|
// inserts it into the list if the data does not already
|
|
// exist in the list. If the data does exist, nothing
|
|
// is done, but SUCCESS is returned
|
|
//
|
|
//
|
|
// Arguments: [IN pvData] -- Data to insert
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
|
|
//
|
|
//+------------------------------------------------------------------
|
|
DWORD CSList::InsertIfUnique(PVOID pvData,
|
|
CompFunc pfnComp)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
|
|
//
|
|
// First, make sure it doesn't already exist, and then insert it
|
|
//
|
|
PCSLIST_NODE pWalk = _pHead;
|
|
|
|
while(pWalk)
|
|
{
|
|
if((pfnComp)(pvData, pWalk->pvData) == TRUE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
if(pWalk == NULL)
|
|
{
|
|
dwErr = Insert(pvData);
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------
|
|
//
|
|
// Member: CSList::Find
|
|
//
|
|
// Synopsis: Locates the given data in the list, if it exists
|
|
//
|
|
// Arguments: [IN pvData] -- Data to insert
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Everything worked
|
|
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
|
|
//
|
|
//+------------------------------------------------------------------
|
|
PVOID CSList::Find(PVOID pvData,
|
|
CompFunc pfnComp)
|
|
{
|
|
PCSLIST_NODE pWalk = _pHead;
|
|
|
|
while(pWalk)
|
|
{
|
|
if((pfnComp)(pvData, pWalk->pvData) == TRUE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
return(pWalk == NULL ? NULL : pWalk->pvData);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------
|
|
//
|
|
// Member: CSList::NextData
|
|
//
|
|
// Synopsis: Returns the next data in the list
|
|
//
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: NULL -- No more items
|
|
// Pointer to next data in list on success
|
|
//
|
|
//+------------------------------------------------------------------
|
|
PVOID CSList::NextData()
|
|
{
|
|
PVOID pvRet = NULL;
|
|
if(_pCurrent != NULL)
|
|
{
|
|
pvRet = _pCurrent->pvData;
|
|
_pCurrent = _pCurrent->pNext;
|
|
}
|
|
|
|
return(pvRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------
|
|
//
|
|
// Member: CSList::Remove
|
|
//
|
|
// Synopsis: Removes the node that references the indicated data
|
|
//
|
|
// Arguments: pData -- The data in the node to remove
|
|
//
|
|
// Returns: ERROR_SUCCESS -- Success
|
|
// ERROR_INVALID_PARAMETER Node not found
|
|
//
|
|
//+------------------------------------------------------------------
|
|
DWORD CSList::Remove(PVOID pData)
|
|
{
|
|
PCSLIST_NODE pWalk = _pHead;
|
|
PCSLIST_NODE pPrev = NULL;
|
|
|
|
DWORD dwErr = ERROR_INVALID_PARAMETER;
|
|
|
|
while(pWalk)
|
|
{
|
|
if(pData == pWalk->pvData)
|
|
{
|
|
if(pPrev == NULL)
|
|
{
|
|
_pHead = pWalk->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrev->pNext = pWalk->pNext;
|
|
}
|
|
|
|
delete pWalk;
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
_cItems--;
|
|
break;
|
|
}
|
|
|
|
pPrev = pWalk;
|
|
pWalk = pWalk->pNext;
|
|
}
|
|
|
|
return(dwErr);
|
|
}
|
|
|
|
|
|
#endif // __CLIST_HXX__
|