561 lines
8.2 KiB
C++
561 lines
8.2 KiB
C++
/*++
|
|
|
|
Copyright (c) 2000, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
Author:
|
|
|
|
Savas Guven (savasg) 27-Nov-2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "stdafx.h"
|
|
|
|
//
|
|
// Initialize STATIC MEMBERS
|
|
//
|
|
|
|
const PCHAR _GENERIC_NODE::ObjectNamep = "GENERIC_NODE";
|
|
|
|
const PCHAR _CLIST::ObjectNamep = "CLIST";
|
|
|
|
|
|
|
|
|
|
_GENERIC_NODE::_GENERIC_NODE()
|
|
:Nextp(NULL),
|
|
Prevp(NULL),
|
|
iKey1(0),
|
|
iKey2(0)
|
|
{
|
|
ICQ_TRC(TM_LIST, TL_DUMP, (" GENERIC_NODE - Default Constructor"));
|
|
}
|
|
|
|
|
|
LONG
|
|
_GENERIC_NODE::CompareToMe(PGENERIC_NODE Nodep)
|
|
{
|
|
LONG KeyOne = 0;
|
|
LONG KeyTwo = 0;
|
|
|
|
if(NULL is Nodep) return -1;
|
|
|
|
if(Nodep->iKey1 is 0 && Nodep->iKey2 is 0) return 0;
|
|
|
|
if(iKey1 > Nodep->iKey1)
|
|
{
|
|
KeyOne = 1;
|
|
}
|
|
else
|
|
{
|
|
(iKey1 < Nodep->iKey1)?(KeyOne = -1):(KeyOne = 0);
|
|
}
|
|
|
|
if(this->iKey2 is 0 || Nodep->iKey2 is 0)
|
|
{
|
|
return KeyOne;
|
|
}
|
|
|
|
if(iKey2 > Nodep->iKey2)
|
|
{
|
|
KeyTwo = 1;
|
|
}
|
|
else
|
|
{
|
|
(iKey2 < Nodep->iKey2)?(KeyTwo = -1):(KeyTwo = 0);
|
|
}
|
|
|
|
|
|
if (KeyOne < 0) return -1;
|
|
|
|
if(KeyOne is 0)
|
|
{
|
|
if(KeyTwo < 0)
|
|
return -1;
|
|
else if(KeyTwo > 0)
|
|
return 1;
|
|
}
|
|
|
|
if (KeyOne > 0) return 1;
|
|
|
|
// this is the case of KeyOne == 0 and KeyTwo == 0
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
_CLIST::_CLIST()
|
|
:listHeadp(NULL),
|
|
listTailp(NULL)
|
|
{
|
|
ICQ_TRC(TM_LIST, TL_DUMP, ("CLIST - DEFAULT CONSTRUCTOR"));
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
_CLIST::~_CLIST()
|
|
{
|
|
ICQ_TRC(TM_LIST, TL_DUMP, ("CLIST - DESTRUCTOR"));
|
|
|
|
if(this->bCleanupCalled is FALSE)
|
|
{
|
|
_CLIST::ComponentCleanUpRoutine();
|
|
}
|
|
|
|
this->bCleanupCalled = FALSE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// This function is inherited from the COMPONENT_REFERENCE
|
|
// Upon Deletion of this List.. it should dereference all the
|
|
// elements still within the List.
|
|
//
|
|
void
|
|
_CLIST::ComponentCleanUpRoutine(void)
|
|
{
|
|
ICQ_TRC(TM_LIST, TL_DUMP, ("CLIST - ComponentCleanUpRoutine"));
|
|
|
|
FreeExistingNodes();
|
|
|
|
this->bCleanupCalled = TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
_CLIST::isListEmpty(VOID)
|
|
{
|
|
return (listHeadp is NULL);
|
|
}
|
|
|
|
|
|
//
|
|
// Remove the Head from the List and return - PRIVATE FUNC
|
|
//
|
|
PGENERIC_NODE
|
|
_CLIST::RemoveHead(VOID)
|
|
{
|
|
PGENERIC_NODE Nodep = NULL;
|
|
|
|
//Acquire the Lock
|
|
// this->AcquireLock();
|
|
do
|
|
{
|
|
if(!isListEmpty())
|
|
{
|
|
Nodep = listHeadp;
|
|
|
|
listHeadp = listHeadp->Nextp;
|
|
|
|
if(listHeadp != NULL)
|
|
{
|
|
listHeadp->Prevp = NULL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
} while (FALSE);
|
|
|
|
// Release the Lock
|
|
// this->ReleaseLock();
|
|
|
|
if(Nodep != NULL)
|
|
{
|
|
CLEAN_NODE(Nodep);
|
|
}
|
|
|
|
return Nodep;
|
|
}
|
|
|
|
|
|
//
|
|
// Remove the Last Element of the List. - PRIVATE FUNC
|
|
//
|
|
PGENERIC_NODE
|
|
_CLIST::RemoveTail(VOID)
|
|
{
|
|
PGENERIC_NODE Nodep = NULL;
|
|
|
|
// this->AcquireLock();
|
|
|
|
do
|
|
{
|
|
if(!isListEmpty())
|
|
{
|
|
Nodep = listTailp;
|
|
|
|
listTailp = listTailp->Prevp;
|
|
|
|
if(listTailp != NULL)
|
|
{
|
|
listTailp->Nextp = NULL;
|
|
}
|
|
else if(Nodep is listHeadp)
|
|
{
|
|
listHeadp = listTailp;
|
|
}
|
|
|
|
break;
|
|
}
|
|
} while (FALSE);
|
|
|
|
// this->ReleaseLock();
|
|
|
|
if(Nodep != NULL)
|
|
{
|
|
CLEAN_NODE(Nodep);
|
|
}
|
|
|
|
return Nodep;
|
|
}
|
|
|
|
|
|
//
|
|
// Inserts node into the tail without looking at the keys. - PRIVATE - FUNC
|
|
//
|
|
VOID
|
|
_CLIST::InsertTail(PGENERIC_NODE Nodep)
|
|
{
|
|
|
|
// this->AcquireLock();
|
|
|
|
do
|
|
{
|
|
if(listTailp is NULL)
|
|
{
|
|
listHeadp = listTailp = Nodep;
|
|
Nodep->Nextp = NULL;
|
|
Nodep->Prevp = NULL;
|
|
break;
|
|
}
|
|
|
|
Nodep->Prevp = listTailp;
|
|
|
|
listTailp->Nextp = Nodep;
|
|
|
|
listTailp = Nodep;
|
|
} while (FALSE);
|
|
|
|
// this->ReleaseLock();
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Inserts a node in to the head without looking at the keys. - PRIVATE FUNC
|
|
//
|
|
VOID
|
|
_CLIST::InsertHead(PGENERIC_NODE Nodep)
|
|
{
|
|
|
|
// this->AcquireLock();
|
|
|
|
do
|
|
{
|
|
if(listHeadp is NULL)
|
|
{
|
|
listHeadp = listTailp = Nodep;
|
|
|
|
Nodep->Prevp = NULL;
|
|
|
|
Nodep->Nextp = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
Nodep->Nextp = listHeadp;
|
|
|
|
listHeadp->Prevp = Nodep;
|
|
|
|
listHeadp = Nodep;
|
|
|
|
} while (FALSE);
|
|
|
|
// this->ReleaseLock();
|
|
}
|
|
|
|
//
|
|
// Inserts the Node as sorted. - PUBLIC
|
|
//
|
|
VOID
|
|
_CLIST::InsertSorted(
|
|
PGENERIC_NODE Nodep
|
|
)
|
|
{
|
|
PGENERIC_NODE NodePivotp = NULL;
|
|
|
|
this->AcquireLock();
|
|
|
|
do
|
|
{
|
|
|
|
if(!isListEmpty())
|
|
{
|
|
for(NodePivotp = listHeadp;
|
|
NodePivotp != NULL;
|
|
NodePivotp = NodePivotp->Nextp)
|
|
{
|
|
if(NodePivotp->CompareToMe(Nodep) <= 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else // No elements just bang it in.
|
|
{
|
|
listHeadp = listTailp = Nodep;
|
|
break;
|
|
}
|
|
|
|
// then insert here.
|
|
if(NodePivotp is listHeadp)
|
|
{
|
|
this->InsertHead(Nodep);
|
|
}
|
|
else if (NodePivotp is NULL)
|
|
{
|
|
this->InsertTail(Nodep);
|
|
}
|
|
else // add prior to Pivot
|
|
{
|
|
Nodep->Prevp = NodePivotp->Prevp;
|
|
Nodep->Nextp = NodePivotp;
|
|
NodePivotp->Prevp = Nodep;
|
|
}
|
|
} while(FALSE);
|
|
|
|
REF_COMPONENT( Nodep, eRefList );
|
|
|
|
this->ReleaseLock();
|
|
}
|
|
|
|
|
|
//
|
|
// Search a Node with the Given Keys.
|
|
// if there is no such node then return NULL - PUBLIC
|
|
//
|
|
PGENERIC_NODE
|
|
_CLIST::SearchNodeKeys
|
|
(
|
|
ULONG iKey1,
|
|
ULONG iKey2
|
|
)
|
|
{
|
|
GENERIC_NODE TempNode;
|
|
PGENERIC_NODE NodePivotp = NULL;
|
|
|
|
TempNode.iKey1 = iKey1;
|
|
TempNode.iKey2 = iKey2;
|
|
|
|
this->AcquireLock();
|
|
|
|
if(!isListEmpty())
|
|
{
|
|
for(NodePivotp = listHeadp;
|
|
NodePivotp != NULL;
|
|
NodePivotp = NodePivotp->Nextp)
|
|
{
|
|
if(NodePivotp->CompareToMe(&TempNode) is 0)
|
|
{
|
|
this->ReleaseLock();
|
|
|
|
return NodePivotp;
|
|
}
|
|
}
|
|
}
|
|
|
|
this->ReleaseLock();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Remove the node with the given Keys from the List.
|
|
//
|
|
// Note that SearchKey acquires and releases the Lock once
|
|
// we should never Acquire Lock s around functions which holds and
|
|
// releases them.
|
|
// this will cause the release of the lock two times which is a wrong
|
|
// operation - PUBLIC
|
|
//
|
|
PGENERIC_NODE
|
|
_CLIST::RemoveSortedKeys
|
|
(
|
|
ULONG iKey1,
|
|
ULONG iKey2
|
|
)
|
|
{
|
|
PGENERIC_NODE GNp = SearchNodeKeys(iKey1, iKey2);
|
|
PGENERIC_NODE EX_Prevp = NULL;
|
|
PGENERIC_NODE EX_Nextp = NULL;
|
|
|
|
this->AcquireLock();
|
|
do
|
|
{
|
|
|
|
if(GNp != NULL)
|
|
{
|
|
|
|
if(GNp is listHeadp)
|
|
{
|
|
RemoveHead();
|
|
}
|
|
else if(GNp is listTailp)
|
|
{
|
|
RemoveTail();
|
|
}
|
|
else if(!isListEmpty())
|
|
{
|
|
EX_Prevp = GNp->Prevp;
|
|
EX_Nextp = GNp->Nextp;
|
|
|
|
// ASSERT(EX_Prevp);
|
|
EX_Prevp->Nextp = EX_Nextp;
|
|
// ASSERT(EX_Nextp);
|
|
EX_Nextp->Prevp = EX_Prevp;
|
|
|
|
}
|
|
|
|
CLEAN_NODE( GNp );
|
|
|
|
STOP_COMPONENT( GNp );
|
|
|
|
DEREF_COMPONENT( GNp, eRefList );
|
|
}
|
|
|
|
} while(FALSE);
|
|
|
|
this->ReleaseLock();
|
|
|
|
return GNp;
|
|
}
|
|
|
|
//
|
|
// PUBLIC
|
|
//
|
|
PGENERIC_NODE
|
|
_CLIST::RemoveNodeFromList(PGENERIC_NODE Pivotp)
|
|
{
|
|
PGENERIC_NODE Nodep = NULL, EX_Prevp = NULL, EX_Nextp = NULL;
|
|
|
|
if(Pivotp is NULL) return NULL;
|
|
|
|
this->AcquireLock();
|
|
|
|
do
|
|
{
|
|
|
|
for(Nodep = listHeadp;
|
|
Nodep != NULL;
|
|
Nodep = Nodep->Nextp)
|
|
{
|
|
if(Nodep is Pivotp)
|
|
{
|
|
if(Nodep is listHeadp)
|
|
{
|
|
RemoveHead();
|
|
}
|
|
else if(Nodep is listTailp)
|
|
{
|
|
RemoveTail();
|
|
}
|
|
else if(!isListEmpty())
|
|
{
|
|
EX_Prevp = Nodep->Prevp;
|
|
EX_Nextp = Nodep->Nextp;
|
|
|
|
// ASSERT(EX_Prevp);
|
|
EX_Prevp->Nextp = EX_Nextp;
|
|
// ASSERT(EX_Nextp);
|
|
EX_Nextp->Prevp = EX_Prevp;
|
|
|
|
}
|
|
|
|
CLEAN_NODE( Nodep );
|
|
|
|
STOP_COMPONENT( Nodep );
|
|
|
|
DEREF_COMPONENT( Nodep, eRefList );
|
|
|
|
break;
|
|
}
|
|
}
|
|
} while (FALSE);
|
|
|
|
this->ReleaseLock();
|
|
|
|
return Nodep;
|
|
}
|
|
|
|
//
|
|
// POP is as the stack operation POP would be.. it returns the HEAD of the List
|
|
// PUBLIC FUNCTION
|
|
//
|
|
PGENERIC_NODE
|
|
_CLIST::Pop()
|
|
{
|
|
PGENERIC_NODE Nodep = NULL;
|
|
|
|
this->AcquireLock();
|
|
|
|
Nodep = this->RemoveHead();
|
|
|
|
if(Nodep != NULL)
|
|
{
|
|
DEREF_COMPONENT( Nodep, eRefList );
|
|
}
|
|
|
|
this->ReleaseLock();
|
|
|
|
return Nodep;
|
|
}
|
|
|
|
|
|
//
|
|
// PRIVATE FUNC
|
|
//
|
|
VOID
|
|
_CLIST::FreeExistingNodes()
|
|
{
|
|
PGENERIC_NODE Nodep;
|
|
|
|
ICQ_TRC(TM_LIST, TL_TRACE, ("CLIST - FreeExistingNodes "));
|
|
|
|
for(Nodep = listHeadp;
|
|
Nodep != NULL;
|
|
Nodep = listHeadp)
|
|
{
|
|
// take Nodep out of List.
|
|
listHeadp = Nodep->Nextp;
|
|
|
|
if(listHeadp != NULL)
|
|
{
|
|
listHeadp->Prevp = Nodep->Prevp;
|
|
}
|
|
|
|
CLEAN_NODE(Nodep);
|
|
|
|
STOP_COMPONENT(Nodep);
|
|
|
|
DEREF_COMPONENT( Nodep, eRefList);
|
|
}
|
|
|
|
listHeadp = NULL;
|
|
listTailp = NULL;
|
|
}
|
|
|