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

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

/* Implementation of Objective C NeXT-compatible Storage object

   Copyright (C) 1993 R. Andrew McCallum <mccallum@cs.rochester.edu>
   Dept. of Computer Science, U. of Rochester, Rochester, NY  14627
   Copyright (C) 1993 Kresten Krab Thorup <krab@iesd.auc.dk>
   Dept. of Mathematics and Computer Science, Aalborg U., Denmark

   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/Storage.h>
#include <stdlib.h>

#define STORAGE_NTH(N) GNU_STORAGE_NTH (self, N)

@implementation Storage

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

// INITIALIZING, FREEING;

- initCount:(unsigned)numSlots
  elementSize:(unsigned)sizeInBytes
  description:(const char*)elemDesc;
{
    [super init];
    numElements = 0;
    maxElements = numSlots;
    elementSize = sizeInBytes;
    description = elemDesc;
    dataPtr = (void**) malloc(maxElements * elementSize);
    return self;
}

- init
{
  return [self initCount:1 elementSize:sizeof(id) description:"@"];
}


- free
{
    if (dataPtr)
	free(dataPtr);
    return [super free];
}

- (const char*)description
{
  return description;
}


// COPYING;

- shallowCopy
{
  Storage *c = [super shallowCopy];
  c->dataPtr = (void**) malloc(maxElements * elementSize);
  bcopy(dataPtr, c->dataPtr, numElements * elementSize);
  return c;
}

// COMPARING TWO STORAGES;

- (BOOL)isEqual: anObject
{
  if ([anObject isKindOf: [Storage class]]
      && [anObject count] == [self count]
      && !bcmp(((GNUStorageId*)anObject)->dataPtr,
	       dataPtr, numElements*elementSize))
    return YES;
  else
    return NO;
}
  
// MANAGING THE STORAGE CAPACITY;

- (unsigned)capacity
{
  return maxElements;
}

static inline void _makeRoomForAnotherIfNecessary(Storage *self)
{
  if (self->numElements == self->maxElements) 
    {
      self->maxElements *= 2;
      self->dataPtr = (void**) realloc(self->dataPtr, 
				       self->maxElements*self->elementSize);
    }
}

static inline void _shrinkIfDesired(Storage *self)
{
  if (self->numElements < (self->maxElements / 2)) 
    {
      self->maxElements /= 2;
      self->dataPtr = (void *) realloc(self->dataPtr, 
				       self->maxElements*self->elementSize);
    }
}

- setAvailableCapacity:(unsigned)numSlots
{
  if (numSlots > numElements) 
    {
      maxElements = numSlots;
      dataPtr = (void**) realloc(dataPtr, maxElements * elementSize);
    }
  return self;
}

- setNumSlots:(unsigned)numSlots
{
  if (numSlots > numElements) 
    {
      maxElements = numSlots;
      dataPtr = (void**) realloc(dataPtr, maxElements * elementSize);
    }
  else if (numSlots < numElements) 
    {
      numElements = numSlots;
      _shrinkIfDesired (self);
    }
  return self;
}

/* Manipulating objects by index */

#define CHECK_INDEX(IND)  if (IND >= numElements) return 0

- (unsigned)count
{
  return numElements;
}

- (void*)elementAt:(unsigned)index
{
  CHECK_INDEX(index);
  return STORAGE_NTH (index);
}

- (void*)lastElement
{
  if (numElements)
    return STORAGE_NTH(numElements-1);
  else
    return 0;
}

- addElement:(void*)anElement
{
  _makeRoomForAnotherIfNecessary(self);
  memcpy(STORAGE_NTH(numElements), anElement, elementSize);
  numElements++;
  return self;
}

- insertElement:(void*)anElement at:(unsigned)index
{
  int i;

  CHECK_INDEX(index);
  _makeRoomForAnotherIfNecessary(self);
#ifndef STABLE_MEMCPY    
  for (i = numElements; i >= index; i--)
    memcpy (STORAGE_NTH(i+1), STORAGE_NTH(i), elementSize);
#else
  memcpy (STORAGE_NTH (index+1),
	  STORAGE_NTH (index),
	  elementSize*(numElements-index));
#endif    
  memcpy(STORAGE_NTH(i), anElement, elementSize);
  return self;
}

- removeElementAt:(unsigned)index
{
    int i;

    CHECK_INDEX(index);
    numElements--;
#ifndef STABLE_MEMCPY
    for (i = index; i < numElements; i++)
      memcpy(STORAGE_NTH(i), STORAGE_NTH(i+1), elementSize);
#else
    memcpy (STORAGE_NTH (index),
	    STORAGE_NTH (index+1),
	    elementSize*(numElements-index-1));
#endif    
    _shrinkIfDesired(self);
    return self;
}

- (void*)removeLastElement
{
  if (numElements) 
    {
      numElements--;
      _shrinkIfDesired(self);
      return STORAGE_NTH(numElements);
    }
  return 0;
}

- replaceElementAt:(unsigned)index with:(void*)newElement
{
    CHECK_INDEX(index);
    memcpy(STORAGE_NTH(index), newElement, elementSize);
    return self;
}

- appendStorage: (Storage *)otherStorage
{
  int c = [otherStorage count];
  if (elementSize == otherStorage->elementSize)
    {
      [self setAvailableCapacity: numElements+c];
      memcpy (STORAGE_NTH (numElements), otherStorage->dataPtr, c*elementSize);
      numElements += c;
      return self;
    }
  else
    [self error: "incompatible storage sizes in %s", sel_get_name(_cmd)];
  return self;
}

/* Manipulating element */

- (unsigned)indexOf:(void*)anElement
{
    int i;

    for (i = 0; i < numElements; i++)
      if (!bcmp (STORAGE_NTH(i), anElement, elementSize))
	return i;
    return GNU_NOT_IN_STORAGE;
}

- addElementIfAbsent:(void*)anElement
{
  if ([self indexOf:anElement] == GNU_NOT_IN_STORAGE)
    [self addElement:anElement];
  return self;
}

- removeElement:(void*)anElement
{
  return [self removeElementAt:[self indexOf:anElement]];
}

- replaceElement:(void*)anElement with:(void*)newElement
{
  return [self replaceElementAt:[self indexOf:anElement]
	       with:newElement];
}

/* Emptying the Storage */

- empty
{
  numElements = 0;
  maxElements = 1;
  dataPtr = (void**) realloc(dataPtr, maxElements * elementSize);
  return self;
}

/* Archiving */

- storeOn:(int)aFd
{
  return [self notImplemented:_cmd];
}

- readFrom:(int)aFd
{
  return [self notImplemented:_cmd];
}

- sortUsingFunction: (int(*)(void*, void*))comparisonFunction
{
  qsort(dataPtr, numElements, elementSize, comparisonFunction);
  return self;
}

@end

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