2025-04-27 07:49:33 -04:00

242 lines
4.2 KiB
C++

/*++
Microsoft Windows NT RPC Name Service
Copyright (c) 1996-1997 Microsoft Corporation
Module Name:
linklist.cxx
Abstract:
This module contains definitions of non inline member functions for the
basic implementation class CLinkList.
Author:
Satish Thatte (SatishT) 08/16/95
--*/
#include <or.hxx>
// define the static members for page-based allocation
DEFINE_PAGE_ALLOCATOR(CLinkList::Link)
#if DBG
void
CLinkList::Link::IsValid()
{
if (_pNext)
{
ASSERT(!IsBadWritePtr(_pNext,sizeof(Link)));
_pNext->IsValid();
}
ASSERT(_pData);
ASSERT(!IsBadWritePtr(_pData,sizeof(IDataItem)));
}
#endif
USHORT
CLinkList::Size()
{
VALIDATE_METHOD
USHORT result = 0;
for (Link *pL = _pLnkFirst; pL != NULL; pL = pL->_pNext)
{
result++;
}
return result;
}
// this throws away duplicates
ORSTATUS
CLinkList::Merge(CLinkList& source)
{
IDataItem *pItem;
ORSTATUS status = OR_OK;
while ((status == OR_OK) && (pItem = source.Pop()))
{
status = Insert(pItem);
if (status == OR_I_DUPLICATE)
{
status = OR_OK;
}
}
return status;
}
void
CLinkList::Remove(CLinkList& NotWanted)
{
CLinkListIterator RemoveIter;
RemoveIter.Init(NotWanted);
for (
IDataItem *pItem = RemoveIter.Next();
pItem != NULL;
pItem = RemoveIter.Next()
)
{
Remove(*pItem);
}
}
ORSTATUS
CLinkList::Push(IDataItem * pData)
{
ASSERT(pData != NULL); // do not allow inssertion of NULL pointers
ORSTATUS status = OR_OK;
Link *pOldFirst = _pLnkFirst;
_pLnkFirst = new Link(pData, _pLnkFirst);
if (!_pLnkFirst)
{
_pLnkFirst = pOldFirst;
status = OR_NOMEM;
}
else
{
pData->Reference();
}
return status;
}
ORSTATUS
CLinkList::Insert(IDataItem * pData)
{
VALIDATE_METHOD
ASSERT(pData != NULL); // do not allow inssertion of NULL pointers
IDataItem *pTemp;
ORSTATUS status = OR_OK;
if (NULL != (pTemp = Find(*pData))) // Is item with this key already in list?
{
return OR_I_DUPLICATE; // We do not allow insertion of duplicate keys
}
return Push(pData);
}
IDataItem*
CLinkList::Pop()
/*++
Routine Description:
Delete first item in the CLinkList and return it
--*/
{
VALIDATE_METHOD
if (!_pLnkFirst) return NULL;
IDataItem* pResult = _pLnkFirst->_pData;
Link * oldFirst = _pLnkFirst;
_pLnkFirst = _pLnkFirst->_pNext;
delete oldFirst;
pResult->Release();
return pResult;
}
IDataItem *
CLinkList::Remove(ISearchKey& di)
/*++
Routine Description:
Remove the specified item and return it.
--*/
{
VALIDATE_METHOD
if (!_pLnkFirst) return NULL; // empty list
if (di == *(_pLnkFirst->_pData)) // Remove first item
{
return Pop();
}
Link * pLnkPrev = _pLnkFirst,
* pLnkCurr = _pLnkFirst->_pNext;
while (pLnkCurr && di != *(pLnkCurr->_pData))
{
pLnkPrev = pLnkCurr;
pLnkCurr = pLnkCurr->_pNext;
}
if (!pLnkCurr) return NULL; // not found
/* pLnkCurr contains the item to be removed and it is not the only
item in the list since it is not the first item */
pLnkPrev->_pNext = pLnkCurr->_pNext;
IDataItem * pResult = pLnkCurr->_pData;
delete pLnkCurr;
pResult->Release();
return pResult;
}
IDataItem*
CLinkList::Find(ISearchKey& di) // item to Find
/*++
Routine Description:
Unlike Remove, this method is designed to use a client-supplied
comparison function instead of pointer equality. The comparison
function is expected to behave like strcmp (returning <0 is less,
0 if equal and >0 if greater).
--*/
{
VALIDATE_METHOD
if (!_pLnkFirst) return NULL; // empty list
Link * pLnkCurr = _pLnkFirst;
while (pLnkCurr && di != *(pLnkCurr->_pData))
pLnkCurr = pLnkCurr->_pNext;
if (!pLnkCurr) return NULL; // not found
else return pLnkCurr->_pData;
}