364 lines
8.7 KiB
C++
364 lines
8.7 KiB
C++
/*
|
|
*
|
|
* NOTES:
|
|
*
|
|
* REVISIONS:
|
|
* pcy26Nov92: Removed windows.h debug stuff
|
|
* jod03Dec92: Changed the == tests to x.Equal in a couple of places.
|
|
* TSC11May93: In Equal(), cast theItemsInContainer as
|
|
* (int) theItemsInContainer
|
|
* TSC11May93: Changed operator ++ (INT) to always return a value,
|
|
* including *(NULL) !! This allows a clean compile,
|
|
* but is not a good solution. PCY SHOULD REVIEW.
|
|
* cad27Sep93: Return before delete moved
|
|
* rct01Feb94: List no longer inherits from Container
|
|
* pcy08Apr94: Trim size, use static iterators, dead code removal
|
|
* mwh05May94: #include file madness , part 2
|
|
* ajr24May94: Added some casts for Uware
|
|
* jps13Jul94: added stdlib.h for os2, changed include order
|
|
* ntf12Oct95: Added line to Next ListIterator::Next function to stop it
|
|
* bombing if theCurrentElement is NULL.
|
|
* cgm24Apr96: Current() returns NULL when theCurrentElement is NULL
|
|
*
|
|
* v-stebe 29Jul2000 Added checks for mem. alloc. failures
|
|
* (bugs #46329, #46330, #46331, #46332, #46333)
|
|
* v-stebe 29Jan2002 Removed List::Equals and ListIterator:operator++
|
|
* methods to resolve prefast errors.
|
|
*/
|
|
|
|
|
|
#define INCL_BASE
|
|
#define INCL_NOPM
|
|
|
|
#include "cdefine.h"
|
|
|
|
extern "C" {
|
|
#if (C_OS & C_OS2)
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include <string.h>
|
|
#if (C_OS & C_NLM)
|
|
#include <process.h>
|
|
#endif
|
|
}
|
|
|
|
#include "list.h"
|
|
#include "node.h"
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
List::List() :
|
|
theItemsInContainer(0),
|
|
theHead((PNode)NULL),
|
|
theTail((PNode)NULL)
|
|
{
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
List::List(PList anOldList) :
|
|
theItemsInContainer(0),
|
|
theHead((PNode)NULL),
|
|
theTail((PNode)NULL)
|
|
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
INT items_in_list = anOldList->GetItemsInContainer();
|
|
|
|
if (items_in_list == 0)
|
|
{
|
|
err = ErrLIST_EMPTY;
|
|
}
|
|
else
|
|
{
|
|
PObj current_object = (PObj)anOldList->GetHead();
|
|
ListIterator list_iterator(*anOldList);
|
|
|
|
while ((current_object) && (err == ErrNO_ERROR))
|
|
{
|
|
if (theTail == theHead)
|
|
{
|
|
theTail = new Node(current_object);
|
|
if (theTail == NULL) {
|
|
// Memory allocation error
|
|
err = ErrMEMORY;
|
|
break;
|
|
}
|
|
|
|
if (theHead == (PNode)NULL)
|
|
{
|
|
theHead = theTail;
|
|
theHead->SetNext((PNode)NULL);
|
|
theHead->SetPrev((PNode)NULL);
|
|
}
|
|
else
|
|
{
|
|
theHead->SetNext(theTail);
|
|
theTail->SetPrev(theHead);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PNode temp = new Node(current_object);
|
|
theTail->SetNext(temp);
|
|
temp->SetPrev(theTail);
|
|
theTail = temp;
|
|
}
|
|
|
|
theItemsInContainer++;
|
|
current_object = (PObj)list_iterator.Next();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
RObj List::PeekHead() const
|
|
{
|
|
return *(theHead->theNext->theData);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
VOID List::Add( RObj anObject )
|
|
{
|
|
if (theHead == (PNode)NULL)
|
|
{
|
|
theHead = new Node( &anObject);
|
|
theTail = theHead;
|
|
theItemsInContainer++;
|
|
}
|
|
else
|
|
{
|
|
PNode temp = new Node( &anObject, theHead );
|
|
if (temp != NULL) {
|
|
theHead->SetPrev(temp);
|
|
temp->SetNext(theHead);
|
|
theHead = temp;
|
|
theItemsInContainer++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
VOID List::Append( PObj anObject )
|
|
{
|
|
if (theTail == theHead)
|
|
{
|
|
theTail = new Node(anObject);
|
|
if (theTail != NULL) {
|
|
if (theHead == (PNode)NULL)
|
|
{
|
|
theHead = theTail;
|
|
theHead->SetNext((PNode)NULL);
|
|
theHead->SetPrev((PNode)NULL);
|
|
}
|
|
else
|
|
{
|
|
theHead->SetNext(theTail);
|
|
theTail->SetPrev(theHead);
|
|
}
|
|
|
|
theItemsInContainer++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PNode temp = new Node(anObject);
|
|
if (temp != NULL) {
|
|
theTail->SetNext(temp);
|
|
temp->SetPrev(theTail);
|
|
theTail = temp;
|
|
theItemsInContainer++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
PObj List::GetHead()
|
|
{
|
|
if (theHead != (PNode)NULL)
|
|
return theHead->GetData();
|
|
return (PObj)NULL;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
PObj List::GetTail()
|
|
{
|
|
if (theTail != (PNode)NULL)
|
|
return theTail->GetData();
|
|
return (PObj)NULL;
|
|
}
|
|
//------------------------------------------------------------------------
|
|
|
|
PObj List::Find( PObj anObject )
|
|
{
|
|
PNode cursor = theHead;
|
|
|
|
while ( cursor != (PNode)NULL)
|
|
{
|
|
// if (*anObject == *(cursor->GetData()) )
|
|
if (anObject->Equal(*(cursor->GetData())) )
|
|
return cursor->GetData();
|
|
cursor = cursor->GetNext();
|
|
}
|
|
return (PObj)NULL;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
PNode List::FindNode( PObj anObject )
|
|
{
|
|
PNode cursor = theHead;
|
|
|
|
while ( cursor != (PNode)NULL)
|
|
{
|
|
// if (*anObject == *(cursor->GetData()) )
|
|
if (anObject->Equal(*(cursor->GetData())) )
|
|
return cursor;
|
|
cursor = cursor->GetNext();
|
|
}
|
|
return (PNode)NULL;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
VOID List::Detach( RObj anObject )
|
|
{
|
|
PNode thenode = FindNode( &anObject );
|
|
if (thenode == (PNode)NULL)
|
|
return; // Not in the List
|
|
|
|
PNode next = thenode->theNext;
|
|
PNode prev = thenode->thePrev;
|
|
|
|
if (prev) // If there is a previous node
|
|
prev->SetNext(thenode->GetNext()); // assign its next field
|
|
else
|
|
theHead = next;
|
|
|
|
if (next)
|
|
next->SetPrev(thenode->GetPrev());
|
|
else
|
|
theTail = prev;
|
|
|
|
theItemsInContainer--;
|
|
delete thenode;
|
|
thenode = NULL;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
/*
|
|
C+
|
|
Name :FlushALL
|
|
Synop :Will delete all the NODES in the list along with the user objects
|
|
as well. The user objects in the list are held by the NODES.
|
|
*/
|
|
VOID List::FlushAll()
|
|
//c-
|
|
{
|
|
PNode current = theHead;
|
|
|
|
while( current != (PNode)NULL) //theTail )
|
|
{
|
|
PNode temp = current;
|
|
current = current->theNext;
|
|
// Delete the User Data. List is a friend of node
|
|
if(temp->theData) {
|
|
delete temp->theData;
|
|
}
|
|
delete temp; // Delete the Node now.
|
|
temp = NULL;
|
|
}
|
|
theHead = (PNode)NULL;
|
|
theTail = (PNode)NULL;
|
|
theItemsInContainer = 0;
|
|
|
|
}
|
|
|
|
|
|
VOID List::Flush()
|
|
{
|
|
// PNode current = theHead->theNext;
|
|
PNode current = theHead;
|
|
|
|
while( current != (PNode)NULL )
|
|
{
|
|
PNode temp = current;
|
|
current = current->theNext;
|
|
delete temp;
|
|
temp = NULL;
|
|
}
|
|
theHead = (PNode)NULL;
|
|
theTail = (PNode)NULL;
|
|
theItemsInContainer = 0;
|
|
|
|
}
|
|
|
|
// SRB: Removed method INT List::Equal( RObj anObject ) const
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
RListIterator List::InitIterator() const
|
|
{
|
|
return *( new ListIterator( (RList)*this ) );
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
ListIterator::ListIterator( RList aList )
|
|
{
|
|
theList = (PList)&aList;
|
|
theCurrentElement = theList->GetHeadNode();
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
RObj ListIterator::Current()
|
|
{
|
|
if (theCurrentElement)
|
|
return *(theCurrentElement->GetData());
|
|
else
|
|
return *((PObj)NULL);
|
|
}
|
|
|
|
// SRB: Removed method RObj ListIterator::operator ++ ( INT )
|
|
|
|
// SRB: Removed method RObj ListIterator::operator ++ ()
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
VOID ListIterator::Reset()
|
|
{
|
|
theCurrentElement = theList->GetHeadNode();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
PObj ListIterator:: Next()
|
|
{
|
|
|
|
//ntf12Oct95: Added next line to stop this function bombing
|
|
if (theCurrentElement == NULL) return((PObj) NULL);
|
|
|
|
PNode tmp = theCurrentElement->GetNext(); //If above if not there, could bomb
|
|
if (tmp)
|
|
{
|
|
theCurrentElement = tmp;
|
|
return theCurrentElement->GetData();
|
|
}
|
|
return (PObj)NULL;
|
|
}
|
|
|
|
|