libs-base/Source/LinkedList.m
Andrew McCallum bf4fd7952b ([LinkedList -insertObject:after:]): When inserting first object, set
_count to 1.
([LinkedList -insertObject:before:]): Likewise.
([LinkedList -appendObject:]): Don't claim ownership here if we're
going to call -insertObject:after: later.
([LinkedList -prependObject:]): Likewise.  And renamed from
prependElement.
([LinkedList -insertObject:atIndex:]): Likewise.
([LinkedList -newEnumState]): New method.
([LinkedList -nextObjectWithEnumState:]): Overhauled.
([LinkedList -prevObjectWithEnumState:]): Likewise.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1044 72102866-910b-0410-8b05-ffd578937521
1996-03-03 01:36:41 +00:00

381 lines
9.1 KiB
Objective-C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Implementation for Objective-C LinkedList collection object
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
Date: May 1993
This file is part of the GNU Objective C Class Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <objects/LinkedList.h>
#include <objects/IndexedCollectionPrivate.h>
#include <objects/Coder.h>
@implementation LinkedList
/* This is the designated initializer of this class */
- init
{
_count = 0;
_first_link = nil;
_last_link = nil;
return self;
}
- initWithObjects: (id*)objs count: (unsigned)c
{
[self init];
while (c--)
[self prependObject: objs[c]];
}
/* Archiving must mimic the above designated initializer */
- _initCollectionWithCoder: aCoder
{
[super _initCollectionWithCoder:aCoder];
_count = 0;
_first_link = nil;
_last_link = nil;
return self;
}
- (void) _encodeContentsWithCoder: (id <Encoding>)aCoder
{
[aCoder startEncodingInterconnectedObjects];
[super _encodeContentsWithCoder:aCoder];
[aCoder finishEncodingInterconnectedObjects];
}
/* xxx See Collection _decodeContentsWithCoder:.
We shouldn't do an -addElement. finishEncodingInterconnectedObjects
should take care of all that. */
- (void) _decodeContentsWithCoder: (id <Decoding>)aCoder
{
[aCoder startDecodingInterconnectedObjects];
[super _decodeContentsWithCoder:aCoder];
[aCoder finishDecodingInterconnectedObjects];
}
/* Empty copy must empty an allocCopy'ed version of self */
- emptyCopy
{
LinkedList *copy = [super emptyCopy];
copy->_first_link = nil;
copy->_last_link = nil;
copy->_count = 0;
return copy;
}
/* This must work without sending any messages to content objects */
- (void) _empty
{
_count = 0;
_first_link = nil;
_last_link = nil;
}
/* These next four methods are the only ones that change the values of
the instance variables _count, _first_link, except for
"-init". */
- (void) removeObject: oldObject
{
assert ([oldObject linkedList] == self);
if (_first_link == oldObject)
{
if (_count > 1)
_first_link = [oldObject nextLink];
else
_first_link = nil;
}
else
[[oldObject prevLink] setNextLink:[oldObject nextLink]];
if (_last_link == oldObject)
{
if (_count > 1)
_last_link = [oldObject prevLink];
else
_first_link = nil;
}
else
[[oldObject nextLink] setPrevLink:[oldObject prevLink]];
_count--;
[oldObject setNextLink: NO_OBJECT];
[oldObject setPrevLink: NO_OBJECT];
[oldObject release];
}
- (void) insertObject: newObject after: oldObject
{
/* Make sure we actually own the oldObject. */
assert ([oldObject linkedList] == self);
/* Make sure no one else already owns the newObject. */
assert ([newObject linkedList] == NO_OBJECT);
/* Claim ownership of the newObject. */
[newObject retain];
[newObject setLinkedList: self];
/* Insert it. */
if (_count == 0)
{
_first_link = newObject;
_last_link = newObject;
_count = 1;
[newObject setNextLink: NO_OBJECT];
[newObject setPrevLink: NO_OBJECT];
}
else
{
if (oldObject == _last_link)
_last_link = newObject;
[newObject setNextLink: [oldObject nextLink]];
[newObject setPrevLink: oldObject];
[[oldObject nextLink] setPrevLink: newObject];
[oldObject setNextLink: newObject];
}
_count++;
}
- (void) insertObject: newObject before: oldObject
{
/* Make sure we actually own the oldObject. */
assert ([oldObject linkedList] == self);
/* Make sure no one else already owns the newObject. */
assert ([newObject linkedList] == NO_OBJECT);
/* Claim ownership of the newObject. */
[newObject retain];
[newObject setLinkedList: self];
/* Insert it. */
if (_count == 0)
{
_first_link = newObject;
_last_link = newObject;
_count = 1;
[newObject setNextLink: NO_OBJECT];
[newObject setPrevLink: NO_OBJECT];
}
else
{
if (oldObject == _first_link)
_first_link = newObject;
[newObject setPrevLink: [oldObject prevLink]];
[newObject setNextLink: oldObject];
[[oldObject prevLink] setNextLink: newObject];
[oldObject setPrevLink: newObject];
}
_count++;
}
- (void) replaceObject: oldObject with: newObject
{
/* Make sure we actually own the oldObject. */
assert ([oldObject linkedList] == self);
/* Make sure no one else already owns the newObject. */
assert ([newObject linkedList] == NO_OBJECT);
/* Claim ownership of the newObject. */
[newObject retain];
[newObject setLinkedList: self];
/* Do the replacement. */
if (oldObject == _first_link)
_first_link = newObject;
[newObject setNextLink:[oldObject nextLink]];
[newObject setPrevLink:[oldObject prevLink]];
[[oldObject prevLink] setNextLink:newObject];
[[oldObject nextLink] setPrevLink:newObject];
/* Release ownership of the oldObject. */
[oldObject setNextLink: NO_OBJECT];
[oldObject setPrevLink: NO_OBJECT];
[oldObject setLinkedList: NO_OBJECT];
[oldObject release];
}
/* End of methods that change the instance variables. */
- (void) appendObject: newObject
{
/* Make sure no one else already owns the newObject. */
assert ([newObject linkedList] == NO_OBJECT);
/* Insert it. */
if (_count == 0)
{
/* Claim ownership of the newObject. */
[newObject retain];
[newObject setLinkedList: self];
/* Put it in as the only node. */
_first_link = newObject;
_last_link = newObject;
_count = 1;
[newObject setNextLink: NO_OBJECT];
[newObject setPrevLink: NO_OBJECT];
}
else
[self insertObject: newObject after: _last_link];
}
- prependObject: newObject
{
/* Make sure no one else already owns the newObject. */
assert ([newObject linkedList] == NO_OBJECT);
/* Insert it. */
if (_count == 0)
{
/* Claim ownership of the newObject. */
[newObject retain];
[newObject setLinkedList: self];
/* Put it in as the only node. */
_first_link = newObject;
_last_link = newObject;
_count = 1;
[newObject setNextLink: NO_OBJECT];
[newObject setPrevLink: NO_OBJECT];
}
else
[self insertObject: newObject before: _first_link];
}
- insertObject: newObject atIndex: (unsigned)index
{
CHECK_INDEX_RANGE_ERROR(index, (_count+1));
/* Make sure no one else already owns the newObject. */
assert ([newObject linkedList] == NO_OBJECT);
/* Insert it. */
if (_count == 0)
{
/* Claim ownership of the newObject. */
[newObject retain];
[newObject setLinkedList: self];
/* Put it in as the only node. */
_first_link = newObject;
_last_link = newObject;
_count = 1;
[newObject setNextLink: NO_OBJECT];
[newObject setPrevLink: NO_OBJECT];
}
else if (index == _count)
[self insertObject: newObject after: _last_link];
else
[self insertObject:newObject before: [self objectAtIndex: index]];
return self;
}
- (void) removeObjectAtIndex: (unsigned)index
{
CHECK_INDEX_RANGE_ERROR(index, _count);
[self removeObject: [self objectAtIndex: index]];
}
- objectAtIndex: (unsigned)index
{
id <LinkedListComprising> link;
CHECK_INDEX_RANGE_ERROR(index, _count);
if (index < _count / 2)
for (link = _first_link;
index;
link = [link nextLink], index--)
;
else
for (link = _last_link, index = _count - index - 1;
index;
link = [link prevLink], index--)
;
return link;
}
- firstObject
{
return _first_link;
}
- lastObject
{
return _last_link;
}
- successorOfObject: oldObject
{
/* Make sure we actually own the oldObject. */
assert ([oldObject linkedList] == self);
return [oldObject nextLink];
}
- predecessorOfObject: oldObject
{
/* Make sure we actually own the oldObject. */
assert ([oldObject linkedList] == self);
return [oldObject prevLink];
}
- (void*) newEnumState
{
return _first_link;
}
- nextObjectWithEnumState: (void**)enumState
{
id ret;
if (!*enumState)
return nil;
ret = *enumState;
*enumState = [(id)(*enumState) nextLink];
/* *enumState points to the next object to be returned. */
return ret;
}
- prevObjectWithEnumState: (void**)enumState
{
/* *enumState points to the object returned last time. */
if (!*enumState)
return nil;
if (*enumState == _first_link)
/* enumState was just initialized from -newEnumState. */
return *enumState = _last_link;
return (id) *enumState = [(id)(*enumState) prevLink];
}
- (unsigned) count
{
return _count;
}
@end