This is GCArray.m in view mode; [Download] [Up]
/* Copyright (C) 1996 Ovidiu Predescu <ovidiu@bx.logicnet.ro> Mircea Oancea <mircea@jupiter.elcom.pub.ro> Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro> This file is part of the FoundationExtensions 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; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <config.h> #include "common.h" #include <extensions/objc-runtime.h> #include <extensions/GCArray.h> #include <extensions/GCObject.h> #include <extensions/GarbageCollector.h> #include <extensions/NSException.h> #include <extensions/exceptions/GeneralExceptions.h> /* * TODO: copyWithZone: */ @implementation GCArray + (void)initialize { static BOOL initialized = NO; if(!initialized) { initialized = YES; class_add_behavior(self, [GCObject class]); } } - (id)initWithObjects:(id*)objects count:(unsigned int)count { int i; items = Calloc(count, sizeof(id)); isGarbageCollectable = Calloc(count, sizeof(BOOL)); itemsCount = count; for (i=0; i < count; i++) if (!(items[i] = [objects[i] retain])) THROW([[InvalidArgumentException alloc] initWithReason:@"Nil object to be added in array"]); else isGarbageCollectable[i] = [objects[i] isGarbageCollectable]; return self; } - (id)initWithArray:(NSArray*)anotherArray { int i, count = [anotherArray count]; items = Calloc(count, sizeof(id)); isGarbageCollectable = Calloc(count, sizeof(BOOL)); itemsCount = count; for (i=0; i < itemsCount; i++) { items[i] = [[anotherArray objectAtIndex:i] retain]; isGarbageCollectable[i] = [items[i] isGarbageCollectable]; } return self; } - (void)dealloc { unsigned int index; if([GarbageCollector isGarbageCollecting]) { for (index = 0; index < itemsCount; index++) if(!isGarbageCollectable[index]) [items[index] release]; } else { for (index = 0; index < itemsCount; index++) [items[index] release]; } Free(items); Free(isGarbageCollectable); [super dealloc]; } - (id)copy { return [self copyWithZone:NSDefaultMallocZone()]; } - (id)copyWithZone:(NSZone*)zone { if ([self zone] == zone) return [self retain]; return [[isa alloc] initWithObjects:items count:itemsCount]; } - (id)mutableCopy { return [self mutableCopyWithZone:NSDefaultMallocZone()]; } - (id)mutableCopyWithZone:(NSZone*)zone { return [[GCMutableArray allocWithZone:zone] initWithObjects:items count:itemsCount]; } - (id)objectAtIndex:(unsigned int)index { if (index >= itemsCount) THROW([[RangeException alloc] initWithReason:@"objectAtIndex: in NSArray" size:itemsCount index:index]); return items[index]; } - (unsigned int)count { return itemsCount; } - (unsigned int)indexOfObjectIdenticalTo:(id)anObject { int i; for (i = 0; i < itemsCount; i++) if (items[i] == anObject) return i; return NSNotFound; } - (void)gcDecrementRefCountOfContainedObjects { int i, count; for (i = 0, count = [self count]; i < count; i++) if (isGarbageCollectable[i]) [[self objectAtIndex:i] gcDecrementRefCount]; } - (BOOL)gcIncrementRefCountOfContainedObjects { int i, count; if ([(id)self gcAlreadyVisited]) return NO; [(id)self gcSetVisited:YES]; for (i = 0, count = [self count]; i < count; i++) if(isGarbageCollectable[i]) { id object = [self objectAtIndex:i]; [object gcIncrementRefCount]; [object gcIncrementRefCountOfContainedObjects]; } return YES; } @end /* GCArray */ @implementation GCMutableArray + (void)initialize { static BOOL initialized = NO; if(!initialized) { initialized = YES; class_add_behavior(self, [GCArray class]); } } - (id)init { return [self initWithCapacity:1]; } - (id)initWithCapacity:(unsigned int)aNumItems { items = Calloc(aNumItems, sizeof(id)); isGarbageCollectable = Calloc(aNumItems, sizeof(BOOL)); maxItems = aNumItems; itemsCount = 0; return self; } - (id)initWithObjects:(id *)objects count:(unsigned int)count { int i; items = Calloc(count, sizeof(id)); isGarbageCollectable = Calloc(count, sizeof(BOOL)); maxItems = itemsCount = count; for (i=0; i < count; i++) if (!(items[i] = [objects[i] retain])) THROW([[InvalidArgumentException alloc] initWithReason:@"Nil object to be added in array"]); else isGarbageCollectable[i] = [objects[i] isGarbageCollectable]; return self; } - (id)copyWithZone:(NSZone*)zone { return [[GCArray allocWithZone:zone] initWithObjects:items count:itemsCount]; } - (id)mutableCopyWithZone:(NSZone*)zone { return [[GCMutableArray allocWithZone:zone] initWithObjects:items count:itemsCount]; } - (void)insertObject:(id)anObject atIndex:(unsigned int)index { unsigned int i; if (!anObject) THROW([[InvalidArgumentException alloc] initWithReason:@"Nil object to be added in array"]); if (index > itemsCount) THROW([[RangeException alloc] initWithReason:@"insertObject:atIndex: in GCMutableArray" size:itemsCount index:index]); if (itemsCount == maxItems) { if (maxItems) { maxItems += (maxItems >> 1) ? (maxItems >>1) : 1; } else { maxItems = 1; } items = (id*)Realloc(items, sizeof(id) * maxItems); isGarbageCollectable = (BOOL*)Realloc(isGarbageCollectable, sizeof(BOOL) * maxItems); } for(i = itemsCount; i > index; i--) { items[i] = items[i - 1]; isGarbageCollectable[i] = isGarbageCollectable[i - 1]; } items[index] = [anObject retain]; isGarbageCollectable[index] = [anObject isGarbageCollectable]; itemsCount++; } - (void)addObject:(id)anObject { [self insertObject:anObject atIndex:itemsCount]; } - (void)replaceObjectAtIndex:(unsigned int)index withObject:(id)anObject { if (!anObject) THROW([[InvalidArgumentException alloc] initWithReason:@"Nil object to be added in array"]); if (index >= itemsCount) THROW([[RangeException alloc] initWithReason:@"GCMutableArray replaceObjectAtIndex" size:itemsCount index:index]); [anObject retain]; [items[index] release]; items[index] = anObject; isGarbageCollectable[index] = [anObject isGarbageCollectable]; } - (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count { int i; if (index + count > itemsCount) THROW([[RangeException alloc] initWithReason:@"removeObjectsFrom:count: in GCMutableArray" size:itemsCount index:index]); if (!count) return; for (i = index; i < index + count; i++) [items[i] release]; for (i = index + count; i < itemsCount; i++, index++) { items[index] = items[i]; isGarbageCollectable[index] = isGarbageCollectable[i]; } for (; index < itemsCount; index++) items[index] = (id)0x3; itemsCount -= count; } - (void)removeAllObjects { [self removeObjectsFrom:0 count:itemsCount]; } - (void)removeLastObject { [self removeObjectsFrom:(itemsCount - 1) count:1]; } - (void)removeObjectAtIndex:(unsigned int)index { [self removeObjectsFrom:index count:1]; } @end /* GCMutableArray */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.