mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Major efficieny rewrites.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3043 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
85c38deb08
commit
b25aac96ce
10 changed files with 1047 additions and 409 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
The Oct 8 15:15:00 1998 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
* src/FastMap.x: Minor bugfixes and updates.
|
||||
* src/NSArray.m: Optimisation - don't use malloc unless really needed.
|
||||
* src/NSCountedSet.m: Tidied
|
||||
* src/NSSet.m: Tidied - core/non-core separation made.
|
||||
* src/NSGArray.m: Rewrite - simpler and faster.
|
||||
* src/NSGCountedSet.m: Rewrite to use FastMap (and work).
|
||||
* src/NSGDictionary.m: Tidied initialisation.
|
||||
* src/NSGSet.m: Rewrite to use FastMap - much faster.
|
||||
* src/include/NSSet.h: tidied - core/non-core stuff.
|
||||
|
||||
Tue Oct 6 16:35:48 1998 Adam Fedor <fedor@doc.com>
|
||||
|
||||
* aclocal.m4: Add win32 test
|
||||
|
@ -5,7 +17,7 @@ Tue Oct 6 16:35:48 1998 Adam Fedor <fedor@doc.com>
|
|||
* src/GNUmakefile: Add win32-load.h
|
||||
* src/win32-load.h: New file.
|
||||
|
||||
Sat Oct 6 16:45:00 1998 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Tue Oct 6 16:45:00 1998 Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
* src/FastMap.x: New map table for dictionaries.
|
||||
* src/include/fast.x: New stuff for avoiding objc message overheads.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Interface for NSSet, NSMutableSet, NSCountedSet for GNUStep
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: Sep 1995
|
||||
|
@ -30,24 +30,29 @@
|
|||
|
||||
@interface NSSet : NSObject <NSCoding, NSCopying, NSMutableCopying>
|
||||
|
||||
+ allocWithZone: (NSZone*)zone;
|
||||
+ set;
|
||||
+ setWithArray: (NSArray*)array;
|
||||
+ setWithObject: anObject;
|
||||
+ setWithObjects: anObject, ...;
|
||||
|
||||
- (id) initWithObjects: (id*)objects
|
||||
count: (unsigned)count;
|
||||
- (unsigned) count;
|
||||
- (id) member: (id)anObject;
|
||||
- (NSEnumerator*) objectEnumerator;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSSet (NonCore)
|
||||
|
||||
- initWithArray: (NSArray*)array;
|
||||
- initWithObjects: (id)objects, ...;
|
||||
- initWithObjects: (id*)objects
|
||||
count: (unsigned)count;
|
||||
- initWithSet: (NSSet*)otherSet;
|
||||
- initWithSet: (NSSet*)otherSet copyItems: (BOOL)flags;
|
||||
|
||||
- (NSArray*) allObjects;
|
||||
- anyObject;
|
||||
- (BOOL) containsObject: anObject;
|
||||
- (unsigned) count;
|
||||
- member: anObject;
|
||||
- (NSEnumerator*) objectEnumerator;
|
||||
- (void) makeObjectsPerform: (SEL)aSelector;
|
||||
- (void) makeObjectsPerform: (SEL)aSelector withObject:argument;
|
||||
|
||||
|
@ -56,38 +61,33 @@
|
|||
- (BOOL) isEqualToSet: (NSSet*)other;
|
||||
- (BOOL) isSubsetOfSet: (NSSet*)other;
|
||||
|
||||
- (NSString*) description;
|
||||
- (NSString*) descriptionWithLocale: (NSDictionary*)ld;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSMutableSet: NSSet
|
||||
|
||||
+ allocWithZone: (NSZone*)zone;
|
||||
+ setWithCapacity: (unsigned)numItems;
|
||||
- initWithCapacity: (unsigned)numItems;
|
||||
|
||||
- (void) addObject: anObject;
|
||||
- initWithCapacity: (unsigned)numItems;
|
||||
- (void) addObject: (id)anObject;
|
||||
- (void) removeObject: (id)anObject;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSMutableSet (NonCore)
|
||||
|
||||
- (void) addObjectsFromArray: (NSArray*)array;
|
||||
- (void) unionSet: (NSSet*)other;
|
||||
- (void) intersectSet: (NSSet*)other;
|
||||
- (void) minusSet: (NSSet*)other;
|
||||
- (void) removeAllObjects;
|
||||
- (void) removeObject: anObject;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSCountedSet : NSMutableSet
|
||||
|
||||
+ allocWithZone: (NSZone*)zone;
|
||||
- initWithCapacity: (unsigned)numItems;
|
||||
- initWithArray: (NSArray*)array;
|
||||
- initWithSet: (NSSet*)otherSet;
|
||||
|
||||
- (void) addObject: anObject;
|
||||
- (void) removeObject: anObject;
|
||||
- (unsigned int) countForObject: anObject;
|
||||
- (NSEnumerator*) objectEnumerator;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ typedef union {
|
|||
NSObject *o;
|
||||
long int i;
|
||||
void *p;
|
||||
unsigned u;
|
||||
} FastMapItem;
|
||||
|
||||
typedef struct _FastMapTable FastMapTable_t;
|
||||
|
@ -316,7 +317,7 @@ FastMapNewNode(FastMapTable map, FastMapItem key)
|
|||
{
|
||||
FastMapNode node = map->freeNodes;
|
||||
|
||||
if (node = 0) {
|
||||
if (node == 0) {
|
||||
FastMapMoreNodes(map);
|
||||
node = map->freeNodes;
|
||||
if (node == 0) {
|
||||
|
@ -524,7 +525,7 @@ FastMapAddKey(FastMapTable map, FastMapItem key)
|
|||
FastMapNode node;
|
||||
|
||||
FAST_MAP_RETAIN_KEY(key);
|
||||
node = FastMapNewNode(map, key, value);
|
||||
node = FastMapNewNode(map, key);
|
||||
|
||||
if (node != 0) {
|
||||
FastMapRightSizeMap(map, map->nodeCount);
|
||||
|
@ -550,7 +551,7 @@ FastMapRemoveKey(FastMapTable map, FastMapItem key)
|
|||
}
|
||||
|
||||
static INLINE void
|
||||
FastMapEmptyMap(FastMapTable map)
|
||||
FastMapCleanMap(FastMapTable map)
|
||||
{
|
||||
FastMapBucket bucket = map->buckets;
|
||||
int i;
|
||||
|
@ -564,6 +565,16 @@ FastMapEmptyMap(FastMapTable map)
|
|||
}
|
||||
bucket++;
|
||||
}
|
||||
map->firstNode = 0;
|
||||
map->nodeCount = 0;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
FastMapEmptyMap(FastMapTable map)
|
||||
{
|
||||
int i;
|
||||
|
||||
FastMapCleanMap(map);
|
||||
if (map->buckets != 0) {
|
||||
NSZoneFree(map->zone, map->buckets);
|
||||
map->buckets = 0;
|
||||
|
@ -577,9 +588,6 @@ FastMapEmptyMap(FastMapTable map)
|
|||
NSZoneFree(map->zone, map->nodeChunks);
|
||||
map->nodeChunks = 0;
|
||||
}
|
||||
|
||||
map->firstNode = 0;
|
||||
map->nodeCount = 0;
|
||||
map->freeNodes = 0;
|
||||
map->zone = 0;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* NSArray - Array object to hold other objects.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
From skeleton by: Adam Fedor <fedor@boulder.colorado.edu>
|
||||
|
@ -194,31 +194,31 @@ static Class NSMutableArray_concrete_class;
|
|||
id *objects;
|
||||
|
||||
c = [self count];
|
||||
OBJC_MALLOC (objects, id, c+1);
|
||||
for (i = 0; i < c; i++)
|
||||
objects[i] = [self objectAtIndex: i];
|
||||
objects[c] = anObject;
|
||||
na = [[NSArray alloc] initWithObjects: objects count: c+1];
|
||||
OBJC_FREE (objects);
|
||||
{
|
||||
id objects[c+1];
|
||||
|
||||
[self getObjects: objects];
|
||||
objects[c] = anObject;
|
||||
na = [[NSArray alloc] initWithObjects: objects count: c+1];
|
||||
}
|
||||
return [na autorelease];
|
||||
}
|
||||
|
||||
- (NSArray*) arrayByAddingObjectsFromArray: (NSArray*)anotherArray
|
||||
{
|
||||
id na;
|
||||
unsigned i, c, l;
|
||||
id *objects;
|
||||
id na;
|
||||
unsigned c, l;
|
||||
|
||||
c = [self count];
|
||||
l = [anotherArray count];
|
||||
OBJC_MALLOC (objects, id, c+l);
|
||||
for (i = 0; i < c; i++)
|
||||
objects[i] = [self objectAtIndex: i];
|
||||
for (i = c; i < c+l; i++)
|
||||
objects[i] = [anotherArray objectAtIndex: i-c];
|
||||
na = [[NSArray alloc] initWithObjects: objects count: c+l];
|
||||
OBJC_FREE (objects);
|
||||
return [na autorelease];
|
||||
c = [self count];
|
||||
l = [anotherArray count];
|
||||
{
|
||||
id objects[c+l];
|
||||
|
||||
[self getObjects: objects];
|
||||
[anotherArray getObjects: &objects[c]];
|
||||
na = [NSArray arrayWithObjects: objects count: c+l];
|
||||
}
|
||||
return na;
|
||||
}
|
||||
|
||||
- initWithObjects: firstObject rest: (va_list) ap
|
||||
|
@ -231,8 +231,8 @@ static Class NSMutableArray_concrete_class;
|
|||
auto id tmpId;
|
||||
|
||||
/* Do initial allocation. */
|
||||
prevSize = 1;
|
||||
curSize = 2;
|
||||
prevSize = 3;
|
||||
curSize = 5;
|
||||
OBJC_MALLOC(objsArray, id, curSize);
|
||||
tmpId = firstObject;
|
||||
|
||||
|
@ -312,16 +312,16 @@ static Class NSMutableArray_concrete_class;
|
|||
|
||||
- initWithArray: (NSArray*)array
|
||||
{
|
||||
unsigned i, c;
|
||||
id *objects;
|
||||
unsigned c;
|
||||
|
||||
c = [array count];
|
||||
OBJC_MALLOC(objects, id, c);
|
||||
for (i = 0; i < c; i++)
|
||||
objects[i] = [array objectAtIndex:i];
|
||||
self = [self initWithObjects:objects count:c];
|
||||
OBJC_FREE(objects);
|
||||
return self;
|
||||
c = [array count];
|
||||
{
|
||||
id objects[c];
|
||||
|
||||
[array getObjects: objects];
|
||||
self = [self initWithObjects: objects count: c];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) getObjects: (id*)aBuffer
|
||||
|
@ -537,16 +537,13 @@ static Class NSMutableArray_concrete_class;
|
|||
else
|
||||
j = range.location + range.length - 1;
|
||||
|
||||
// Copy the ids from the range into a temporary array
|
||||
OBJC_MALLOC(objects, id, j-i+1);
|
||||
for (k = i; k <= j; k++)
|
||||
objects[k-i] = [self objectAtIndex:k];
|
||||
|
||||
// Create the new array
|
||||
na = [[NSArray alloc] initWithObjects:objects count:j-i+1];
|
||||
OBJC_FREE(objects);
|
||||
return [na autorelease];
|
||||
{
|
||||
id objects[j-i+1];
|
||||
|
||||
[self getObjects: objects range: NSMakeRange(i, j-i+1)];
|
||||
na = [NSArray arrayWithObjects: objects count: j-i+1];
|
||||
}
|
||||
return na;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
|
|
|
@ -22,17 +22,30 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <Foundation/NSSet.h>
|
||||
#include <Foundation/NSGSet.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSUtilities.h>
|
||||
#include <gnustep/base/NSString.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <assert.h>
|
||||
|
||||
@class NSSetNonCore;
|
||||
@class NSMutableSetNonCore;
|
||||
|
||||
@implementation NSCountedSet
|
||||
|
||||
static Class NSCountedSet_concrete_class;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSCountedSet class]) {
|
||||
NSCountedSet_concrete_class = [NSGCountedSet class];
|
||||
behavior_class_add_class(self, [NSMutableSetNonCore class]);
|
||||
behavior_class_add_class(self, [NSSetNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) _CountedSetConcreteClass: (Class)c
|
||||
{
|
||||
NSCountedSet_concrete_class = c;
|
||||
|
@ -43,58 +56,11 @@ static Class NSCountedSet_concrete_class;
|
|||
return NSCountedSet_concrete_class;
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
NSCountedSet_concrete_class = [NSGCountedSet class];
|
||||
}
|
||||
|
||||
+ allocWithZone: (NSZone*)z
|
||||
{
|
||||
return NSAllocateObject([self _concreteClass], 0, z);
|
||||
}
|
||||
|
||||
|
||||
/* This is the designated initializer */
|
||||
/* Also, override superclass's designated initializer */
|
||||
- initWithCapacity: (unsigned)numItems
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- initWithArray: (NSArray*)array
|
||||
{
|
||||
int i, c = [array count];
|
||||
[self initWithCapacity:c];
|
||||
for (i = 0; i < c; i++)
|
||||
[self addObject:[array objectAtIndex:i]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithSet: (NSSet*)other
|
||||
{
|
||||
id o, e = [other objectEnumerator];
|
||||
|
||||
[self initWithCapacity:[other count]];
|
||||
while ((o = [e nextObject]))
|
||||
[self addObject:o];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) addObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (unsigned int) countForObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
|
@ -103,14 +69,51 @@ static Class NSCountedSet_concrete_class;
|
|||
|
||||
- copyWithZone: (NSZone*)z
|
||||
{
|
||||
id o, e = [self objectEnumerator];
|
||||
id c = [[[[self class] _concreteClass] alloc]
|
||||
initWithCapacity:[self count]];
|
||||
while ((o = [e nextObject]))
|
||||
[(NSCountedSet*)c addObject:o];
|
||||
/* Cast to avoid type warning.
|
||||
I'll fix the type in gnustep/base/Collecting.h eventually. */
|
||||
return o;
|
||||
/* a deep copy */
|
||||
int count = [self count];
|
||||
id objects[count];
|
||||
id enumerator = [self objectEnumerator];
|
||||
id o;
|
||||
NSSet *newSet;
|
||||
int i;
|
||||
BOOL needCopy = [self isKindOfClass: [NSMutableSet class]];
|
||||
|
||||
if (NSShouldRetainWithZone(self, z) == NO)
|
||||
needCopy = YES;
|
||||
|
||||
for (i = 0; (o = [enumerator nextObject]); i++)
|
||||
{
|
||||
objects[i] = [o copyWithZone:z];
|
||||
if (objects[i] != o)
|
||||
needCopy = YES;
|
||||
}
|
||||
if (needCopy)
|
||||
{
|
||||
int j;
|
||||
|
||||
newSet = [[[[self class] _concreteClass] allocWithZone: z]
|
||||
initWithObjects:objects count:count];
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
unsigned extra = [self countForObject: objects[j]];
|
||||
|
||||
if (extra > 1)
|
||||
while (--extra)
|
||||
[newSet addObject: objects[j]];
|
||||
}
|
||||
}
|
||||
else
|
||||
newSet = [self retain];
|
||||
for (i = 0; i < count; i++)
|
||||
[objects[i] release];
|
||||
return newSet;
|
||||
}
|
||||
|
||||
- mutableCopyWithZone: (NSZone*)z
|
||||
{
|
||||
/* a shallow copy */
|
||||
return [[[[self class] _concreteClass] allocWithZone: z] initWithSet: self];
|
||||
}
|
||||
|
||||
- initWithCoder: aCoder
|
||||
|
@ -124,4 +127,38 @@ static Class NSCountedSet_concrete_class;
|
|||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- initWithSet: (NSSet*)other copyItems: (BOOL)flag
|
||||
{
|
||||
int c = [other count];
|
||||
id os[c], o, e = [other objectEnumerator];
|
||||
int i = 0;
|
||||
|
||||
while ((o = [e nextObject]))
|
||||
{
|
||||
if (flag)
|
||||
os[i] = [o copy];
|
||||
else
|
||||
os[i] = o;
|
||||
i++;
|
||||
}
|
||||
self = [self initWithObjects:os count:c];
|
||||
if ([other isKindOfClass: [NSCountedSet class]])
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
unsigned extra = [(NSCountedSet*)other countForObject: os[j]];
|
||||
|
||||
if (extra > 1)
|
||||
while (--extra)
|
||||
[self addObject: os[j]];
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
while (--i)
|
||||
[os[i] release];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/* Concrete implementation of NSArray based on GNU Array class
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
/* Concrete implementation of NSArray
|
||||
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: March 1995
|
||||
Rewrite by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
|
@ -23,13 +24,29 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <gnustep/base/preface.h>
|
||||
#include <Foundation/NSGArray.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <gnustep/base/NSArray.h>
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <gnustep/base/Array.h>
|
||||
#include <gnustep/base/ArrayPrivate.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSPortCoder.h>
|
||||
#include <gnustep/base/Coding.h>
|
||||
|
||||
#define BADREALLOC 1
|
||||
|
||||
@interface NSGArray : NSArray
|
||||
{
|
||||
id *_contents_array;
|
||||
unsigned _count;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSGMutableArray : NSMutableArray
|
||||
{
|
||||
id *_contents_array;
|
||||
unsigned _count;
|
||||
unsigned _capacity;
|
||||
int _grow_factor;
|
||||
}
|
||||
@end
|
||||
|
||||
@class NSArrayNonCore;
|
||||
|
||||
|
@ -37,61 +54,159 @@
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSGArray class])
|
||||
{
|
||||
behavior_class_add_class (self, [NSArrayNonCore class]);
|
||||
behavior_class_add_class (self, [Array class]);
|
||||
if (self == [NSGArray class]) {
|
||||
behavior_class_add_class(self, [NSArrayNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
/* #define self ((Array*)self) */
|
||||
|
||||
#if 0
|
||||
/* This is the designated initializer for NSArray. */
|
||||
- initWithObjects: (id*)objects count: (unsigned)count
|
||||
- (void) dealloc
|
||||
{
|
||||
int i;
|
||||
if (_contents_array) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (objects[i] == nil)
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"Tried to add nil"];
|
||||
[self initWithCapacity: count];
|
||||
while (count--)
|
||||
[self addObject: [objects[count] retain]];
|
||||
return self;
|
||||
for (i = 0; i < _count; i++) {
|
||||
[_contents_array[i] release];
|
||||
}
|
||||
NSZoneFree([self zone], _contents_array);
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* This is the designated initializer for NSArray. */
|
||||
- (id) initWithObjects: (id*)objects count: (unsigned)count
|
||||
{
|
||||
if (count > 0) {
|
||||
unsigned i;
|
||||
|
||||
_contents_array = NSZoneMalloc([self zone], sizeof(id)*count);
|
||||
if (_contents_array == 0) {
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((_contents_array[i] = [objects[i] retain]) == nil) {
|
||||
_count = i;
|
||||
[self autorelease];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Tried to add nil"];
|
||||
}
|
||||
}
|
||||
_count = count;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
[(id<Encoding>)aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &_count
|
||||
withName: @"Array content count"];
|
||||
|
||||
if ([aCoder isKindOfClass: [NSPortCoder class]] &&
|
||||
[(NSPortCoder*)aCoder isBycopy]) {
|
||||
for (i = 0; i < _count; i++) {
|
||||
[(id<Encoding>)aCoder encodeBycopyObject: _contents_array[i]
|
||||
withName: @"Array content"];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < _count; i++) {
|
||||
[(id<Encoding>)aCoder encodeObject: _contents_array[i]
|
||||
withName: @"Array content"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned count;
|
||||
|
||||
[(id<Decoding>)aCoder decodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: NULL];
|
||||
if (count > 0) {
|
||||
_contents_array = NSZoneMalloc([self zone], sizeof(id)*count);
|
||||
if (_contents_array == 0) {
|
||||
[NSException raise: NSMallocException
|
||||
format: @"Unable to make array"];
|
||||
}
|
||||
while (_count < count) {
|
||||
[(id<Decoding>)aCoder decodeObjectAt: &_contents_array[_count++]
|
||||
withName: NULL];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
return [self initWithObjects: 0 count: 0];
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
/* Force message to go to super class rather than the behavior class */
|
||||
- (unsigned) indexOfObject: anObject
|
||||
{
|
||||
return [super indexOfObject: anObject];
|
||||
unsigned hash = [anObject hash];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _count; i++) {
|
||||
if ([_contents_array[i] hash] == hash) {
|
||||
if ([_contents_array[i] isEqual: anObject]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
- (unsigned) indexOfObjectIdenticalTo: anObject
|
||||
{
|
||||
if (index >= self->_count)
|
||||
[NSException raise: NSRangeException
|
||||
format: @"Index out of bounds"];
|
||||
return self->_contents_array[index];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _count; i++) {
|
||||
if (anObject == _contents_array[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
- (id) objectAtIndex: (unsigned)index
|
||||
{
|
||||
if (index >= _count) {
|
||||
[NSException raise: NSRangeException
|
||||
format: @"Index out of bounds"];
|
||||
}
|
||||
return _contents_array[index];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (void) getObjects: (id*)aBuffer
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < _count; i++)
|
||||
aBuffer[i] = _contents_array[i];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < _count; i++) {
|
||||
aBuffer[i] = _contents_array[i];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) getObjects: (id*)aBuffer range: (IndexRange)aRange
|
||||
{
|
||||
unsigned i, j = 0, e = aRange.location + aRange.length;
|
||||
if (_count < e)
|
||||
e = _count;
|
||||
for (i = aRange.location; i < _count; i++)
|
||||
aBuffer[j++] = _contents_array[i];
|
||||
unsigned i, j = 0, e = aRange.location + aRange.length;
|
||||
|
||||
if (_count < e) {
|
||||
e = _count;
|
||||
}
|
||||
for (i = aRange.location; i < _count; i++) {
|
||||
aBuffer[j++] = _contents_array[i];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -102,16 +217,189 @@
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSGMutableArray class])
|
||||
{
|
||||
behavior_class_add_class (self, [NSMutableArrayNonCore class]);
|
||||
behavior_class_add_class (self, [NSGArray class]);
|
||||
behavior_class_add_class (self, [Array class]);
|
||||
if (self == [NSGMutableArray class]) {
|
||||
behavior_class_add_class(self, [NSMutableArrayNonCore class]);
|
||||
behavior_class_add_class(self, [NSGArray class]);
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithCapacity: (unsigned)cap
|
||||
{
|
||||
if (cap == 0) {
|
||||
cap = 1;
|
||||
}
|
||||
_contents_array = NSZoneMalloc([self zone], sizeof(id)*cap);
|
||||
_capacity = cap;
|
||||
_grow_factor = cap > 1 ? cap/2 : 1;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned count;
|
||||
|
||||
[(id<Decoding>)aCoder decodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: NULL];
|
||||
if ([self initWithCapacity: count] == nil) {
|
||||
[NSException raise: NSMallocException
|
||||
format: @"Unable to make array"];
|
||||
}
|
||||
while (_count < count) {
|
||||
[(id<Decoding>)aCoder decodeObjectAt: &_contents_array[_count++]
|
||||
withName: NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id*)objects count: (unsigned)count
|
||||
{
|
||||
self = [self initWithCapacity: count];
|
||||
if (self != nil && count > 0) {
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if ((_contents_array[i] = [objects[i] retain]) == nil) {
|
||||
_count = i;
|
||||
[self autorelease];
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Tried to add nil"];
|
||||
}
|
||||
}
|
||||
_count = count;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) insertObject: (id)anObject atIndex: (unsigned)index
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (!anObject) {
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Tried to insert nil"];
|
||||
}
|
||||
if (index > _count) {
|
||||
[NSException raise: NSRangeException format:
|
||||
@"in insertObject:atIndex:, index %d is out of range", index];
|
||||
}
|
||||
if (_count == _capacity) {
|
||||
id *ptr;
|
||||
size_t size = (_capacity + _grow_factor)*sizeof(id);
|
||||
|
||||
#if BADREALLOC
|
||||
ptr = NSZoneMalloc([self zone], size);
|
||||
#else
|
||||
ptr = NSZoneRealloc([self zone], _contents_array, size);
|
||||
#endif
|
||||
if (ptr == 0) {
|
||||
[NSException raise: NSMallocException
|
||||
format: @"Unable to grow"];
|
||||
}
|
||||
#if BADREALLOC
|
||||
if (_contents_array) {
|
||||
memcpy(ptr, _contents_array, _capacity*sizeof(id));
|
||||
NSZoneFree([self zone], _contents_array);
|
||||
}
|
||||
#endif
|
||||
_contents_array = ptr;
|
||||
_capacity += _grow_factor;
|
||||
_grow_factor = _capacity/2;
|
||||
}
|
||||
for (i = _count; i > index; i--) {
|
||||
_contents_array[i] = _contents_array[i - 1];
|
||||
}
|
||||
/*
|
||||
* Make sure the array is 'sane' so that it can be deallocated
|
||||
* safely by an autorelease pool if the '[anObject retain]' causes
|
||||
* an exception.
|
||||
*/
|
||||
_contents_array[index] = nil;
|
||||
_count++;
|
||||
_contents_array[index] = [anObject retain];
|
||||
}
|
||||
|
||||
- (void) addObject: (id)anObject
|
||||
{
|
||||
if (anObject == nil) {
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Tried to add nil"];
|
||||
}
|
||||
if (_count >= _capacity) {
|
||||
id *ptr;
|
||||
size_t size = (_capacity + _grow_factor)*sizeof(id);
|
||||
|
||||
#if BADREALLOC
|
||||
ptr = NSZoneMalloc([self zone], size);
|
||||
#else
|
||||
ptr = NSZoneRealloc([self zone], _contents_array, size);
|
||||
#endif
|
||||
if (ptr == 0) {
|
||||
[NSException raise: NSMallocException
|
||||
format: @"Unable to grow"];
|
||||
}
|
||||
#if BADREALLOC
|
||||
if (_contents_array) {
|
||||
memcpy(ptr, _contents_array, _capacity*sizeof(id));
|
||||
NSZoneFree([self zone], _contents_array);
|
||||
}
|
||||
#endif
|
||||
_contents_array = ptr;
|
||||
_capacity += _grow_factor;
|
||||
_grow_factor = _capacity/2;
|
||||
}
|
||||
_contents_array[_count] = [anObject retain];
|
||||
_count++; /* Do this AFTER we have retained the object. */
|
||||
}
|
||||
|
||||
- (void) removeLastObject
|
||||
{
|
||||
if (_count == 0) {
|
||||
[NSException raise: NSRangeException
|
||||
format: @"Trying to remove from an empty array."];
|
||||
}
|
||||
_count--;
|
||||
[_contents_array[_count] release];
|
||||
}
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
id obj;
|
||||
|
||||
if (index >= _count) {
|
||||
[NSException raise: NSRangeException format:
|
||||
@"in removeObjectAtIndex:, index %d is out of range", index];
|
||||
}
|
||||
obj = _contents_array[index];
|
||||
_count--;
|
||||
while (index < _count) {
|
||||
_contents_array[index] = _contents_array[index+1];
|
||||
index++;
|
||||
}
|
||||
[obj release]; /* Adjust array BEFORE releasing object. */
|
||||
}
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: (id)anObject
|
||||
{
|
||||
id obj;
|
||||
|
||||
if (index >= _count) {
|
||||
[NSException raise: NSRangeException format:
|
||||
@"in replaceObjectAtIndex:withObject:, index %d is out of range",
|
||||
index];
|
||||
}
|
||||
/*
|
||||
* Swap objects in order so that there is always a valid object in the
|
||||
* array in case a retain or release causes an exception.
|
||||
*/
|
||||
obj = _contents_array[index];
|
||||
[anObject retain];
|
||||
_contents_array[index] = anObject;
|
||||
[obj release];
|
||||
}
|
||||
|
||||
- (void) sortUsingFunction: (int(*)(id,id,void*))compare
|
||||
context: (void*)context
|
||||
context: (void*)context
|
||||
{
|
||||
/* Shell sort algorithm taken from SortingInAction - a NeXT example */
|
||||
#define STRIDE_FACTOR 3 // good value for stride factor is not well-understood
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* Concrete implementation of NSCountedSet based on GNU Bag class
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
/* Concrete implementation of NSSet based on GNU Set class
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: Sep 1995
|
||||
Written by: Richard frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Created: October 1998
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
|
@ -22,41 +22,62 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <Foundation/NSGSet.h>
|
||||
#include <gnustep/base/NSSet.h>
|
||||
#include <Foundation/NSSet.h>
|
||||
//#include <Foundation/NSGSet.h>
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <gnustep/base/Set.h>
|
||||
#include <Foundation/NSUtilities.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSPortCoder.h>
|
||||
#include <gnustep/base/Coding.h>
|
||||
|
||||
|
||||
#define FAST_MAP_RETAIN_VAL(X) X
|
||||
#define FAST_MAP_RELEASE_VAL(X)
|
||||
|
||||
#include "FastMap.x"
|
||||
|
||||
@class NSSetNonCore;
|
||||
@class NSMutableSetNonCore;
|
||||
|
||||
@interface NSGCountedSet : NSCountedSet
|
||||
{
|
||||
@public
|
||||
FastMapTable_t map;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSGCountedSetEnumerator : NSEnumerator
|
||||
{
|
||||
NSCountedSet *bag;
|
||||
void *enum_state;
|
||||
NSGCountedSet *set;
|
||||
FastMapNode node;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSGCountedSetEnumerator
|
||||
|
||||
- initWithCountedSet: (NSCountedSet*)d
|
||||
- initWithSet: (NSSet*)d
|
||||
{
|
||||
[super init];
|
||||
bag = d;
|
||||
[bag retain];
|
||||
enum_state = [bag newEnumState];
|
||||
return self;
|
||||
[super init];
|
||||
set = [(NSGCountedSet*)d retain];
|
||||
node = set->map.firstNode;
|
||||
return self;
|
||||
}
|
||||
|
||||
- nextObject
|
||||
{
|
||||
return [bag nextObjectWithEnumState: &enum_state];
|
||||
FastMapNode old = node;
|
||||
|
||||
if (node == 0) {
|
||||
return nil;
|
||||
}
|
||||
node = node->nextInMap;
|
||||
return old->key.o;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[bag freeEnumState: &enum_state];
|
||||
[bag release];
|
||||
[super dealloc];
|
||||
[set release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -66,30 +87,162 @@
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
static int done = 0;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
done = 1;
|
||||
class_add_behavior([NSGCountedSet class], [Bag class]);
|
||||
if (self == [NSGCountedSet class]) {
|
||||
class_add_behavior(self, [NSSetNonCore class]);
|
||||
class_add_behavior(self, [NSMutableSetNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
FastMapEmptyMap(&map);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned count = map.nodeCount;
|
||||
FastMapNode node = map.firstNode;
|
||||
|
||||
[(id<Encoding>)aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: @"Set content count"];
|
||||
|
||||
if ([aCoder isKindOfClass: [NSPortCoder class]] &&
|
||||
[(NSPortCoder*)aCoder isBycopy]) {
|
||||
while (node != 0) {
|
||||
[(id<Encoding>)aCoder encodeBycopyObject: node->key.o
|
||||
withName: @"Set value"];
|
||||
[(id<Encoding>)aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &node->value.u
|
||||
withName: @"Set value count"];
|
||||
node = node->nextInMap;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (node != 0) {
|
||||
[(id<Encoding>)aCoder encodeObject: node->key.o
|
||||
withName: @"Set content"];
|
||||
[(id<Encoding>)aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &node->value.u
|
||||
withName: @"Set value count"];
|
||||
node = node->nextInMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned count;
|
||||
id value;
|
||||
unsigned valcnt;
|
||||
|
||||
[(id<Decoding>)aCoder decodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: NULL];
|
||||
|
||||
FastMapInitWithZoneAndCapacity(&map, [self zone], count);
|
||||
while (count-- > 0) {
|
||||
[(id<Decoding>)aCoder decodeObjectAt: &value withName: NULL];
|
||||
[(id<Decoding>)aCoder decodeValueOfCType: @encode(unsigned)
|
||||
at: &valcnt
|
||||
withName: NULL];
|
||||
FastMapAddPairNoRetain(&map, (FastMapItem)value, (FastMapItem)valcnt);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Designated initialiser */
|
||||
- (id) initWithCapacity: (unsigned)cap
|
||||
{
|
||||
FastMapInitWithZoneAndCapacity(&map, [self zone], cap);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithObjects: (id*)objs count: (unsigned)c
|
||||
{
|
||||
int i;
|
||||
|
||||
if ([self initWithCapacity: c] == nil) {
|
||||
return nil;
|
||||
}
|
||||
for (i = 0; i < c; i++) {
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)objs[i]);
|
||||
|
||||
if (node == 0) {
|
||||
FastMapAddPair(&map,(FastMapItem)objs[i],(FastMapItem)(unsigned)1);
|
||||
}
|
||||
else {
|
||||
node->value.u++;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) addObject: (NSObject*)anObject
|
||||
{
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)anObject);
|
||||
|
||||
if (node == 0) {
|
||||
FastMapAddPair(&map,(FastMapItem)anObject,(FastMapItem)(unsigned)1);
|
||||
}
|
||||
else {
|
||||
node->value.u++;
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return map.nodeCount;
|
||||
}
|
||||
|
||||
- (unsigned) countForObject: (id)anObject
|
||||
{
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)anObject);
|
||||
|
||||
if (node == 0) {
|
||||
return 0;
|
||||
}
|
||||
return node->value.u;
|
||||
}
|
||||
|
||||
- (id) member: (id)anObject
|
||||
{
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)anObject);
|
||||
|
||||
if (node == 0) {
|
||||
return nil;
|
||||
}
|
||||
return node->key.o;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
return [[[NSGCountedSetEnumerator alloc] initWithCountedSet:self]
|
||||
autorelease];
|
||||
return [[[NSGCountedSetEnumerator alloc] initWithSet: self] autorelease];
|
||||
}
|
||||
|
||||
- (unsigned int) countForObject: anObject
|
||||
- (void) removeObject: (NSObject*)anObject
|
||||
{
|
||||
return [self occurrencesOfObject: anObject];
|
||||
FastMapBucket bucket;
|
||||
|
||||
bucket = FastMapBucketForKey(&map, (FastMapItem)anObject);
|
||||
if (bucket) {
|
||||
FastMapNode node;
|
||||
|
||||
node = FastMapNodeForKeyInBucket(bucket, (FastMapItem)anObject);
|
||||
if (node) {
|
||||
if (--node->value.u == 0) {
|
||||
FastMapRemoveNodeFromMap(&map, bucket, node);
|
||||
FastMapFreeNode(&map, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* To deal with behavior over-enthusiasm. Will be fixed later. */
|
||||
- (BOOL) isEqual: other
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
return [super isEqual:other];
|
||||
FastMapCleanMap(&map);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -99,18 +99,6 @@ myEqual(NSObject *self, NSObject *other)
|
|||
|
||||
@class NSDictionaryNonCore;
|
||||
@class NSMutableDictionaryNonCore;
|
||||
@class NSGDictionary;
|
||||
@class NSGMutableDictionary;
|
||||
|
||||
@interface NSGDictionaryKeyEnumerator : NSEnumerator
|
||||
{
|
||||
NSGDictionary *dictionary;
|
||||
FastMapNode node;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSGDictionaryObjectEnumerator : NSGDictionaryKeyEnumerator
|
||||
@end
|
||||
|
||||
@interface NSGDictionary : NSDictionary
|
||||
{
|
||||
|
@ -126,13 +114,22 @@ myEqual(NSObject *self, NSObject *other)
|
|||
}
|
||||
@end
|
||||
|
||||
@interface NSGDictionaryKeyEnumerator : NSEnumerator
|
||||
{
|
||||
NSGDictionary *dictionary;
|
||||
FastMapNode node;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSGDictionaryObjectEnumerator : NSGDictionaryKeyEnumerator
|
||||
@end
|
||||
|
||||
@implementation NSGDictionary
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSGDictionary class])
|
||||
{
|
||||
behavior_class_add_class (self, [NSDictionaryNonCore class]);
|
||||
if (self == [NSGDictionary class]) {
|
||||
behavior_class_add_class(self, [NSDictionaryNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,6 +194,7 @@ myEqual(NSObject *self, NSObject *other)
|
|||
return self;
|
||||
}
|
||||
|
||||
/* Designated initialiser */
|
||||
- (id) initWithObjects: (id*)objs forKeys: (NSObject**)keys count: (unsigned)c
|
||||
{
|
||||
int i;
|
||||
|
@ -243,20 +241,20 @@ myEqual(NSObject *self, NSObject *other)
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSGMutableDictionary class])
|
||||
{
|
||||
behavior_class_add_class (self, [NSMutableDictionaryNonCore class]);
|
||||
behavior_class_add_class (self, [NSGDictionary class]);
|
||||
if (self == [NSGMutableDictionary class]) {
|
||||
behavior_class_add_class(self, [NSMutableDictionaryNonCore class]);
|
||||
behavior_class_add_class(self, [NSGDictionary class]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Designated initialiser */
|
||||
- (id) initWithCapacity: (unsigned)cap
|
||||
{
|
||||
FastMapInitWithZoneAndCapacity(&map, [self zone], cap);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setObject:anObject forKey:(NSObject *)aKey
|
||||
- (void) setObject: (NSObject*)anObject forKey: (NSObject *)aKey
|
||||
{
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)aKey);
|
||||
|
||||
|
@ -270,7 +268,12 @@ myEqual(NSObject *self, NSObject *other)
|
|||
}
|
||||
}
|
||||
|
||||
- (void) removeObjectForKey:(NSObject *)aKey
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
FastMapCleanMap(&map);
|
||||
}
|
||||
|
||||
- (void) removeObjectForKey: (NSObject *)aKey
|
||||
{
|
||||
FastMapRemoveKey(&map, (FastMapItem)aKey);
|
||||
}
|
||||
|
|
206
Source/NSGSet.m
206
Source/NSGSet.m
|
@ -1,8 +1,9 @@
|
|||
/* Concrete implementation of NSSet based on GNU Set class
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: September 1995
|
||||
Rewrite by: Richard frith-Macdonald <richard@brainstorm.co.uk>
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
|
@ -22,17 +23,39 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <Foundation/NSGSet.h>
|
||||
#include <gnustep/base/NSSet.h>
|
||||
#include <Foundation/NSSet.h>
|
||||
//#include <Foundation/NSGSet.h>
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <gnustep/base/Set.h>
|
||||
#include <Foundation/NSUtilities.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSPortCoder.h>
|
||||
#include <gnustep/base/Coding.h>
|
||||
|
||||
#define FAST_MAP_HAS_VALUE 0
|
||||
|
||||
#include "FastMap.x"
|
||||
|
||||
@class NSSetNonCore;
|
||||
@class NSMutableSetNonCore;
|
||||
|
||||
@interface NSGSet : NSSet
|
||||
{
|
||||
@public
|
||||
FastMapTable_t map;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSGMutableSet : NSMutableSet
|
||||
{
|
||||
@public
|
||||
FastMapTable_t map;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSGSetEnumerator : NSEnumerator
|
||||
{
|
||||
NSSet *set;
|
||||
void *enum_state;
|
||||
NSGSet *set;
|
||||
FastMapNode node;
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -40,22 +63,27 @@
|
|||
|
||||
- initWithSet: (NSSet*)d
|
||||
{
|
||||
[super init];
|
||||
set = d;
|
||||
[set retain];
|
||||
enum_state = [set newEnumState];
|
||||
return self;
|
||||
[super init];
|
||||
set = [(NSGSet*)d retain];
|
||||
node = set->map.firstNode;
|
||||
return self;
|
||||
}
|
||||
|
||||
- nextObject
|
||||
{
|
||||
return [set nextObjectWithEnumState: &enum_state];
|
||||
FastMapNode old = node;
|
||||
|
||||
if (node == 0) {
|
||||
return nil;
|
||||
}
|
||||
node = node->nextInMap;
|
||||
return old->key.o;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[set release];
|
||||
[super dealloc];
|
||||
[set release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -65,74 +93,132 @@
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
static int done = 0;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
done = 1;
|
||||
class_add_behavior([NSGSet class], [Set class]);
|
||||
if (self == [NSGSet class]) {
|
||||
class_add_behavior(self, [NSSetNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return map.nodeCount;
|
||||
}
|
||||
|
||||
/* This is the designated initializer
|
||||
- initWithObjects: (id*)objects
|
||||
count: (unsigned)count
|
||||
Implemented by behavior. */
|
||||
- (void) dealloc
|
||||
{
|
||||
FastMapEmptyMap(&map);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned count = map.nodeCount;
|
||||
FastMapNode node = map.firstNode;
|
||||
|
||||
[(id<Encoding>)aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: @"Set content count"];
|
||||
|
||||
if ([aCoder isKindOfClass: [NSPortCoder class]] &&
|
||||
[(NSPortCoder*)aCoder isBycopy]) {
|
||||
while (node != 0) {
|
||||
[(id<Encoding>)aCoder encodeBycopyObject: node->key.o
|
||||
withName: @"Set content"];
|
||||
node = node->nextInMap;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (node != 0) {
|
||||
[(id<Encoding>)aCoder encodeObject: node->key.o
|
||||
withName: @"Set content"];
|
||||
node = node->nextInMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
unsigned count;
|
||||
id value;
|
||||
|
||||
[(id<Decoding>)aCoder decodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: NULL];
|
||||
|
||||
FastMapInitWithZoneAndCapacity(&map, [self zone], count);
|
||||
while (count-- > 0) {
|
||||
[(id<Decoding>)aCoder decodeObjectAt: &value withName: NULL];
|
||||
FastMapAddKeyNoRetain(&map, (FastMapItem)value);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Designated initialiser */
|
||||
- (id) initWithObjects: (id*)objs count: (unsigned)c
|
||||
{
|
||||
int i;
|
||||
FastMapInitWithZoneAndCapacity(&map, [self zone], c);
|
||||
for (i = 0; i < c; i++) {
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)objs[i]);
|
||||
|
||||
if (node == 0) {
|
||||
FastMapAddKey(&map, (FastMapItem)objs[i]);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) member: (id)anObject
|
||||
{
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)anObject);
|
||||
|
||||
if (node == 0) {
|
||||
return nil;
|
||||
}
|
||||
return node->key.o;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
return [[[NSGSetEnumerator alloc] initWithSet:self]
|
||||
autorelease];
|
||||
return [[[NSGSetEnumerator alloc] initWithSet: self] autorelease];
|
||||
}
|
||||
|
||||
/* To deal with behavior over-enthusiasm. Will be fixed later. */
|
||||
- (BOOL) isEqual: other
|
||||
{
|
||||
#if 1
|
||||
return [self isEqualToSet: other];
|
||||
#else
|
||||
/* xxx What is the correct behavior here?
|
||||
If we end up calling [NSSet -isEqualToSet:] we end up in
|
||||
an infinite loop, since that method enumerates the set, and
|
||||
the set enumerator asks if things are equal...
|
||||
[Huh? What am I saying here?] */
|
||||
return (self == other);
|
||||
#endif
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSGMutableSet
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
static int done = 0;
|
||||
|
||||
if (!done)
|
||||
{
|
||||
done = 1;
|
||||
class_add_behavior([NSGMutableSet class], [NSGSet class]);
|
||||
if (self == [NSGMutableSet class]) {
|
||||
class_add_behavior(self, [NSMutableSetNonCore class]);
|
||||
class_add_behavior(self, [NSGSet class]);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer
|
||||
- initWithCapacity: (unsigned)numItems
|
||||
implemented by behavior. */
|
||||
/* Designated initialiser */
|
||||
- (id) initWithCapacity: (unsigned)cap
|
||||
{
|
||||
FastMapInitWithZoneAndCapacity(&map, [self zone], cap);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Implemented by behavior:
|
||||
- (void) addObject: newObject;
|
||||
- (void) removeObject: anObject
|
||||
*/
|
||||
- (void) addObject: (NSObject*)anObject
|
||||
{
|
||||
FastMapNode node = FastMapNodeForKey(&map, (FastMapItem)anObject);
|
||||
|
||||
if (node == 0) {
|
||||
FastMapAddKey(&map, (FastMapItem)anObject);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeObject: (NSObject *)anObject
|
||||
{
|
||||
FastMapRemoveKey(&map, (FastMapItem)anObject);
|
||||
}
|
||||
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
[self empty];
|
||||
}
|
||||
|
||||
/* To deal with behavior over-enthusiasm. Will be fixed later. */
|
||||
- (BOOL) isEqual: other
|
||||
{
|
||||
return [super isEqual:other];
|
||||
FastMapCleanMap(&map);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
308
Source/NSSet.m
308
Source/NSSet.m
|
@ -1,5 +1,5 @@
|
|||
/* NSSet - Set object to store key/value pairs
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: Sep 1995
|
||||
|
@ -22,18 +22,33 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <gnustep/base/behavior.h>
|
||||
#include <Foundation/NSSet.h>
|
||||
#include <Foundation/NSGSet.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSUtilities.h>
|
||||
#include <gnustep/base/NSString.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <assert.h>
|
||||
|
||||
@interface NSSetNonCore : NSSet
|
||||
@end
|
||||
@interface NSMutableSetNonCore: NSMutableSet
|
||||
@end
|
||||
|
||||
@implementation NSSet
|
||||
|
||||
static Class NSSet_concrete_class;
|
||||
static Class NSMutableSet_concrete_class;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSSet class]) {
|
||||
NSSet_concrete_class = [NSGSet class];
|
||||
NSMutableSet_concrete_class = [NSGMutableSet class];
|
||||
behavior_class_add_class(self, [NSSetNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void) _setConcreteClass: (Class)c
|
||||
{
|
||||
NSSet_concrete_class = c;
|
||||
|
@ -54,17 +69,6 @@ static Class NSMutableSet_concrete_class;
|
|||
return NSMutableSet_concrete_class;
|
||||
}
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
NSSet_concrete_class = [NSGSet class];
|
||||
NSMutableSet_concrete_class = [NSGMutableSet class];
|
||||
}
|
||||
|
||||
+ allocWithZone: (NSZone*)z
|
||||
{
|
||||
return NSAllocateObject([self _concreteClass], 0, z);
|
||||
}
|
||||
|
||||
+ set
|
||||
{
|
||||
return [[[self alloc] init]
|
||||
|
@ -81,9 +85,7 @@ static Class NSMutableSet_concrete_class;
|
|||
|
||||
+ setWithArray: (NSArray*)objects
|
||||
{
|
||||
/* xxx Only works because NSArray also responds to objectEnumerator
|
||||
and nextObject. */
|
||||
return [[[self alloc] initWithSet:(NSSet*)objects]
|
||||
return [[[self alloc] initWithArray: objects]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
|
@ -94,34 +96,6 @@ static Class NSMutableSet_concrete_class;
|
|||
autorelease];
|
||||
}
|
||||
|
||||
/* Same as NSArray */
|
||||
/* Not very pretty... */
|
||||
#define INITIAL_OBJECTS_SIZE 10
|
||||
- initWithObjects: firstObject rest: (va_list)ap
|
||||
{
|
||||
id *objects;
|
||||
int i = 0;
|
||||
int s = INITIAL_OBJECTS_SIZE;
|
||||
|
||||
OBJC_MALLOC(objects, id, s);
|
||||
if (firstObject != nil)
|
||||
{
|
||||
objects[i++] = firstObject;
|
||||
while ((objects[i++] = va_arg(ap, id)))
|
||||
{
|
||||
if (i >= s)
|
||||
{
|
||||
s *= 2;
|
||||
OBJC_REALLOC(objects, id, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
self = [self initWithObjects:objects count:i-1];
|
||||
OBJC_FREE(objects);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Same as NSArray */
|
||||
+ setWithObjects: firstObject, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -131,6 +105,11 @@ static Class NSMutableSet_concrete_class;
|
|||
return [self autorelease];
|
||||
}
|
||||
|
||||
+ allocWithZone: (NSZone*)z
|
||||
{
|
||||
return NSAllocateObject([self _concreteClass], 0, z);
|
||||
}
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithObjects: (id*)objects
|
||||
count: (unsigned)count
|
||||
|
@ -139,11 +118,121 @@ static Class NSMutableSet_concrete_class;
|
|||
return 0;
|
||||
}
|
||||
|
||||
- initWithArray: (NSArray*)array
|
||||
- initWithCoder: aCoder
|
||||
{
|
||||
/* xxx Only works because NSArray also responds to objectEnumerator
|
||||
and nextObject. */
|
||||
return [self initWithSet:(NSSet*)array];
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- member: anObject
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- copyWithZone: (NSZone*)z
|
||||
{
|
||||
/* a deep copy */
|
||||
int count = [self count];
|
||||
id objects[count];
|
||||
id enumerator = [self objectEnumerator];
|
||||
id o;
|
||||
NSSet *newSet;
|
||||
int i;
|
||||
BOOL needCopy = [self isKindOfClass: [NSMutableSet class]];
|
||||
|
||||
if (NSShouldRetainWithZone(self, z) == NO)
|
||||
needCopy = YES;
|
||||
|
||||
for (i = 0; (o = [enumerator nextObject]); i++)
|
||||
{
|
||||
objects[i] = [o copyWithZone:z];
|
||||
if (objects[i] != o)
|
||||
needCopy = YES;
|
||||
}
|
||||
if (needCopy)
|
||||
newSet = [[[[self class] _concreteClass] allocWithZone: z]
|
||||
initWithObjects:objects
|
||||
count:count];
|
||||
else
|
||||
newSet = [self retain];
|
||||
for (i = 0; i < count; i++)
|
||||
[objects[i] release];
|
||||
return newSet;
|
||||
}
|
||||
|
||||
- mutableCopyWithZone: (NSZone*)z
|
||||
{
|
||||
/* a shallow copy */
|
||||
return [[[[self class] _mutableConcreteClass] allocWithZone: z]
|
||||
initWithSet: self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSSetNonCore
|
||||
|
||||
/* Same as NSArray */
|
||||
- initWithObjects: firstObject rest: (va_list)ap
|
||||
{
|
||||
register unsigned i;
|
||||
register unsigned curSize;
|
||||
auto unsigned prevSize;
|
||||
auto unsigned newSize;
|
||||
auto id *objsArray;
|
||||
auto id tmpId;
|
||||
|
||||
/* Do initial allocation. */
|
||||
prevSize = 3;
|
||||
curSize = 5;
|
||||
OBJC_MALLOC(objsArray, id, curSize);
|
||||
tmpId = firstObject;
|
||||
|
||||
/* Loop through adding objects to array until a nil is
|
||||
* found.
|
||||
*/
|
||||
for (i = 0; tmpId != nil; i++)
|
||||
{
|
||||
/* Put id into array. */
|
||||
objsArray[i] = tmpId;
|
||||
|
||||
/* If the index equals the current size, increase size. */
|
||||
if (i == curSize - 1)
|
||||
{
|
||||
/* Fibonacci series. Supposedly, for this application,
|
||||
* the fibonacci series will be more memory efficient.
|
||||
*/
|
||||
newSize = prevSize + curSize;
|
||||
prevSize = curSize;
|
||||
curSize = newSize;
|
||||
|
||||
/* Reallocate object array. */
|
||||
OBJC_REALLOC(objsArray, id, curSize);
|
||||
}
|
||||
tmpId = va_arg(ap, id);
|
||||
}
|
||||
va_end( ap );
|
||||
|
||||
/* Put object ids into NSSet. */
|
||||
self = [self initWithObjects: objsArray count: i];
|
||||
OBJC_FREE( objsArray );
|
||||
return( self );
|
||||
}
|
||||
|
||||
/* Same as NSArray */
|
||||
|
@ -162,6 +251,21 @@ static Class NSMutableSet_concrete_class;
|
|||
return [self initWithObjects:NULL count:0];
|
||||
}
|
||||
|
||||
- initWithArray: (NSArray*)other
|
||||
{
|
||||
unsigned count = [other count];
|
||||
|
||||
if (count == 0) {
|
||||
return [self init];
|
||||
}
|
||||
else {
|
||||
id objs[count];
|
||||
|
||||
[other getObjects: objs];
|
||||
return [self initWithObjects: objs count: count];
|
||||
}
|
||||
}
|
||||
|
||||
- initWithSet: (NSSet*)other copyItems: (BOOL)flag
|
||||
{
|
||||
int c = [other count];
|
||||
|
@ -176,7 +280,11 @@ static Class NSMutableSet_concrete_class;
|
|||
os[i] = o;
|
||||
i++;
|
||||
}
|
||||
return [self initWithObjects:os count:c];
|
||||
self = [self initWithObjects:os count:c];
|
||||
if (flag)
|
||||
while (--i)
|
||||
[os[i] release];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithSet: (NSSet*)other
|
||||
|
@ -216,23 +324,6 @@ static Class NSMutableSet_concrete_class;
|
|||
return (([self member:anObject]) ? YES : NO);
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- member: anObject
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerform: (SEL)aSelector
|
||||
{
|
||||
id o, e = [self objectEnumerator];
|
||||
|
@ -322,62 +413,16 @@ static Class NSMutableSet_concrete_class;
|
|||
return [[self allObjects] descriptionWithLocale: locale];
|
||||
}
|
||||
|
||||
- copyWithZone: (NSZone*)z
|
||||
{
|
||||
/* a deep copy */
|
||||
int count = [self count];
|
||||
id objects[count];
|
||||
id enumerator = [self objectEnumerator];
|
||||
id o;
|
||||
NSSet *newSet;
|
||||
int i;
|
||||
BOOL needCopy = [self isKindOfClass: [NSMutableSet class]];
|
||||
|
||||
if (NSShouldRetainWithZone(self, z) == NO)
|
||||
needCopy = YES;
|
||||
|
||||
for (i = 0; (o = [enumerator nextObject]); i++)
|
||||
{
|
||||
objects[i] = [o copyWithZone:z];
|
||||
if (objects[i] != o)
|
||||
needCopy = YES;
|
||||
}
|
||||
if (needCopy)
|
||||
newSet = [[[[self class] _concreteClass] alloc]
|
||||
initWithObjects:objects
|
||||
count:count];
|
||||
else
|
||||
newSet = [self retain];
|
||||
for (i = 0; i < count; i++)
|
||||
[objects[i] release];
|
||||
return newSet;
|
||||
}
|
||||
|
||||
- mutableCopyWithZone: (NSZone*)z
|
||||
{
|
||||
/* a shallow copy */
|
||||
return [[[[[self class] _mutableConcreteClass] _mutableConcreteClass] alloc]
|
||||
initWithSet:self];
|
||||
}
|
||||
|
||||
- initWithCoder: aCoder
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSMutableSet
|
||||
|
||||
+ allocWithZone: (NSZone*)z
|
||||
+ (void) initialize
|
||||
{
|
||||
return NSAllocateObject([self _mutableConcreteClass], 0, z);
|
||||
if (self == [NSMutableSet class]) {
|
||||
behavior_class_add_class(self, [NSMutableSetNonCore class]);
|
||||
behavior_class_add_class(self, [NSSetNonCore class]);
|
||||
}
|
||||
}
|
||||
|
||||
+ setWithCapacity: (unsigned)numItems
|
||||
|
@ -386,12 +431,31 @@ static Class NSMutableSet_concrete_class;
|
|||
autorelease];
|
||||
}
|
||||
|
||||
+ allocWithZone: (NSZone*)z
|
||||
{
|
||||
return NSAllocateObject([self _mutableConcreteClass], 0, z);
|
||||
}
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithCapacity: (unsigned)numItems
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) addObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSMutableSetNonCore
|
||||
|
||||
/* Override superclass's designated initializer */
|
||||
- initWithObjects: (id*)objects
|
||||
count: (unsigned)count
|
||||
|
@ -402,11 +466,6 @@ static Class NSMutableSet_concrete_class;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void) addObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) addObjectsFromArray: (NSArray*)array
|
||||
{
|
||||
int i, c = [array count];
|
||||
|
@ -448,9 +507,4 @@ static Class NSMutableSet_concrete_class;
|
|||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in a new issue