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.
197 lines
3.4 KiB
197 lines
3.4 KiB
// ChrisPi: This is a quick attempt to create a list class that uses the
|
|
// same member functions and parameters as MFC's CObList. Only the members
|
|
// used in DCL's master objects are implemented.
|
|
|
|
#include "precomp.h"
|
|
#include <oblist.h>
|
|
|
|
#ifdef DEBUG
|
|
VOID* COBLIST::GetHead()
|
|
{
|
|
ASSERT(m_pHead);
|
|
|
|
return m_pHead->pItem;
|
|
}
|
|
#endif // ifdef DEBUG
|
|
|
|
VOID* COBLIST::GetTail()
|
|
{
|
|
ASSERT(m_pTail);
|
|
|
|
return m_pTail->pItem;
|
|
}
|
|
|
|
VOID* COBLIST::GetNext(POSITION& rPos)
|
|
{
|
|
ASSERT(rPos);
|
|
|
|
VOID* pReturn = rPos->pItem;
|
|
rPos = rPos->pNext;
|
|
|
|
return pReturn;
|
|
}
|
|
|
|
VOID* COBLIST::RemoveAt(POSITION Pos)
|
|
{
|
|
VOID* pReturn = NULL;
|
|
|
|
if (m_pHead)
|
|
{
|
|
if (m_pHead == Pos)
|
|
{
|
|
// Removing the first element in the list
|
|
|
|
m_pHead = Pos->pNext;
|
|
pReturn = Pos->pItem;
|
|
delete Pos;
|
|
|
|
if (NULL == m_pHead)
|
|
{
|
|
// Removing the only element!
|
|
m_pTail = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
POSITION pCur = m_pHead;
|
|
|
|
while (pCur && pCur->pNext)
|
|
{
|
|
if (pCur->pNext == Pos)
|
|
{
|
|
// Removing
|
|
|
|
pCur->pNext = Pos->pNext;
|
|
if (m_pTail == Pos)
|
|
{
|
|
m_pTail = pCur;
|
|
}
|
|
pReturn = Pos->pItem;
|
|
delete Pos;
|
|
}
|
|
|
|
pCur = pCur->pNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pReturn;
|
|
}
|
|
|
|
POSITION COBLIST::AddTail(VOID* pItem)
|
|
{
|
|
POSITION posRet = NULL;
|
|
|
|
if (m_pTail)
|
|
{
|
|
if (m_pTail->pNext = new COBNODE)
|
|
{
|
|
m_pTail = m_pTail->pNext;
|
|
m_pTail->pItem = pItem;
|
|
m_pTail->pNext = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(!m_pHead);
|
|
if (m_pHead = new COBNODE)
|
|
{
|
|
m_pTail = m_pHead;
|
|
m_pTail->pItem = pItem;
|
|
m_pTail->pNext = NULL;
|
|
}
|
|
}
|
|
|
|
return m_pTail;
|
|
}
|
|
|
|
void COBLIST::EmptyList()
|
|
{
|
|
while (!IsEmpty()) {
|
|
RemoveAt(GetHeadPosition());
|
|
}
|
|
}
|
|
|
|
COBLIST::~COBLIST()
|
|
{
|
|
ASSERT(IsEmpty());
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
#if 0
|
|
VOID* COBLIST::RemoveTail()
|
|
{
|
|
ASSERT(m_pHead);
|
|
ASSERT(m_pTail);
|
|
|
|
return RemoveAt(m_pTail);
|
|
}
|
|
#endif
|
|
|
|
VOID* COBLIST::RemoveHead()
|
|
{
|
|
ASSERT(m_pHead);
|
|
ASSERT(m_pTail);
|
|
|
|
return RemoveAt(m_pHead);
|
|
}
|
|
|
|
void * COBLIST::GetFromPosition(POSITION Pos)
|
|
{
|
|
void * Result = SafeGetFromPosition(Pos);
|
|
ASSERT(Result);
|
|
return Result;
|
|
}
|
|
#endif /* if DEBUG */
|
|
|
|
POSITION COBLIST::GetPosition(void* _pItem)
|
|
{
|
|
// For potential efficiency of lookup (if we switched to
|
|
// a doubly linked list), users should really store the POSITION
|
|
// of an item. For those that don't, this method is provided.
|
|
|
|
POSITION Position = m_pHead;
|
|
|
|
while (Position) {
|
|
if (Position->pItem == _pItem) {
|
|
break;
|
|
}
|
|
GetNext(Position);
|
|
}
|
|
return Position;
|
|
}
|
|
|
|
POSITION COBLIST::Lookup(void* pComparator)
|
|
{
|
|
POSITION Position = m_pHead;
|
|
|
|
while (Position) {
|
|
if (Compare(Position->pItem, pComparator)) {
|
|
break;
|
|
}
|
|
GetNext(Position);
|
|
}
|
|
return Position;
|
|
}
|
|
|
|
void * COBLIST::SafeGetFromPosition(POSITION Pos)
|
|
{
|
|
// Safe way to validate that an entry is still in the list,
|
|
// which ensures bugs that would reference deleted memory,
|
|
// reference a NULL pointer instead
|
|
// (e.g. an event handler fires late/twice).
|
|
// Note that versioning on entries would provide an additional
|
|
// safeguard against re-use of a position.
|
|
// Walk list to find entry.
|
|
|
|
POSITION PosWork = m_pHead;
|
|
|
|
while (PosWork) {
|
|
if (PosWork == Pos) {
|
|
return Pos->pItem;
|
|
}
|
|
GetNext(PosWork);
|
|
}
|
|
return NULL;
|
|
}
|