ftp.nice.ch/pub/next/developer/resources/libraries/libcoll.930521.s.tar.gz#/libcoll-930521/LinkList.m

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

/* Implementation for Objective-C LinkList collection object

   Copyright (C) 1993 R. Andrew McCallum <mccallum@cs.rochester.edu>
   Dept. of Computer Science, U. of Rochester, Rochester, NY  14627

   This file is part of the GNU Objective-C Collection 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 <coll/LinkList.h>
#include <objc/objc-api.h>
#include <coll/IndexedCollectionPrivate.h>

@implementation LinkList (ErrorReporting)
- errorElementNotLinking: (elt)anElement inMethod: (SEL)aSel
{
  [self warning:"in %s, element=0x%x does not conform to <ListLinking>"];
  return self;
}
@end

@implementation LinkList

+ initialize
{
    if (self == [LinkList class])
	[self setVersion:-1];	/* alpha release */
    return self;
}

/* This is the designated initializer of this class */
- init
{
  [super initDescription:"@"];
  _count = 0;
  _firstLink = nil;
  return self;
}

/* Override the designated initializer for our superclass IndexedCollection
   to make sure we have object values. */
- initDescription: (const char *)description
{
  if (*description != _C_ID)
    [self error:"LinkList contents must be objects conforming to "
	  "<DoubleLinking> protocol"];
  [self init];
  return self;
}

/* These next four methods are the only ones that change the values of
   the instance variables _count, _firstLink, except for
   "-initDescription:". */

- (elt) removeElement: (elt)oldElement
{
  if (_firstLink == oldElement.id_t)
    {
      if (_count > 1)
	_firstLink = [oldElement.id_t nextLink];
      else
	_firstLink = nil;
    }
  [[oldElement.id_t nextLink] setPrevLink:[oldElement.id_t prevLink]];
  [[oldElement.id_t prevLink] setNextLink:[oldElement.id_t nextLink]];
  _count--;
  return oldElement;
}
  
- insertElement: (elt)newElement after: (elt)oldElement
{
  if (_count == 0)
    {
      /* link to self */
      _firstLink = newElement.id_t;
      [newElement.id_t setNextLink:newElement.id_t];
      [newElement.id_t setPrevLink:newElement.id_t];
    }
  else
    {
      [newElement.id_t setNextLink:[oldElement.id_t nextLink]];
      [newElement.id_t setPrevLink:oldElement.id_t];
      [[oldElement.id_t nextLink] setPrevLink:newElement.id_t];
      [oldElement.id_t setNextLink:newElement.id_t];
    }
  _count++;
  return self;
}

- insertElement: (elt)newElement before: (elt)oldElement
{
  if (oldElement.id_t == _firstLink)
      _firstLink = newElement.id_t;
  if (_count == 0)
    {
      /* Link to self */
      [newElement.id_t setNextLink:newElement.id_t];
      [newElement.id_t setPrevLink:newElement.id_t];
    }
  else
    {
      [newElement.id_t setPrevLink:[oldElement.id_t prevLink]];
      [newElement.id_t setNextLink:oldElement.id_t];
      [[oldElement.id_t prevLink] setNextLink:newElement.id_t];
      [oldElement.id_t setPrevLink:newElement.id_t];
    }
  _count++;
  return self;
}

- (elt) replaceElement: (elt)oldElement with: (elt)newElement
{
  if (oldElement.id_t == _firstLink)
    _firstLink = newElement.id_t;
  [newElement.id_t setNextLink:[oldElement.id_t nextLink]];
  [newElement.id_t setPrevLink:[oldElement.id_t prevLink]];
  [[oldElement.id_t prevLink] setNextLink:newElement.id_t];
  [[oldElement.id_t nextLink] setPrevLink:newElement.id_t];
  return oldElement;
}

/* End of methods that change the instance variables. */

- appendElement: (elt)newElement
{
  [self insertElement:newElement after:[self lastElement]];
  return self;
}

- prependElement: (elt)newElement
{
  [self insertElement:newElement before:_firstLink];
  return self;
}

- insertElement: (elt)newElement atIndex: (unsigned)index
{
  if (INDEX_RANGE_WARNING(index, (_count+1)))
    return nil;
  if (index == _count)
    [self appendElement:newElement];
  else
    [self insertElement:newElement before:[self elementAtIndex:index]];
  return self;
}

- (elt) removeElementAtIndex: (unsigned)index
{
  if (INDEX_RANGE_WARNING(index, _count))
    return COLL_NO_ELEMENT;
  [self removeElement:[self elementAtIndex:index]];
  return self;
}

- (elt) elementAtIndex: (unsigned)index
{
  id <ListLinking> aLink;

  if (INDEX_RANGE_WARNING(index, _count))
    return COLL_NO_ELEMENT;
  if (index < _count / 2)
    for (aLink = _firstLink;
	 index;
	 aLink = [aLink nextLink], index--)
      ;
  else
    for (aLink = [_firstLink prevLink], index = _count - index - 1;
	 index;
	 aLink = [aLink prevLink], index--)
      ;
  return aLink;
}

- (elt) firstElement
{
  return _firstLink;
}

- (elt) lastElement
{
  if (_count)
    return [_firstLink prevLink];
  else
    return COLL_NO_ELEMENT;
}

- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState
{
  if (*enumState == _firstLink)
    return NO;
  else if (!(*enumState))
    *enumState = _firstLink;
  *anElementPtr = *enumState;
  *enumState = [(id)(*enumState) nextLink];
  return YES;
}

- (BOOL) getPrevElement:(elt *)anElementPtr withEnumState: (void**)enumState
{
  if (*enumState == _firstLink)
    return NO;
  if (!(*enumState))
    *enumState = _firstLink;
  *enumState = [(id)(*enumState) prevLink];
  *anElementPtr = *enumState;
  return YES;
}

- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag
{
  id link;
  unsigned i;

  for (link = _firstLink, i = 0;
       *flag && i < _count;
       link = [link nextLink], i++)
    {
      aFunc(link);
    }
  return self;
}

- withElementsInReverseCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag
{
  id link;
  unsigned i;

  if (!_firstLink)
    return self;
  for (link = [_firstLink prevLink], i = 0;
       *flag && i < _count;
       link = [link prevLink], i++)
    {
      aFunc(link);
    }
  return self;
}


- (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.