ftp.nice.ch/Attic/openStep/implementation/gnustep/sources/gstep-base-0.2.7.tgz#/gstep-base-0.2.7/src/LinkedList.m

This is LinkedList.m in view mode; [Download] [Up]

/* 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



These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.