#if !defined(_INLINE)
static char cvsid[] = "@(#)$Id: List.cpp,v 1.5 1999/05/22 13:00:54 philogelos Exp $";
static char debugFileId[] = __FILE__;
#endif
#include "Debug.hpp"
#include "LinkManager.hpp"
#include "OGuard.hpp"
#include "PGuard.hpp"
#include "containers/lists/List.hpp"
#include "containers/lists/ListNode.hpp"
#include "containers/lists/ListNodeFactory.hpp"
#include "containers/lists/DefaultListNodeFactory.hpp"
#include "containers/MutablePositionEnumeration.hpp"
#include "iter/enumerations/TypedEnumeration.hpp"
#include "iter/enumerations/EmptyEnumeration.hpp"
#include "containers/EmptyContainer.hpp"
List::List()
{
init();
setNodeFactory( new DefaultListNodeFactory() );
}
List::List( List &aSource )
{
Enumeration *en;
PGuard _self( this, this );
LGuard _source( ( const List * )&aSource, this );
init();
setNodeFactory( aSource.getNodeFactory() );
en = aSource.getValueEnumeration();
OGuard _en( en, this );
while( en -> hasMoreElements() )
{
append( en -> getNextElement() );
}
postC_( this -> equals( &aSource ) );
}
List::~List()
{
OGuard _this( this, this );
clearAll();
setCurrent( ( ListNode * ) NIL );
setTail( ( ListNode * ) NIL );
setHead( ( ListNode * ) NIL );
setNodeFactory( ( ListNodeFactory * ) NIL );
}
Position *List::getCurrentPunct() const
{
return getCurrentPosition();
}
Position *List::getAlwaysPunct() const
{
return getPositionToCurrent();
}
void List::clearAll()
{
OGuard _this( this, this );
while( !isEmpty() )
{
LinkManager::recycle( behead() );
}
}
TypedEnumeration< ListNode > *List::getNodeEnumeration() const
{
if( isEmpty() )
{
return TypedEnumeration< ListNode >::upcast( new EmptyEnumeration() );
}
else
{
return new ListNodeEnumeration( getHead(), getTail() );
}
}
boolean List::isFirst() const
{
return( getCurrent() == getHead() );
}
boolean List::isLast() const
{
return( getCurrent() == getTail() );
}
boolean List::atEnd() const
{
return( getCurrent() == ( ListNode * ) NIL );
}
void List::next() THROWS( AfterLast * )
{
OGuard _( this, this );
if( atEnd() )
{
throw
new AfterLast( "List::next() advances beyond the end of the list",
null );
}
if( ! isLast() )
{
setCurrent( getCurrent() -> getNext() );
}
else
{
setCurrent( ( ListNode * ) NIL );
}
}
void List::prev() THROWS( BeforeFirst * )
{
OGuard _( this, this );
if( isFirst() )
{
throw
new BeforeFirst( "List::prev() moves beyond the beginning of the list",
null );
}
setCurrent( getCurrent() -> getPrev() );
}
Top *List::getCurrentValue() THROWS( AfterLast * )
{
OGuard _( this, this );
if( atEnd() )
{
throw
new AfterLast( "List::getCurrentValue() requests value after the end of the list",
null );
}
return getCurrent() -> getValue();
}
Top *List::setCurrentValue( Top *aNewValue ) THROWS( AfterLast * )
{
OGuard _( this, this );
Top *oldValue;
if( atEnd() )
{
throw
new AfterLast( "List::setCurrentValue() requests value after the end of the list",
null );
}
oldValue = getCurrentValue();
OGuard _oldValue( oldValue, this );
getCurrent() -> setValue( aNewValue );
return oldValue;
}
void List::toFirst()
{
OGuard _( this, this );
setCurrent( getHead() );
postC_( isFirst() );
}
void List::toLast()
{
OGuard _( this, this );
setCurrent( getTail() );
postC_( isLast() );
}
Index List::length() const
{
OGuard _( this, this );
Index len;
if( isEmpty() )
{
return 0;
}
len = 1;
for( ListNode *spot = getHead() ;
spot != getTail() ;
spot = spot -> getNext() )
{
++len;
}
return len;
}
Top *List::car() const THROWS( EmptyContainer * )
{
OGuard _( this, this );
if( isEmpty() )
{
throw
new EmptyContainer( "List::car() of empty list",
null );
}
else
{
test_( getHead() != nil );
return( getHead() -> getValue() );
}
}
List *List::cdr() THROWS( EmptyContainer * )
{
OGuard _( this, this );
if( isEmpty() )
{
throw
new EmptyContainer( "List::cdr() of empty list",
null );
}
else
{
List *cdrCopy;
Enumeration *en;
boolean firstElement;
cdrCopy = new List();
PGuard _cdrCopy( cdrCopy, this );
en = getValueEnumeration();
OGuard _en( en, this );
firstElement = true;
while( en -> hasMoreElements() )
{
Top *value;
value = en -> getNextElement();
OGuard _value( value, this );
if( ! firstElement )
{
cdrCopy -> append( value );
}
else
{
firstElement = false;
}
}
cdrCopy -> toFirst();
return cdrCopy;
}
}
List *List::map( Map *aMap )
{
OGuard _this( this, this );
OGuard _aMap( ( Top * ) aMap, ( Top * ) this );
List *mapped;
Enumeration *en;
mapped = new List();
PGuard _mapped( mapped, this );
en = getValueEnumeration();
OGuard _en( en, this );
while( en -> hasMoreElements() )
{
Top *value;
value = en -> getNextElement();
OGuard _value( value, this );
mapped -> append( aMap -> apply( value ) );
}
mapped -> toFirst();
return mapped;
}
List *List::append( Top *aValue )
{
appendNode( getNewNode( aValue ) );
return this;
}
List *List::prepend( Top *aValue )
{
prependNode( getNewNode( aValue ) );
return this;
}
void List::insert( Top *aValue )
{
insertNode( getNewNode( aValue ) );
}
Top *List::behead() THROWS( EmptyContainer * )
{
OGuard _( this, this );
if( isEmpty() )
{
throw
new EmptyContainer( "List::behead() of empty list",
null );
}
Top *headValue;
headValue = car();
PGuard _headValue( headValue, this );
if( getHead() == getTail() )
{
setCurrent( ( ListNode *) NIL );
setTail( ( ListNode *) NIL );
setHead( ( ListNode *) NIL );
}
else
{
if( isFirst() )
{
next();
}
OGuard _head( getHead(), this );
setHead( getHead() -> getNext() );
getHead() -> getPrev() -> setNext( ( ListNode * ) NIL );
getHead() -> setPrev( ( ListNode * ) NIL );
}
return headValue;
}
Top *List::betail() THROWS( EmptyContainer * )
{
OGuard _( this, this );
if( isEmpty() )
{
throw
new EmptyContainer( "List::betail() of empty list",
null );
}
Top *tailValue;
tailValue = getTail() -> getValue();
PGuard _tailValue( tailValue, this );
if( isLast() && isFirst() )
{
setCurrent( ( ListNode *) NIL );
setTail( ( ListNode *) NIL );
setHead( ( ListNode *) NIL );
}
else
{
if( isLast() )
{
prev();
}
OGuard _tail( getTail(), this );
setTail( getTail() -> getPrev() );
getTail() -> getNext() -> setPrev( ( ListNode * ) NIL );
getTail() -> setNext( ( ListNode * ) NIL );
}
return tailValue;
}
Top *List::remove() THROWS( AfterLast * )
{
Top *value;
OGuard _( this, this );
if( atEnd() )
{
throw
new AfterLast( "List::remove() after the last element of the list",
null );
}
if( isFirst() )
{
return( behead() );
}
if( isLast() )
{
return( betail() );
}
else
{
ListNode *oldCurrent;
value = getCurrentValue();
PGuard _value( value, this );
oldCurrent = getCurrent();
OGuard _current( oldCurrent, this );
next();
oldCurrent -> getPrev() -> setNext( oldCurrent -> getNext() );
oldCurrent -> getNext() -> setPrev( oldCurrent -> getPrev() );
oldCurrent -> setPrev( ( ListNode * ) NIL );
oldCurrent -> setNext( ( ListNode * ) NIL );
return value;
}
}
ListNodeFactory *List::getNodeFactory() const
{
return factory;
}
void List::setNodeFactory( ListNodeFactory *aFactory )
{
LinkManager::move( this, factory, aFactory );
factory = aFactory;
}
boolean List::isValidNode( const ListNode *aNode ) const
{
OGuard _this( this, this );
if( isEmpty() )
{
return( aNode == null );
}
ListNode *spot = getHead();
while( true )
{
if( spot == aNode )
{
return true;
}
if( spot == getTail() )
{
break;
}
test_( spot != ( ListNode * ) NIL );
spot = spot -> getNext();
}
return false;
}
Index List::getLowBound() const
{
return 0;
}
Index List::getHighBound() const
{
return( length() );
}
void List::setCurrentAt( const Index anIndex )
{
OGuard _this( this, this );
preC_( isValidIndex( anIndex ) );
Index i;
for( toFirst(), i = 0 ; !atEnd() ; next(), ++i )
{
if( i == anIndex )
{
return;
}
}
impossible_;
}
Index List::getCurrentIndex() const
{
LGuard _this( this, this );
Index i;
ListNode *oldCurrent;
oldCurrent = getCurrent();
for( ( ( List * ) this ) -> toFirst(), i = 0 ;
!atEnd() ;
( ( List * ) this ) -> next(), ++i )
{
if( oldCurrent == getCurrent() )
{
return i;
}
}
return getCardinality();
}
MutablePositionEnumeration *List::getMutableEnumeration() const
{
return new ListEnumeration( ( List * ) this );
}
Top *List::getAt( const Index anIndex ) const
{
preC_( ( getLowBound() <= anIndex ) &&
( anIndex < getHighBound() ) );
LGuard _this( this, this );
List *pseudoThis;
Index i;
pseudoThis = ( List * ) this;
for( pseudoThis -> toFirst(), i = 0 ;
!( pseudoThis -> atEnd() ) ;
pseudoThis -> next(), ++i )
{
if( i == anIndex )
{
return pseudoThis -> getCurrentValue();
}
}
impossible_;
return nil;
}
Top *List::setAt( const Index anIndex, Top *aNewValue )
{
preC_( ( getLowBound() <= anIndex ) &&
( anIndex < getHighBound() ) );
LGuard _this( this, this );
Index i;
for( toFirst(), i = 0 ; !atEnd() ; next(), ++i )
{
if( i == anIndex )
{
return setCurrentValue( aNewValue );
}
}
impossible_;
return ( Top * ) nil;
}
PositionEnumeration *List::getEnumeration() const
{
return( getMutableEnumeration() );
}
Index List::getCardinality() const
{
return RangedContainer::getCardinality();
}
boolean List::isValid( const Position *aPosition ) const
{
preC_( aPosition != ( Position * ) NULL );
return( aPosition -> isValid() );
}
boolean List::isEmpty() const
{
return( getHead() == nil );
}
ListPosition *List::getCurrentPosition() const THROWS( AfterLast * )
{
if( atEnd() )
{
throw new AfterLast( "List::getCurrentPosition()",
null );
}
else
{
return new ListPosition( ( List * ) this,
getCurrent() );
}
}
ListCurrentPosition *List::getPositionToCurrent() const
{
return new ListCurrentPosition( this );
}
PositionFactory *List::getDefaultPositionFactory() const
{
return new ListCurrentFactory( this );
}
boolean List::canRemoveSlot( Position *aPosition ) const
{
return false;
}
void List::removeSlot( Position *aPosition )
{
impossible_;
}
ListTailFactory *List::getTailFactory() const
{
return new ListTailFactory( this );
}
ListHeadFactory *List::getHeadFactory() const
{
return new ListHeadFactory( this );
}
ListCurrentFactory *List::getCurrentFactory() const
{
return new ListCurrentFactory( this );
}
boolean List::equals( const Top *anOther ) const
{
List *other;
List *self;
self = ( List * ) this;
other = DCAST( anOther, List );
if( other == nil )
{
return false;
}
LGuard _we( self, this );
LGuard _they( other, this );
for( self -> toFirst(), other -> toFirst() ;
( ( !( self -> atEnd() ) ) &&
( !( other -> atEnd() ) ) ) ;
( self -> next(), other -> next() ) )
{
if( !( self -> getCurrentValue()
-> equals( other -> getCurrentValue() ) ) )
{
return false;
}
}
return( ( self -> atEnd() ) &&
( other -> atEnd() ) );
}
Top *List::clone() const
{
return new List( * ( List * ) this );
}
String List::toString() const
{
List *self;
self = ( List * ) this;
LGuard _( self, this );
String result;
ListNode *savedCurrent;
result = Object::toString() + String( "( ", false );
savedCurrent = self -> getCurrent();
for( self -> toFirst() ;
! ( self -> atEnd() ) ;
self -> next() )
{
if( ( self -> getCurrent() ) != getHead() )
{
result = result + String( ", ", false );
}
if( ( self -> getCurrent() ) == savedCurrent )
{
result = result + String( "*", false );
}
result = result + ( self
-> getCurrentValue()
-> toString() );
}
result = result + String( " )", false );
return result;
}
boolean List::invariant() const
{
return( Object::invariant() &&
( equiv( getHead() == nil, getTail() == nil ) &&
ergo( getHead() == nil, getCurrent() == nil ) &&
isValidNode( getHead() ) &&
isValidNode( getTail() ) &&
ergo( !atEnd(), isValidNode( getCurrent() ) ) ) );
}
List::List( ListNode *aHead, ListNode *aTail, ListNode *aCurrent )
{
init();
setHead( aHead );
setTail( aTail );
setCurrent( aCurrent );
}
void List::init()
{
head = ( ListNode * ) NIL;
tail = ( ListNode * ) NIL;
current = ( ListNode * ) NIL;
}
String List::getClassName() const
{
return "List";
}
ListNode *List::getHead() const
{
return head;
}
ListNode *List::getTail() const
{
return tail;
}
ListNode *List::getCurrent() const
{
return current;
}
void List::setHead( ListNode *aNode )
{
LinkManager::move( this, head, aNode );
head = aNode;
}
void List::setTail( ListNode *aNode )
{
LinkManager::move( this, tail, aNode );
tail = aNode;
}
void List::setCurrent( ListNode *aNode )
{
LinkManager::move( this, current, aNode );
current = aNode;
}
ListNode *List::getNewNode( Top *aValue ) const
{
preC_( getNodeFactory() != nil );
ListNode *newNode;
newNode = getNodeFactory() -> createListNode();
test_( newNode != nil );
newNode -> setValue( aValue );
return newNode;
}
void List::appendNode( ListNode *aNode )
{
preC_( aNode != nil );
OGuard _node( aNode, this );
preC_( ! isValidNode( aNode ) );
OGuard _( this, this );
if( isEmpty() )
{
setHead( aNode );
setTail( aNode );
setCurrent( aNode );
}
else
{
getTail() -> setNext( aNode );
aNode -> setPrev( getTail() );
setTail( aNode );
}
}
void List::prependNode( ListNode *aNode )
{
preC_( aNode != nil );
preC_( ! isValidNode( aNode ) );
OGuard _( this, this );
OGuard _node( aNode, this );
if( isEmpty() )
{
setHead( aNode );
setTail( aNode );
setCurrent( aNode );
}
else
{
getHead() -> setPrev( aNode );
aNode -> setNext( getHead() );
setHead( aNode );
}
}
void List::insertNode( ListNode *aNode ) THROWS( AfterLast * )
{
OGuard _( this, this );
OGuard _node( aNode, this );
preC_( aNode != nil );
preC_( ! isValidNode( aNode ) );
if( atEnd() )
{
throw new
AfterLast( "List::insertNode after the last element of the list",
null );
}
if( isLast() )
{
appendNode( aNode );
return;
}
test_( getCurrent() -> getNext() != nil );
OGuard _current( getCurrent(), this );
OGuard _next( getCurrent() -> getNext(), this );
aNode -> setNext( getCurrent() -> getNext() );
aNode -> setPrev( getCurrent() );
getCurrent() -> getNext() -> setPrev( aNode );
getCurrent() -> setNext( aNode );
}
#if defined( TESTING )
#include "IdentityMap.hpp"
#include "containers/Stack.hpp"
boolean List::tester( int ) const
{
{
Debug::getLogger() -> log( "List Testing: constructor" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
}
{
Debug::getLogger() -> log( "List Testing: append" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
target -> append( new String( "item" ) );
Debug::getLogger() -> logObject( "Appended item: %s", target );
}
{
Debug::getLogger() -> log( "List Testing: car" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
target -> append( new String( "item" ) );
Debug::getLogger() -> logObject( "Appended item: %s", target );
Debug::getLogger() -> logObject( "car: %s", target -> car() );
}
{
Debug::getLogger() -> log( "List Testing: behead" );
List *target;
Top *hd;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
target -> append( new String( "item" ) );
Debug::getLogger() -> logObject( "Appended item: %s", target );
hd = target -> behead();
OGuard _head( hd, this );
Debug::getLogger() -> logObject( "Behead: %s", hd );
Debug::getLogger() -> logObject( "Result: %s", target );
if( !( target -> isEmpty() ) )
{
Debug::getLogger() -> log( "cdr( e ) != nil" );
return false;
}
}
{
Debug::getLogger() -> log( "List Testing: car cdr" );
List *target;
Top *hd;
List *rest;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
target -> append( new String( "item" ) );
Debug::getLogger() -> logObject( "Appended item: %s", target );
hd = target -> car();
OGuard _head( hd, this );
Debug::getLogger() -> logObject( "car: %s", hd );
rest = target -> cdr();
OGuard _rest( rest, this );
Debug::getLogger() -> logObject( "cdr: %s", rest );
rest -> prepend( hd );
if( !( target -> equals( rest ) ) )
{
Debug::getLogger() -> log( "this != car + cdr" );
return false;
}
}
{
Debug::getLogger() -> log( "List Testing: cdr misc" );
List *target;
List *cdred;
target = new List();
OGuard _target( target, this );
target -> append( new Object() );
Debug::getLogger() -> logObject( target );
target -> append( new String( "#" ) );
Debug::getLogger() -> logObject( target );
target -> prepend( new String( "!" ) );
Debug::getLogger() -> logObject( target );
cdred = target;
LinkManager::reg( this, cdred );
while( ! cdred -> isEmpty() )
{
List *newCdr;
newCdr = cdred -> cdr();
LinkManager::free( this, cdred );
cdred = newCdr;
LinkManager::reg( this, cdred );
Debug::getLogger() -> logObject( cdred );
}
LinkManager::free( this, cdred );
Enumeration *en;
en = target -> getValueEnumeration();
OGuard _en( en, this );
while( en -> hasMoreElements() )
{
target -> prepend( en -> getNextElement() );
}
Debug::getLogger() -> logObject( target );
}
{
Debug::getLogger() -> log( "List Testing: copy remove append" );
List *target;
List *copy;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
for( int i = 0 ; i < 10 ; ++i )
{
target -> append( new String( i, 10 ) );
}
Debug::getLogger() -> logObject( "Filled: %s", target );
copy = new List( *target );
OGuard _copy( copy, this );
Debug::getLogger() -> logObject( "Copy: %s", copy );
target -> toFirst();
for( int j = 0 ; j < 10 ; ++j )
{
target -> append( target -> remove() );
}
Debug::getLogger() -> logObject( "Mixed: %s", target );
if( !( copy -> equals( target ) ) )
{
Debug::getLogger() -> log( "Mixed != original" );
return false;
}
}
{
Debug::getLogger() -> log( "List Testing: insert" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
for( int i = 0 ; i < 10 ; ++i )
{
target -> append( new String( i, 10 ) );
}
Debug::getLogger() -> logObject( "Filled: %s", target );
target -> toFirst();
target -> insert( new String( "inserted at head" ) );
Debug::getLogger() -> logObject( "Result: %s", target );
target -> toLast();
target -> insert( new String( "inserted at last" ) );
Debug::getLogger() -> logObject( "Result: %s", target );
}
{
Debug::getLogger() -> log( "List Testing: map" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
for( int i = 0 ; i < 10 ; ++i )
{
target -> append( new String( i, 10 ) );
}
Debug::getLogger() -> logObject( "Filled: %s", target );
if( !( target -> equals( target -> map( new IdentityMap() ) ) ) )
{
Debug::getLogger() -> log( "map(id) != this" );
return false;
}
}
{
Debug::getLogger() -> log( "List Testing: getAt length" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
int i;
for( i = 0 ; i < 10 ; ++i )
{
target -> append( new String( i, 10 ) );
}
Debug::getLogger() -> logObject( "Filled: %s", target );
i = 0;
target -> toFirst();
while( !( target -> atEnd() ) )
{
if( !( target -> getAt( i ) -> equals( target -> getCurrentValue() ) ) )
{
Debug::getLogger() -> log( "Current != list[ i ]" );
return false;
}
++i;
target -> next();
}
if( i != target -> length() )
{
Debug::getLogger() -> log( "Wrong length!" );
return false;
}
}
{
Debug::getLogger() -> log( "List Testing: setAt" );
List *matrix;
List *target;
matrix = new List();
OGuard _matrix( matrix, this );
target = new List();
OGuard _target( target, this );
int i;
for( i = 0 ; i < 10 ; ++i )
{
String *item = new String( i, 10 );
target -> append( item );
matrix -> prepend( item );
}
Debug::getLogger() -> logObject( "target Filled: %s", target );
Debug::getLogger() -> logObject( "matrix Filled: %s", matrix );
for( i = 0 ; i < ( matrix -> length() ) ; ++i )
{
target -> setAt( i, matrix -> getAt( i ) );
}
Debug::getLogger() -> logObject( "result: %s", target );
if( !( matrix -> equals( target ) ) )
{
Debug::getLogger() -> log( "Wrong setAt behavior!" );
return false;
}
}
{
Debug::getLogger() -> log( "List Testing: isValidNode" );
List *target;
target = new List();
OGuard _target( target, this );
Debug::getLogger() -> logObject( "Created fresh: %s", target );
for( int i = 0 ; i < 10 ; ++i )
{
target -> append( new String( i, 10 ) );
}
Debug::getLogger() -> logObject( "Filled: %s", target );
for( target -> toFirst() ; !( target -> atEnd() ) ; target -> next() )
{
if( !( target -> isValidNode( target -> getCurrent() ) ) )
{
Debug::getLogger() -> log( "Current is invalid!" );
return false;
}
}
}
return true;
}
#endif
ListNodeEnumeration::ListNodeEnumeration( ListNode *aFrom, ListNode *aTo )
{
OGuard _( this, this );
preC_( aFrom != nil );
preC_( aTo != nil );
LinkManager::reg( this, aFrom );
LinkManager::reg( this, aTo );
first = aFrom;
last = aTo;
reset();
}
ListNodeEnumeration::~ListNodeEnumeration()
{
LinkManager::free( this, first );
LinkManager::free( this, last );
}
ListNode *ListNodeEnumeration::getNextTypedElement()
{
OGuard _( this, this );
ListNode *value;
value = current;
current = current -> getNext();
postC_( current != nil );
return value;
}
Top *ListNodeEnumeration::getNextElement()
{
return TypedEnumeration< ListNode >::getNextElement();
}
boolean ListNodeEnumeration::hasMoreElements()
{
return( current != last );
}
void ListNodeEnumeration::reset()
{
current = first;
}
LGuard::LGuard( const List *aTarget, const Top *anOwner ) :
OGuard( aTarget, anOwner ),
list( ( List * ) aTarget ),
savedCurrent( aTarget -> getCurrent() )
{}
LGuard::~LGuard()
{
if( list -> isValidNode( savedCurrent ) )
{
list -> setCurrent( savedCurrent );
}
}
ListPosition::ListPosition( List *aContainer, ListNode *aNode ) :
PositionAdapter( aContainer )
{
preC_( aNode != nil );
LinkManager::reg( this, aNode );
node = aNode;
}
ListPosition::~ListPosition()
{
LinkManager::free( this, node );
node = ( ListNode * ) NIL;
}
Top *ListPosition::setValue( Top *aNewValue )
{
OGuard _( this, this );
preC_( isValid() );
Top *oldValue;
oldValue = node -> getValue();
PGuard _oldValue( oldValue, this );
node -> setValue( aNewValue );
return oldValue;
}
boolean ListPosition::isValid() const
{
OGuard _( this, this );
preC_( DCAST( getContainer(), List ) != nil );
return( DCAST( getContainer(), List ) -> isValidNode( node ) );
}
Top *ListPosition::getValue() const
{
OGuard _( this, this );
preC_( isValid() );
return( node -> getValue() );
}
ListEnumeration::ListEnumeration( List *aList )
{
preC_( aList != ( List * ) NIL );
LinkManager::reg( this, aList );
list = aList;
current = list -> getHead();
if( current != ( ListNode * ) NIL )
{
LinkManager::reg( this, current );
}
}
ListEnumeration::~ListEnumeration()
{
if( current != ( ListNode * ) NIL )
{
LinkManager::free( this, current );
current = ( ListNode * ) NIL;
}
LinkManager::free( this, list );
list = ( List * ) NIL;
}
MutablePosition *ListEnumeration::getNextMutablePosition() THROWS( InvalidArgument * )
{
OGuard _( this, this );
LGuard( list, this );
if( ! ( list -> isValidNode( current ) ) )
{
throw new InvalidArgument( madeInvalid, null );
}
else
{
ListNode *oldCurrent;
oldCurrent = current;
list -> setCurrent( current );
test_( ! ( list -> atEnd() ) );
list -> next();
current = list -> getCurrent();
LinkManager::move( this, oldCurrent, current );
return new ListPosition( list, oldCurrent );
}
}
boolean ListEnumeration::hasMoreElements() THROWS( InvalidArgument * )
{
OGuard _( this, this );
LGuard( list, this );
if( current == ( ListNode * ) NIL )
{
return false;
}
if( ! ( list -> isValidNode( current ) ) )
{
throw new InvalidArgument( madeInvalid, null );
}
else
{
list -> setCurrent( current );
return( ! ( list -> atEnd() ) );
}
}
String ListEnumeration::madeInvalid( "List was modified and made this enumeration invalid",
false );
ListCurrentPosition::ListCurrentPosition( const List *aContainer ) :
PositionAdapter( ( Container * ) aContainer )
{}
ListCurrentPosition::~ListCurrentPosition()
{}
Top *ListCurrentPosition::setValue( Top *aNewValue )
{
OGuard _( this, this );
preC_( isValid() );
return DCAST( getContainer(), List ) -> setCurrentValue( aNewValue );
}
boolean ListCurrentPosition::isValid () const
{
return ! ( DCAST( getContainer(), List ) -> atEnd() );
}
Top *ListCurrentPosition::getValue() const
{
OGuard _( this, this );
preC_( isValid() );
return DCAST( getContainer(), List ) -> getCurrentValue();
}
ListPositionFactory::ListPositionFactory( const List *aList )
{
preC_( aList != ( const List * ) NULL );
LinkManager::reg( ( Top * ) this, aList );
list = ( List * ) aList;
}
ListPositionFactory::~ListPositionFactory()
{
LinkManager::free( ( Top * ) this, list );
list = ( List * ) NIL;
}
MutablePosition *ListPositionFactory::createPosition()
{
return createListPosition();
}
ListTailFactory::ListTailFactory( const List *aList ) :
ListPositionFactory( aList )
{}
ListPosition *ListTailFactory::createListPosition()
{
LGuard _list( list, ( Top * ) this );
ListPosition *lastPosition;
list -> append( nil );
list -> toLast();
lastPosition = list -> getCurrentPosition();
return lastPosition;
}
ListHeadFactory::ListHeadFactory( const List *aList ) :
ListPositionFactory( aList )
{}
ListPosition *ListHeadFactory::createListPosition()
{
LGuard _list( list, this );
ListPosition *firstPosition;
list -> prepend( nil );
list -> toFirst();
firstPosition = list -> getCurrentPosition();
return firstPosition;
}
ListCurrentFactory::ListCurrentFactory( const List *aList ) :
ListPositionFactory( aList )
{}
ListPosition *ListCurrentFactory::createListPosition()
{
OGuard _list( list, this );
ListPosition *currentPosition;
if( ( list -> isEmpty() ) ||
( list -> atEnd() ) )
{
list -> append( nil );
list -> toLast();
}
else
{
list -> insert( nil );
list -> next();
}
currentPosition = list -> getCurrentPosition();
return currentPosition;
}
#if defined( USE_PER_CLASS_NEW )
#include "FixedSizeAllocator.hpp"
INLINE void *ListPosition::operator new( size_t size )
{
return getAllocator() -> allocate( ( Index ) size );
}
INLINE void ListPosition::operator delete( void *anAddress )
{
getAllocator() -> deallocate( anAddress );
}
MemoryAllocator *ListPosition::getAllocator()
{
if( allocator == ( MemoryAllocator * ) NIL )
{
allocator = new FixedSizeAllocator( sizeof( ListPosition ), 10,
"ListPosition" );
}
return allocator;
}
MemoryAllocator *ListPosition::allocator = ( MemoryAllocator * ) NIL;
#endif
#if defined(_INLINE)
#include "../src/Debug.ipp"
#endif