quakeforge/tools/Forge/Bundles/MapEdit/Storage.m

254 lines
5.7 KiB
Mathematica
Raw Normal View History

/* Implementation of Objective C NeXT-compatible Storage object
Copyright (C) 1993,1994, 1996 Free Software Foundation, Inc.
Written by: Kresten Krab Thorup <krab@iesd.auc.dk>
Dept. of Mathematics and Computer Science, Aalborg U., Denmark
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 <config.h> */
#include "Storage.h"
#include <string.h>
#include <strings.h>
#define GNU_STORAGE_NTH(x, N) \
({GNUStorageId* __s = (GNUStorageId*) (x); \
(void*) (((char*) __s->dataPtr) + (__s->elementSize * (N))); })
#define STORAGE_NTH(N) GNU_STORAGE_NTH (self, N)
typedef struct {
@defs (Storage)
} GNUStorageId;
@implementation Storage
+ (id) initialize
{
if (self == [Storage class])
[self setVersion: 0]; /* beta release */
return self;
}
// INITIALIZING, FREEING;
- (id) initCount: (NSUInteger)numSlots elementSize: (NSUInteger)sizeInBytes
description: (const char *)
elemDesc;
{
[super init];
numElements = numSlots;
maxElements = (numSlots > 0) ? numSlots : 1;
elementSize = sizeInBytes;
description = elemDesc;
dataPtr = (void *) objc_malloc (maxElements * elementSize);
bzero (dataPtr, numElements * elementSize);
return self;
}
- (id) init
{
return [self initCount: 1 elementSize: sizeof (id)
description: @encode (id)];
}
- (void) dealloc
{
if (dataPtr)
free (dataPtr);
[super dealloc];
}
- (const char *) description
{
return description;
}
// COPYING;
- (id) copy
{
Storage *c = [super copy];
c->dataPtr = (void *) objc_malloc (maxElements * elementSize);
memcpy (c->dataPtr, dataPtr, numElements * elementSize);
return c;
}
// COMPARING TWO STORAGES;
- (BOOL) isEqual: anObject
{
if ([anObject isKindOfClass: [Storage class]]
&& [anObject count] == [self count]
&& !memcmp (((GNUStorageId *) anObject)->dataPtr,
dataPtr, numElements * elementSize))
return YES;
else
return NO;
}
// MANAGING THE STORAGE CAPACITY;
static inline void
_makeRoomForAnotherIfNecessary (Storage * self)
{
if (self->numElements == self->maxElements) {
self->maxElements *= 2;
self->dataPtr = (void *)
objc_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 *)
objc_realloc (self->dataPtr,
self->maxElements * self->elementSize);
}
}
- (id) setAvailableCapacity: (NSUInteger)numSlots
{
if (numSlots > numElements) {
maxElements = numSlots;
dataPtr = (void *) objc_realloc (dataPtr, maxElements * elementSize);
}
return self;
}
- (id) setNumSlots: (NSUInteger)numSlots
{
if (numSlots > numElements) {
maxElements = numSlots;
dataPtr = (void *) objc_realloc (dataPtr, maxElements * elementSize);
bzero (STORAGE_NTH (numElements),
(maxElements - numElements) * elementSize);
} else if (numSlots < numElements) {
numElements = numSlots;
_shrinkIfDesired (self);
}
return self;
}
/* Manipulating objects by index */
#define CHECK_INDEX(IND) if (IND >= numElements) return 0
- (NSUInteger) count
{
return numElements;
}
- (void *) elementAt: (NSUInteger)index
{
CHECK_INDEX (index);
return STORAGE_NTH (index);
}
- (id) addElement: (void *)anElement
{
_makeRoomForAnotherIfNecessary (self);
memcpy (STORAGE_NTH (numElements), anElement, elementSize);
numElements++;
return self;
}
- (id) insertElement: (void *)
anElement at: (NSUInteger)index
{
NSUInteger 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);
numElements++;
return self;
}
- (id) removeElementAt: (NSUInteger)index
{
NSUInteger 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;
}
- (id) removeLastElement
{
if (numElements) {
numElements--;
_shrinkIfDesired (self);
}
return self;
}
- (id) replaceElementAt: (NSUInteger)
index with: (void *)newElement
{
CHECK_INDEX (index);
memcpy (STORAGE_NTH (index), newElement, elementSize);
return self;
}
/* Emptying the Storage */
- (id) empty
{
numElements = 0;
maxElements = 1;
dataPtr = (void *) objc_realloc (dataPtr, maxElements * elementSize);
return self;
}
+ (id) new
{
return [[self alloc] init];
}
+ (id) newCount: (NSUInteger)
count elementSize: (NSUInteger)sizeInBytes
description: (const char *)descriptor
{
return [[self alloc] initCount: count elementSize: sizeInBytes description:
descriptor];
}
@end