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.