libs-base/Source/LinkedList.m
Andrew McCallum 168f431ba9 Change "Gnustep" to "GNUstep"
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1521 72102866-910b-0410-8b05-ffd578937521
1996-05-12 00:56:10 +00:00

406 lines
9.7 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: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
Date: May 1993
This file is part of the GNUstep Base 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 <gnustep/base/LinkedList.h>
#include <gnustep/base/IndexedCollectionPrivate.h>
#include <gnustep/base/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]];
return self;
}
/* Archiving must mimic the above designated initializer */
- (void) encodeWithCoder: coder
{
id l;
[super encodeWithCoder: coder];
[coder encodeValueOfCType: @encode (typeof (_count))
at: &_count
withName: @"LinkedList count"];
FOR_COLLECTION (self, l)
{
[coder encodeObject: l
withName: @"LinkedList element"];
}
END_FOR_COLLECTION (self);
[coder encodeObjectReference: _first_link
withName: @"LinkedList first link"];
[coder encodeObjectReference: _last_link
withName: @"LinkedList last link"];
}
- initWithCoder: coder
{
int i;
// id link;
self = [super initWithCoder: coder];
[coder decodeValueOfCType: @encode (typeof (_count))
at: &_count
withName: NULL];
/* We don't really care about storing the elements decoded, because
we access them through their own link pointers. */
for (i = 0; i < _count; i++)
[coder decodeObjectAt: NULL
withName: NULL];
[coder decodeObjectAt: &_first_link
withName: NULL];
[coder decodeObjectAt: &_last_link
withName: NULL];
#if 0
/* xxx Not necessary, since the links encode this?
But should we rely on the links encoding this?
BUT! Look out: the next link pointers may not be set until
the last finishDecoding... method is run... */
FOR_COLLECTION (self, link)
{
[link setLinkedList: self];
}
END_FOR_COLLECTION (self);
#endif
return self;
}
/* 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];
}
- (void) 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];
}
- (void) 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]];
}
- (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