mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 04:21:51 +00:00
rewrite Array, AutoreleasePool
This version is a bit more useful, and we should be able to get rid of the Stack class. Also, the Ruamoko parts of the autorelease system should be almost ready now.
This commit is contained in:
parent
4bd37e7b64
commit
505076a98d
8 changed files with 626 additions and 153 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -251,6 +251,7 @@ core
|
|||
/ruamoko/*.dat
|
||||
/ruamoko/*.qfo
|
||||
/ruamoko/*.sym
|
||||
/ruamoko/doxygen/
|
||||
|
||||
# /ruamoko/cl_menu/
|
||||
/ruamoko/cl_menu/*.dat
|
||||
|
|
|
@ -3,25 +3,213 @@
|
|||
|
||||
#include "Object.h"
|
||||
|
||||
@interface Array: Object
|
||||
/**
|
||||
A general ordered collection class
|
||||
|
||||
The %Array class manages an ordered collection of objects.
|
||||
If you want to subclass Array, you need to override these methods:
|
||||
|
||||
\li #count()
|
||||
\li #objectAtIndex:
|
||||
\li #addObject:
|
||||
\li #insertObject:atIndex:
|
||||
\li #removeObjectAtIndex:
|
||||
\li #removeLastObject
|
||||
\li #replaceObjectAtIndex:withObject:
|
||||
*/
|
||||
@interface Array: Object //<Copying>
|
||||
{
|
||||
integer count, size;
|
||||
integer incr;
|
||||
id [] array;
|
||||
unsigned count; ///< The number of objects currently contained
|
||||
unsigned capacity; ///< The number of objects that can be held right now
|
||||
unsigned granularity; ///< The number of pointers allocated at a time (based on initial capacity)
|
||||
id [] _objs; ///< A primitive array of pointers to objects
|
||||
}
|
||||
- (id) init;
|
||||
- (id) initWithIncrement: (integer) inc;
|
||||
- (void) dealloc;
|
||||
- (id) getItemAt: (integer) index;
|
||||
- (void) setItemAt: (integer) index item:(id) item;
|
||||
- (void) addItem: (id) item;
|
||||
- (void) removeItem: (id) item;
|
||||
- (id) removeItemAt: (integer) index;
|
||||
- (id) insertItemAt: (integer) index item:(id) item;
|
||||
- (integer) count;
|
||||
- (integer) findItem: (id) item;
|
||||
-(void)makeObjectsPerformSelector:(SEL)selector;
|
||||
-(void)makeObjectsPerformSelector:(SEL)selector withObject:(id)arg;
|
||||
|
||||
///\name Creating arrays
|
||||
//\{
|
||||
/**
|
||||
Create and return an empty array with the default initial capacity.
|
||||
*/
|
||||
+ (id) array;
|
||||
|
||||
/**
|
||||
Creates and returns an empty array with initial capacity \a cap.
|
||||
|
||||
\param cap The initial capacity of the array.
|
||||
*/
|
||||
+ (id) arrayWithCapacity: (unsigned)cap;
|
||||
|
||||
/**
|
||||
Returns a copy of \a array, retaining its contents.
|
||||
*/
|
||||
+ (id) arrayWithArray: (Array)array;
|
||||
|
||||
/**
|
||||
Create an array containing only \a anObject .
|
||||
*/
|
||||
+ (id) arrayWithObject: (id)anObject;
|
||||
|
||||
/**
|
||||
Create an array from a list of objects.
|
||||
|
||||
\warning Due to the nature of the Ruamoko/QuakeC language, do not supply
|
||||
more than 6 objects to this method.
|
||||
*/
|
||||
+ (id) arrayWithObjects: (id)firstObj, ...;
|
||||
|
||||
/**
|
||||
Create and return an array containing the first \a count objects from
|
||||
primitive array \a objs.
|
||||
|
||||
\warning Do not supply a primitive array containing fewer than \a count
|
||||
objects.
|
||||
*/
|
||||
+ (id) arrayWithObjects: (id [])objs
|
||||
count: (unsigned)cnt;
|
||||
//\}
|
||||
|
||||
///\name Initializing arrays
|
||||
//\{
|
||||
/**
|
||||
Initialize the receiver with capacity \a cap
|
||||
*/
|
||||
- (id) initWithCapacity: (unsigned)cap;
|
||||
|
||||
/**
|
||||
Initialize the receiver with objects from \a array.
|
||||
*/
|
||||
- (id) initWithArray: (Array)array;
|
||||
|
||||
/**
|
||||
Initialize the receiver with objects from \a array.
|
||||
|
||||
\param array The array to duplicate
|
||||
\param flag if #YES, copies the contents instead of retaining them.
|
||||
*/
|
||||
- (id) initWithArray: (Array)array
|
||||
copyItems: (BOOL)flag;
|
||||
|
||||
/**
|
||||
Initialize the receiver with a list of objects.
|
||||
|
||||
\warning Due to the nature of the Ruamoko/QuakeC language, do not supply
|
||||
more than 6 objects to this method.
|
||||
*/
|
||||
- (id) initWithObjects: (id)firstObj, ...;
|
||||
|
||||
/**
|
||||
Initialize the receiver with a primitive array of objects.
|
||||
*/
|
||||
- (id) initWithObjects: (id [])objs
|
||||
count: (unsigned)count;
|
||||
//\}
|
||||
|
||||
///\name Querying an array
|
||||
//\{
|
||||
/**
|
||||
Returns #YES if the receiver contains \a anObject.
|
||||
|
||||
The #isEqual: method is used to determine this, so that (for example) a
|
||||
newly-created string object can be compared to one already in the array.
|
||||
*/
|
||||
- (BOOL) containsObject: (id)anObject;
|
||||
|
||||
/**
|
||||
Returns the number of objects contained in the receiver.
|
||||
*/
|
||||
- (unsigned) count;
|
||||
|
||||
/**
|
||||
Returns the object contained at index \a index.
|
||||
*/
|
||||
- (id) objectAtIndex: (unsigned)index;
|
||||
|
||||
/**
|
||||
Returns the contained object with the highest index.
|
||||
*/
|
||||
- (id) lastObject;
|
||||
//- (Enumerator) objectEnumerator;
|
||||
//- (Enumerator) reverseObjectEnumerator;
|
||||
|
||||
#if 0
|
||||
/**
|
||||
Copies all object references in the receiver to \a aBuffer.
|
||||
|
||||
\warning The destination buffer must be large enough to hold all contents.
|
||||
*/
|
||||
- (BOOL) getObjects: (id [])aBuffer;
|
||||
#endif
|
||||
//\}
|
||||
|
||||
///\name Adding objects
|
||||
//\{
|
||||
|
||||
/**
|
||||
Adds a single object to an array
|
||||
*/
|
||||
- (void) addObject: (id)anObject;
|
||||
|
||||
/**
|
||||
Adds each object in \a array to the receiver, retaining it.
|
||||
*/
|
||||
- (void) addObjectsFromArray: (Array)array;
|
||||
|
||||
/**
|
||||
Adds a single object to an array
|
||||
|
||||
Adds \a anObject to the receiver at index \a index, pushing any objects
|
||||
with a higher index to the next higher slot.
|
||||
*/
|
||||
- (void) insertObject: (id)anObject
|
||||
atIndex: (unsigned)index;
|
||||
//\}
|
||||
|
||||
///\name Replacing Objects
|
||||
//\{
|
||||
- (void) replaceObjectAtIndex: (unsigned)index
|
||||
withObject: (id)anObject;
|
||||
- (void) setArray: (Array)array;
|
||||
//\}
|
||||
|
||||
///\name Removing Objects
|
||||
//\{
|
||||
|
||||
/**
|
||||
Recursively removes all objects from the receiver by sending
|
||||
#removeLastObject to \a self, until #count() returns zero.
|
||||
*/
|
||||
- (void) removeAllObjects;
|
||||
|
||||
|
||||
- (void) removeLastObject;
|
||||
|
||||
/**
|
||||
Finds and removes all objects from the receiver that are equal to
|
||||
\a anObject, by sending each #isEqual: with \a anObject as the argument.
|
||||
*/
|
||||
- (void) removeObject: (id)anObject;
|
||||
|
||||
/**
|
||||
Finds and removes all objects from the receiver that are equal to any
|
||||
objects in array \a anArray.
|
||||
*/
|
||||
- (void) removeObjectsInArray: (Array)anArray;
|
||||
|
||||
/**
|
||||
Finds and removes all objects from the receiver that are \b exactly equal
|
||||
to \a anObject, using a direct address comparison.
|
||||
*/
|
||||
- (void) removeObjectIdenticalTo: (id)anObject;
|
||||
- (void) removeObjectAtIndex: (unsigned)index;
|
||||
//\}
|
||||
|
||||
///\name Sending Messages to Elements
|
||||
//\{
|
||||
- (void) makeObjectsPerformSelector: (SEL)selector;
|
||||
- (void) makeObjectsPerformSelector: (SEL)selector
|
||||
withObject: (id)arg;
|
||||
//\}
|
||||
|
||||
@end
|
||||
|
||||
#endif//__ruamoko_Array_h
|
||||
|
|
|
@ -15,4 +15,6 @@
|
|||
|
||||
@end
|
||||
|
||||
void ARP_FreeAllPools (void);
|
||||
|
||||
#endif // __ruamoko_AutoreleasePool_h
|
||||
|
|
32
ruamoko/lib/Array+Private.h
Normal file
32
ruamoko/lib/Array+Private.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef __ruamoko_Array_Private_h
|
||||
#define __ruamoko_Array_Private_h
|
||||
|
||||
#include <Array.h>
|
||||
|
||||
/**
|
||||
Internal Array methods
|
||||
*/
|
||||
@interface Array (Private)
|
||||
|
||||
/**
|
||||
Adds an object to the receiver, but without retaining it.
|
||||
|
||||
This is a dangerous thing to do, and it's only done so that we can use an
|
||||
Array to implement the AutoreleasePool class.
|
||||
|
||||
\warning Using this method can result in crashes, and is only included
|
||||
for internal use by other classes.
|
||||
*/
|
||||
- (void) addObjectNoRetain: (id)anObject;
|
||||
|
||||
/**
|
||||
Removes an object from the receiver, but without releasing it.
|
||||
|
||||
This can leak objects, and is only used so that we can use Arrays to
|
||||
implement the autorelease system.
|
||||
*/
|
||||
- (void) removeObjectNoRelease: (id)anObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif //__ruamoko_Array_Private_h
|
33
ruamoko/lib/Array+Private.r
Normal file
33
ruamoko/lib/Array+Private.r
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "Array+Private.h"
|
||||
|
||||
@implementation Array (Private)
|
||||
|
||||
/**
|
||||
This is a somewhat dangerous thing to do, and it's only done so that we can
|
||||
use an Array to implement AutoreleasePool.
|
||||
*/
|
||||
- (void) addObjectNoRetain: (id)anObject
|
||||
{
|
||||
if (count == capacity) {
|
||||
capacity += granularity;
|
||||
_objs = (id [])obj_realloc (_objs, capacity * @sizeof (id));
|
||||
}
|
||||
_objs[count++] = anObject;
|
||||
}
|
||||
|
||||
- (void) removeObjectNoRelease: (id)anObject
|
||||
{
|
||||
local unsigned i = count;
|
||||
local unsigned tmp;
|
||||
|
||||
do {
|
||||
if (_objs[--i] == anObject) {
|
||||
for (tmp = i; tmp < count; tmp++) {
|
||||
_objs[tmp] = _objs[tmp + 1];
|
||||
}
|
||||
count--;
|
||||
}
|
||||
} while (i);
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,143 +1,367 @@
|
|||
#include "math.h"
|
||||
|
||||
#include "Array.h"
|
||||
|
||||
#define STANDARD_CAPACITY 16
|
||||
#define ARRAY_MAX_GRANULARITY 100
|
||||
|
||||
/*
|
||||
Optimization opportunity:
|
||||
|
||||
if ([self class] == [Array class]) {
|
||||
[[do things optimally instead of only through primitive methods]]
|
||||
}
|
||||
*/
|
||||
|
||||
@implementation Array
|
||||
|
||||
+ (id) array
|
||||
{
|
||||
return [self arrayWithCapacity: STANDARD_CAPACITY];
|
||||
}
|
||||
|
||||
+ (id) arrayWithCapacity: (unsigned)cap
|
||||
{
|
||||
return [[[self alloc] initWithCapacity: cap] autorelease];
|
||||
}
|
||||
|
||||
+ (id) arrayWithArray: (Array)array
|
||||
{
|
||||
return [[array copy] autorelease];
|
||||
}
|
||||
|
||||
+ (id) arrayWithObject: (id)anObject
|
||||
{
|
||||
Array newArray = (Array)[self arrayWithCapacity: STANDARD_CAPACITY];
|
||||
|
||||
[newArray addObject: anObject];
|
||||
return newArray;
|
||||
}
|
||||
|
||||
+ (id) arrayWithObjects: (id)firstObj, ...
|
||||
{
|
||||
local integer i;
|
||||
id newArray = [self arrayWithObject: firstObj];
|
||||
|
||||
for (i = 0; i < @args.count; i++) {
|
||||
[newArray addObject: (id) @args.list[i].pointer_val];
|
||||
}
|
||||
return [newArray autorelease];
|
||||
}
|
||||
|
||||
+ (id) arrayWithObjects: (id []) objs count: (unsigned)cnt
|
||||
{
|
||||
local integer i;
|
||||
id newArray = [self array];
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
[newArray addObject: (id) objs[i]];
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
self = [super init];
|
||||
count = size = 0;
|
||||
incr = 16;
|
||||
array = NIL;
|
||||
return self;
|
||||
return [self initWithCapacity: STANDARD_CAPACITY];
|
||||
}
|
||||
|
||||
- (id) initWithIncrement: (integer) inc
|
||||
- (id) initWithCapacity: (unsigned)cap
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return NIL;
|
||||
|
||||
count = 0;
|
||||
size = incr = inc;
|
||||
array = (id []) obj_malloc (inc * @sizeof (id));
|
||||
if ((capacity = cap) < 1)
|
||||
capacity = 1;
|
||||
|
||||
granularity = (capacity + 1) / 2;
|
||||
if (granularity < 1)
|
||||
granularity = 1;
|
||||
|
||||
if (granularity > ARRAY_MAX_GRANULARITY)
|
||||
granularity = ARRAY_MAX_GRANULARITY;
|
||||
|
||||
_objs = (id []) obj_malloc (capacity * @sizeof (id));
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
- (id) initWithArray: (Array)array
|
||||
{
|
||||
#if 0
|
||||
local unsigned i;
|
||||
local unsigned max = [array count];
|
||||
|
||||
if (!(self = [self initWithCapacity: max]))
|
||||
return NIL;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
_objs[i] = [[array objectAtIndex: i] retain];
|
||||
}
|
||||
return self;
|
||||
#else
|
||||
return [self initWithArray: array copyItems: NO];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (id) initWithArray: (Array)array
|
||||
copyItems: (BOOL)copy
|
||||
{
|
||||
local unsigned i;
|
||||
local unsigned max = [array count];
|
||||
|
||||
if (!(self = [self initWithCapacity: max]))
|
||||
return NIL;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
if (copy)
|
||||
_objs[i] = [[array objectAtIndex: i] copy];
|
||||
else
|
||||
_objs[i] = [[array objectAtIndex: i] retain];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id)firstObj, ...
|
||||
{
|
||||
local integer i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (array[i])
|
||||
[array[i] release];
|
||||
}
|
||||
if (array) {
|
||||
obj_free (array);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) getItemAt: (integer) index
|
||||
{
|
||||
if (index == -1)
|
||||
index = count - 1;
|
||||
if (index < 0 || index >= count)
|
||||
if (!(self = [self initWithCapacity: @args.count + 1]))
|
||||
return NIL;
|
||||
return array[index];
|
||||
}
|
||||
|
||||
- (void) setItemAt: (integer) index item: (id) item
|
||||
{
|
||||
if (index == -1)
|
||||
index = count - 1;
|
||||
if (index < 0 || index >= count)
|
||||
return;
|
||||
[item retain];
|
||||
[array[index] release];
|
||||
array[index] = item;
|
||||
}
|
||||
|
||||
- (void) addItem: (id) item
|
||||
{
|
||||
if (count == size) {
|
||||
size += incr;
|
||||
array = (id [])obj_realloc (array, size * @sizeof (id));
|
||||
[self addObject: firstObj];
|
||||
for (i = 0; i < @args.count; i++) {
|
||||
[self addObject: (id) @args.list[i].pointer_val];
|
||||
}
|
||||
[item retain];
|
||||
array[count++] = item;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) removeItem: (id) item
|
||||
{
|
||||
local integer i, n;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (array[i] == item) {
|
||||
count--;
|
||||
for (n = i--; n < count; n++)
|
||||
array[n] = array[n + 1];
|
||||
[item release];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
- (id) removeItemAt: (integer) index
|
||||
- (id) initWithObjects: (id []) objs count: (unsigned)cnt
|
||||
{
|
||||
local integer i;
|
||||
local id item;
|
||||
|
||||
if (index == -1)
|
||||
index = count -1;
|
||||
if (index < 0 || index >= count)
|
||||
if (!(self = [self initWithCapacity: cnt]))
|
||||
return NIL;
|
||||
item = array[index];
|
||||
count--;
|
||||
for (i = index; i < count; i++)
|
||||
array[i] = array[i + 1];
|
||||
[item release];
|
||||
return item;
|
||||
}
|
||||
|
||||
- (id) insertItemAt: (integer) index item:(id) item
|
||||
{
|
||||
local integer i;
|
||||
if (index == -1)
|
||||
index = count -1;
|
||||
if (index < 0 || index >= count)
|
||||
return NIL;
|
||||
if (count == size) {
|
||||
size += incr;
|
||||
array = (id [])obj_realloc (array, size * @sizeof (id));
|
||||
for (i = 0; i < cnt; i++) {
|
||||
[self addObject: (id) objs[i]];
|
||||
}
|
||||
for (i = count; i > index; i--)
|
||||
array[i] = array[i - 1];
|
||||
[item retain];
|
||||
array[index] = item;
|
||||
count++;
|
||||
return item;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (integer) count
|
||||
- (unsigned) count
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
- (integer) findItem: (id) item
|
||||
- (BOOL) containsObject: (id)anObject
|
||||
{
|
||||
local integer i;
|
||||
for (i = 0; i < count; i++)
|
||||
if (array[i] == item)
|
||||
return i;
|
||||
return -1;
|
||||
return [self indexOfObject: anObject] ? YES : NO;
|
||||
}
|
||||
|
||||
-(void)makeObjectsPerformSelector:(SEL)selector
|
||||
- (id) objectAtIndex: (unsigned)index
|
||||
{
|
||||
local integer i;
|
||||
for (i = 0; i < count; i++)
|
||||
[array[i] performSelector:selector];
|
||||
if (index >= count) {
|
||||
return NIL; // FIXME: need exceptions
|
||||
}
|
||||
return _objs[index];
|
||||
}
|
||||
|
||||
-(void)makeObjectsPerformSelector:(SEL)selector withObject:(id)arg
|
||||
- (id) lastObject
|
||||
{
|
||||
return [self objectAtIndex: [self count] - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
Adding objects
|
||||
*/
|
||||
|
||||
- (void) addObject: (id)anObject
|
||||
{
|
||||
if (count == capacity) {
|
||||
capacity += granularity;
|
||||
_objs = (id [])obj_realloc (_objs, capacity * @sizeof (id));
|
||||
}
|
||||
_objs[count++] = [anObject retain];
|
||||
}
|
||||
|
||||
- (void) addObjectsFromArray: (Array)array
|
||||
{
|
||||
local unsigned i;
|
||||
|
||||
if (!array || array == self)
|
||||
return; // FIXME: need exceptions
|
||||
|
||||
for (i = 0; i < [array count]; i++) {
|
||||
[self addObject: [array objectAtIndex: i]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) insertObject: (id)anObject
|
||||
atIndex: (unsigned)index
|
||||
{
|
||||
local integer i;
|
||||
for (i = 0; i < count; i++)
|
||||
[array[i] performSelector:selector withObject:arg];
|
||||
|
||||
if (index >= count)
|
||||
return; // FIXME: need exceptions
|
||||
|
||||
if (count == capacity) { // at capacity, expand
|
||||
_objs = (id [])obj_realloc (_objs, capacity * @sizeof (id));
|
||||
capacity += granularity;
|
||||
}
|
||||
|
||||
for (i = count; i > index; i--) {
|
||||
_objs[i] = _objs[i - 1];
|
||||
}
|
||||
|
||||
_objs[index] = [anObject retain];
|
||||
count++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Replacing objects
|
||||
*/
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned)index
|
||||
withObject: (id)anObject
|
||||
{
|
||||
local id tmp;
|
||||
|
||||
if (!anObject || index >= count) {
|
||||
return; // FIXME: need exceptions
|
||||
}
|
||||
|
||||
// retain before release
|
||||
tmp = _objs[index];
|
||||
_objs[index] = [anObject retain];
|
||||
[tmp release];
|
||||
}
|
||||
|
||||
- (void) setArray: (Array)array
|
||||
{
|
||||
if (self == array)
|
||||
return;
|
||||
|
||||
[self removeAllObjects];
|
||||
[self addObjectsFromArray: array];
|
||||
}
|
||||
|
||||
/*
|
||||
Object removal
|
||||
*/
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
#if 0
|
||||
local id tmp;
|
||||
|
||||
while (count) {
|
||||
/*
|
||||
We do it this way to avoid having something weird happen when
|
||||
the object is released (dealloc may trigger, which in turn could
|
||||
cause something else to happen).
|
||||
*/
|
||||
tmp = _objs[--count];
|
||||
_objs[i] = NIL;
|
||||
[tmp release];
|
||||
}
|
||||
#else
|
||||
while ([self count]) {
|
||||
[self removeLastObject];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) removeLastObject
|
||||
{
|
||||
local id tmp;
|
||||
|
||||
tmp = _objs[--count];
|
||||
_objs[count] = NIL;
|
||||
[tmp release];
|
||||
}
|
||||
|
||||
- (void) removeObject: (id)anObject
|
||||
{
|
||||
local unsigned i = [self count];
|
||||
do {
|
||||
--i;
|
||||
if ([[self objectAtIndex: i] isEqual: anObject]) {
|
||||
[self removeObjectAtIndex: i];
|
||||
}
|
||||
} while (i);
|
||||
}
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
local integer i;
|
||||
local id temp;
|
||||
|
||||
if (index >= count)
|
||||
return; // FIXME: need exceptions
|
||||
|
||||
temp = _objs[index];
|
||||
count--;
|
||||
for (i = index; i < count; i++) { // reassign all objs >= index
|
||||
_objs[i] = _objs[i+1];
|
||||
}
|
||||
|
||||
[temp release];
|
||||
}
|
||||
|
||||
- (void) removeObjectIdenticalTo: (id)anObject
|
||||
{
|
||||
local unsigned i = [self count];
|
||||
do {
|
||||
--i;
|
||||
if ([self objectAtIndex: i] == anObject) {
|
||||
[self removeObjectAtIndex: i];
|
||||
}
|
||||
} while (i);
|
||||
}
|
||||
|
||||
- (void) removeObjectsInArray: (Array)array
|
||||
{
|
||||
local unsigned i = [array count];
|
||||
|
||||
do {
|
||||
--i;
|
||||
[self removeObject: [array objectAtIndex: i]];
|
||||
} while (i);
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerformSelector: (SEL)selector
|
||||
{
|
||||
local integer i;
|
||||
|
||||
for (i = 0; i < [self count]; i++) {
|
||||
[[self objectAtIndex: i] performSelector: selector];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerformSelector: (SEL)selector
|
||||
withObject: (id)anObject
|
||||
{
|
||||
local integer i;
|
||||
|
||||
for (i = 0; i < [self count]; i++) {
|
||||
[[self objectAtIndex: i] performSelector: selector withObject: anObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
local unsigned i;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (_objs[i])
|
||||
[_objs[i] release];
|
||||
}
|
||||
|
||||
if (_objs) {
|
||||
obj_free (_objs);
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
#include "AutoreleasePool.h"
|
||||
//#include "Stack.h"
|
||||
|
||||
@static AutoreleasePool sharedInstance;
|
||||
//@static Stack poolStack;
|
||||
//@static AutoreleasePool sharedInstance;
|
||||
@static Array poolStack;
|
||||
|
||||
@interface AutoreleasePool (Private)
|
||||
- (void) addItem: (id)anItem;
|
||||
@end
|
||||
//@static Stack poolStack;
|
||||
|
||||
@implementation AutoreleasePool
|
||||
|
||||
|
@ -15,28 +13,26 @@
|
|||
if (!(self = [super init]))
|
||||
return NIL;
|
||||
|
||||
//if (!poolStack)
|
||||
// poolStack = [Stack new];
|
||||
if (!poolStack)
|
||||
poolStack = [[Array alloc] initWithCapacity: 1];
|
||||
|
||||
if (!sharedInstance)
|
||||
sharedInstance = self;
|
||||
[poolStack addObjectNoRetain: self];
|
||||
|
||||
array = [[Array alloc] init];
|
||||
array = [Array new];
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void) addObject: (id)anObject
|
||||
{
|
||||
if (!sharedInstance)
|
||||
if (!poolStack || [poolStack count])
|
||||
[[AutoreleasePool alloc] init];
|
||||
[sharedInstance addObject: anObject];
|
||||
|
||||
[[poolStack lastObject] addObject: anObject];
|
||||
}
|
||||
|
||||
- (void) addObject: (id)anObject
|
||||
{
|
||||
[array addItem: anObject];
|
||||
[anObject release]; // the array retains the item, and releases when
|
||||
// dealloced
|
||||
[array addObjectNoRetain: anObject];
|
||||
}
|
||||
|
||||
- (id) retain
|
||||
|
@ -44,33 +40,27 @@
|
|||
[self error: "Don't send -retain to an autorelease pool."];
|
||||
}
|
||||
|
||||
+ (void) release
|
||||
- (id) autorelease
|
||||
{
|
||||
[sharedInstance release];
|
||||
sharedInstance = NIL;
|
||||
}
|
||||
|
||||
- (/*oneway*/ void) release
|
||||
{
|
||||
[self dealloc];
|
||||
[self error: "Don't send -autorelease to an autorelease pool."];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
//local id tmp;
|
||||
|
||||
[array release];
|
||||
|
||||
/*
|
||||
This may be wrong.
|
||||
Releasing an autorelease pool should keep popping pools off the stack
|
||||
until it gets to itself.
|
||||
*/
|
||||
//do {
|
||||
// tmp = [poolStack pop];
|
||||
//} while (tmp != self);
|
||||
|
||||
sharedInstance = NIL;
|
||||
[poolStack removeObjectNoRelease: self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (/*oneway*/ void) release
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void
|
||||
ARP_FreeAllPools (void)
|
||||
{
|
||||
[poolStack removeAllObjects];
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ RANLIB=touch
|
|||
|
||||
INCLUDES= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include
|
||||
|
||||
noinst_HEADERS= \
|
||||
Array+Private.h
|
||||
|
||||
ruamoko_libs=libr.a libqw.a libnq.a libcsqc.a
|
||||
if BUILD_RUAMOKO
|
||||
libs=$(ruamoko_libs)
|
||||
|
@ -29,7 +32,7 @@ EXTRA_LIBRARIES= $(ruamoko_libs)
|
|||
libr_a_SOURCES=\
|
||||
cbuf.r cmd.r cvar.r file.r hash.r plist.r qfile.r qfs.r script.r sound.r \
|
||||
string.r \
|
||||
AutoreleasePool.r Array.r Entity.r List.r ListNode.r Object.r \
|
||||
AutoreleasePool.r Array.r Array+Private.r Entity.r List.r ListNode.r Object.r \
|
||||
PropertyList.r Protocol.r Stack.r
|
||||
libr_a_AR=$(PAK) -cf
|
||||
|
||||
|
|
Loading…
Reference in a new issue