dbllist.cc
//***********************************************************************
// MODULE : DblList - Class body *
// AUTHOR : Ron Chernich *
// PURPOSE: Double linked List Class (after Atkinson**2, 1990: p505). *
// Note that data is added to the list by making a byte-wise *
// copy, so take care that the source element data is , *
// or disposed of, if possible. *
// HISTORY: *
// 10-JAN-93 First (MSC/C++ 7.00) version *
// 28-JAN-93 Fixed: Delete needs to adjust current or tail gets lost *
//***********************************************************************
#include "dbllist.hh"
//////////////////////
// Initializes a new "element" for a list
// RETURNS: pointer to initialised list element
//
PDBLT DblList::create(void *pData, UINT16 nLen)
{
if ((pTemp = new DBLT) == NULL)
return NULL;
if (NULL == (pTemp->data = new unsigned char[nLen])) {
free(pTemp);
return NULL;
}
memmove(pTemp->data, pData, nLen);
pTemp->prev = pTemp->next = NULL;
pTemp->nBytes = nLen;
return pTemp;
}
/////////////
// Constructor simply Nulls pointers.
//
DblList::DblList(INT16 sort)
{
order = sort;
pBase = pCrnt = pTemp = NULL;
}
/////////////
// Destructor for a list removes all contents.
//
DblList::~DblList()
{
DblDrop();
}
/////////////
// Delete the "current" element (if any), closing up as required. The
// "current" pointer is adjusted to the following element is one exists,
// or the previous if we've just killed the tail. This may be NULL.
//
void DblList::DblDelete()
{
if (pCrnt) {
if ((pTemp = pCrnt->next) == NULL)
pTemp = pCrnt->prev;
if (pCrnt->prev == NULL)
pBase = pCrnt->next;
else
pCrnt->prev->next = pCrnt->next;
if (pCrnt->next)
pCrnt->next->prev = pCrnt->prev;
DELETE_ARRAY pCrnt->data;
delete pCrnt;
pCrnt = pTemp;
}
}
/////////////
// Deletes all elements from list and sets list pointer to virgin.
//
void DblList::DblDrop()
{
pCrnt = pBase;
while (pCrnt) {
pTemp = pCrnt->next;
DblDelete();
pCrnt = pTemp;
}
pBase = pCrnt = pTemp = NULL;
}
/////////////
// Set current record to the head of the list.
// RETURNS: pointer to first element, or NULL if list empty
//
void *DblList::DblGetHead()
{
pCrnt = pBase;
return ((pCrnt) ? pCrnt->data : NULL);
}
/////////////
// Chase through the list, head to tail (really should implement a *tail).
// RETURNS: pointer to last element, or NULL if list empty
//
void *DblList::DblGetTail()
{
pCrnt = pBase;
if (pCrnt)
while (pCrnt->next)
pCrnt = pCrnt->next;
return ((pCrnt) ? pCrnt->data : NULL);
}
/////////////
// RETURNS: pointer to element following "current", or NULL already at tail
//
void *DblList::DblGetNext()
{
if (pCrnt)
pCrnt = pCrnt->next;
return ((pCrnt) ? pCrnt->data : NULL);
}
/////////////
// RETURNS: pointer to element prior to "current", or NULL already at head
//
void *DblList::DblGetPrev()
{
if (pCrnt)
pCrnt = pCrnt->prev;
return ((pCrnt) ? pCrnt->data : NULL);
}
/////////////
// Append passed element data to the end of the list.
// *NOTE* that is possible to insert duplicate data!
// RETURNS: pointer to new element, or NULL if append failed
//
void *DblList::DblAppend(void *data, UINT16 bytes)
{
if (NULL == (pTemp = create(data, bytes)))
return NULL;
DblGetTail();
if (pCrnt == NULL)
pBase = pCrnt = pTemp;
else {
pCrnt->next = pTemp;
pTemp->prev = pCrnt;
pCrnt = pTemp;
}
return pCrnt->data;
}
/////////////
// Add passed element data to list in the order specified when this object
// was instantiated, based on binary contents of data (which can be
// anything!). *NOTE* it is possible to insert duplicate data!
// RETURNS: pointer to new element, or NULL if insert failed
//
void *DblList::DblInsert (void *data, UINT16 bytes)
{
PDBLT pHold;
DblGetHead();
if (pCrnt == NULL)
return DblAppend(data, bytes);
if (NULL == (pHold = create(data, bytes)))
return NULL;
while (pCrnt->next && (memcmp(data, pCrnt->data, bytes) == order))
pCrnt = pCrnt->next;
if ((pCrnt->next == NULL) && (memcmp(data, pCrnt->data, bytes) == order)) {
pCrnt->next = pHold;
pHold->prev = pCrnt;
pCrnt = pHold;
}
else {
pTemp = pCrnt->prev;
pHold->prev = pTemp;
pHold->next = pCrnt;
pCrnt->prev = pHold;
if (pTemp == NULL)
pBase = pHold;
else
pTemp->next = pHold;
pCrnt = pHold;
}
return pCrnt->data;
}
/********************************** EOF ***********************************/