mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Overhaul for new collection class scheme to improve distributed
objects and NeXT-compatibility. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@947 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
7853b9d1b0
commit
f46b4d9b55
16 changed files with 776 additions and 2171 deletions
|
@ -6,44 +6,35 @@
|
|||
|
||||
#include <objects/Archiver.h>
|
||||
#include <objects/TextCStream.h>
|
||||
#include <objects/Set.h>
|
||||
#include <objects/EltNodeCollector.h>
|
||||
#include <objects/LinkedList.h>
|
||||
#include <objects/LinkedListEltNode.h>
|
||||
#include <objects/Array.h>
|
||||
#include <objects/Dictionary.h>
|
||||
#include <objects/NSString.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
id set, ll;
|
||||
id array, dictionary;
|
||||
id archiver;
|
||||
id name;
|
||||
id arp;
|
||||
|
||||
int i;
|
||||
|
||||
[NSObject enableDoubleReleaseCheck: YES];
|
||||
arp = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
/* Create a Set of int's
|
||||
and a LinkedList of float's */
|
||||
set = [[Set alloc] initWithType:@encode(int)];
|
||||
ll = [[EltNodeCollector alloc] initWithType:@encode(float)
|
||||
nodeCollector:[[LinkedList alloc] init]
|
||||
nodeClass:[LinkedListEltNode class]];
|
||||
/* Create an Array and Dictionary */
|
||||
array = [Array new];
|
||||
dictionary = [Dictionary new];
|
||||
|
||||
/* Populate the Set and display it */
|
||||
[set addElement:1234567];
|
||||
[set addElement:2345678];
|
||||
[set addElement:3456789];
|
||||
[set addElement:4567891];
|
||||
[set addElement:5678912];
|
||||
[set printForDebugger];
|
||||
|
||||
/* Populate the LinkedList and display it */
|
||||
[ll addElement:1.2f];
|
||||
[ll addElement:(float)3.4];
|
||||
[ll addElement:(float)5.6];
|
||||
[ll addElement:(float)7.8];
|
||||
[ll addElement:(float)9.0];
|
||||
[ll printForDebugger];
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
[array addObject: [NSNumber numberWithInt: i]];
|
||||
[dictionary putObject: [NSNumber numberWithInt: i]
|
||||
atKey: [NSNumber numberWithInt: i*i]];
|
||||
}
|
||||
[array printForDebugger];
|
||||
[dictionary printForDebugger];
|
||||
|
||||
/* Write them to a file */
|
||||
|
||||
|
@ -52,12 +43,14 @@ int main()
|
|||
coding. */
|
||||
archiver = [[Archiver alloc] initForWritingToFile: @"./textcoding.txt"
|
||||
withCStreamClass: [TextCStream class]];
|
||||
[archiver encodeObject:set withName:@"Test Set"];
|
||||
[archiver encodeObject:ll withName:@"Test EltNodeCollector LinkedList"];
|
||||
[archiver encodeObject: array
|
||||
withName:@"Test Array"];
|
||||
[archiver encodeObject: dictionary
|
||||
withName:@"Test Dictionary"];
|
||||
|
||||
/* Release the objects that were coded */
|
||||
[set release];
|
||||
[ll release];
|
||||
[array release];
|
||||
[dictionary release];
|
||||
|
||||
/* Close the archiver, (and thus flush the stream); then release it.
|
||||
We must separate the idea of "closing" a stream and
|
||||
|
@ -72,21 +65,21 @@ int main()
|
|||
/* First create the unarchiver */
|
||||
archiver = [Unarchiver newReadingFromFile: @"./textcoding.txt"];
|
||||
|
||||
/* Read in the Set */
|
||||
[archiver decodeObjectAt:&set withName:&name];
|
||||
/* Read in the Array */
|
||||
[archiver decodeObjectAt: &array withName: &name];
|
||||
printf("got object named %@\n", name);
|
||||
|
||||
/* Read in the LinkedList */
|
||||
[archiver decodeObjectAt:&ll withName:&name];
|
||||
/* Read in the Dictionary */
|
||||
[archiver decodeObjectAt: &dictionary withName: &name];
|
||||
printf("got object named %@\n", name);
|
||||
|
||||
/* Display what we read, to make sure it matches what we wrote */
|
||||
[set printForDebugger];
|
||||
[ll printForDebugger];
|
||||
[array printForDebugger];
|
||||
[dictionary printForDebugger];
|
||||
|
||||
/* Relase the objects we read */
|
||||
[set release];
|
||||
[ll release];
|
||||
[array release];
|
||||
[dictionary release];
|
||||
|
||||
/* Release the unarchiver. */
|
||||
[archiver release];
|
||||
|
|
231
Source/Array.m
231
Source/Array.m
|
@ -24,13 +24,61 @@
|
|||
#include <objects/Array.h>
|
||||
#include <objects/ArrayPrivate.h>
|
||||
#include <objects/NSString.h>
|
||||
#include <objects/OrderedCollection.h>
|
||||
|
||||
@implementation ConstantArray
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithObjects: (id*)objs count: (unsigned)c
|
||||
{
|
||||
_count = c;
|
||||
OBJC_MALLOC(_contents_array, id, _count);
|
||||
while (c--)
|
||||
_contents_array[c] = objs[c];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
Array *copy = [super emptyCopy];
|
||||
copy->_count = 0;
|
||||
OBJC_MALLOC(copy->_contents_array, id, copy->_capacity);
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void) _collectionDealloc
|
||||
{
|
||||
OBJC_FREE(_contents_array);
|
||||
[super _collectionDealloc];
|
||||
}
|
||||
|
||||
|
||||
// GETTING ELEMENTS BY INDEX;
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
return _contents_array[index];
|
||||
}
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation Array
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Array class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
class_add_behavior (self, [OrderedCollection class]);
|
||||
}
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
@ -47,17 +95,14 @@
|
|||
{
|
||||
return DEFAULT_ARRAY_GROW_FACTOR;
|
||||
}
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
capacity: (unsigned)aCapacity
|
||||
|
||||
/* This is the designated initializer for this class */
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
[super initWithType:contentEncoding];
|
||||
_comparison_function = elt_get_comparison_function(contentEncoding);
|
||||
_grow_factor = [[self class] defaultGrowFactor];
|
||||
_count = 0;
|
||||
_capacity = (aCapacity < 1) ? 1 : aCapacity;
|
||||
OBJC_MALLOC(_contents_array, elt, _capacity);
|
||||
OBJC_MALLOC(_contents_array, id, _capacity);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -65,12 +110,7 @@
|
|||
|
||||
- (void) _encodeCollectionWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
const char *encoding = [self contentType];
|
||||
|
||||
[super _encodeCollectionWithCoder:coder];
|
||||
[coder encodeValueOfCType:@encode(char*)
|
||||
at:&encoding
|
||||
withName:@"Array Encoding Type"];
|
||||
[coder encodeValueOfCType:@encode(unsigned)
|
||||
at:&_grow_factor
|
||||
withName:@"Array Grow Factor"];
|
||||
|
@ -81,12 +121,7 @@
|
|||
|
||||
- _initCollectionWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
char *encoding;
|
||||
[super _initCollectionWithCoder:coder];
|
||||
[coder decodeValueOfCType:@encode(char*)
|
||||
at:&encoding
|
||||
withName:NULL];
|
||||
_comparison_function = elt_get_comparison_function(encoding);
|
||||
[coder decodeValueOfCType:@encode(unsigned)
|
||||
at:&_grow_factor
|
||||
withName:NULL];
|
||||
|
@ -94,76 +129,23 @@
|
|||
[coder decodeValueOfCType:@encode(unsigned)
|
||||
at:&_capacity
|
||||
withName:NULL];
|
||||
OBJC_MALLOC(_contents_array, elt, _capacity);
|
||||
OBJC_MALLOC(_contents_array, id, _capacity);
|
||||
return self;
|
||||
}
|
||||
|
||||
- _writeInit: (TypedStream*)aStream
|
||||
/* Override superclass' designated initializer to call ours */
|
||||
- initWithObjects: (id*)objs count: (unsigned)c
|
||||
{
|
||||
const char *encoding = [self contentType];
|
||||
|
||||
[super _writeInit: aStream];
|
||||
// This implicitly archives the _comparison_function;
|
||||
objc_write_type(aStream, @encode(char*), &encoding);
|
||||
objc_write_type(aStream, @encode(unsigned int), &_grow_factor);
|
||||
objc_write_type(aStream, @encode(unsigned int), &_capacity);
|
||||
return self;
|
||||
}
|
||||
|
||||
- _readInit: (TypedStream*)aStream
|
||||
{
|
||||
char *encoding;
|
||||
|
||||
[super _readInit: aStream];
|
||||
objc_read_type(aStream, @encode(char*), &encoding);
|
||||
_comparison_function = elt_get_comparison_function(encoding);
|
||||
objc_read_type(aStream, @encode(unsigned int), &_grow_factor);
|
||||
_count = 0;
|
||||
objc_read_type(aStream, @encode(unsigned int), &_capacity);
|
||||
OBJC_MALLOC(_contents_array, elt, _capacity);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
Array *copy = [super emptyCopy];
|
||||
copy->_count = 0;
|
||||
OBJC_MALLOC(copy->_contents_array, elt, copy->_capacity);
|
||||
return copy;
|
||||
int i;
|
||||
[self initWithCapacity: c];
|
||||
for (i = 0; i < c; i++)
|
||||
[self insertObject: objs[i] atIndex:i]; // xxx this most efficient method?
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- _empty
|
||||
- (void) _empty
|
||||
{
|
||||
_count = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) _collectionDealloc
|
||||
{
|
||||
OBJC_FREE(_contents_array);
|
||||
[super _collectionDealloc];
|
||||
}
|
||||
|
||||
- initWithContentsOf: (id <Collecting>)aCollection
|
||||
{
|
||||
[self initWithType:[aCollection contentType]
|
||||
capacity:[aCollection count]];
|
||||
[self addContentsOf:aCollection];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
return [self initWithType:@encode(id) capacity:aCapacity];
|
||||
}
|
||||
|
||||
/* Catch designated initializer for IndexedCollection */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
{
|
||||
return [self initWithType:contentEncoding
|
||||
capacity:[[self class] defaultCapacity]];
|
||||
}
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
@ -171,13 +153,12 @@
|
|||
/* This is the only method that changes the value of the instance
|
||||
variable _capacity, except for "-initDescription:capacity:" */
|
||||
|
||||
- setCapacity: (unsigned)newCapacity
|
||||
- (void) setCapacity: (unsigned)newCapacity
|
||||
{
|
||||
if (newCapacity > _count) {
|
||||
_capacity = newCapacity;
|
||||
OBJC_REALLOC(_contents_array, elt, _capacity);
|
||||
OBJC_REALLOC(_contents_array, id, _capacity);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned) growFactor
|
||||
|
@ -185,109 +166,73 @@
|
|||
return _grow_factor;
|
||||
}
|
||||
|
||||
- setGrowFactor: (unsigned)aNum;
|
||||
- (void) setGrowFactor: (unsigned)aNum;
|
||||
{
|
||||
_grow_factor = aNum;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
// ADDING;
|
||||
|
||||
- appendElement: (elt)newElement
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
RETAIN_ELT(newElement);
|
||||
_contents_array[_count-1] = newElement;
|
||||
return self;
|
||||
[newObject retain];
|
||||
_contents_array[_count-1] = newObject;
|
||||
}
|
||||
|
||||
- prependElement: (elt)newElement
|
||||
- (void) prependObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
RETAIN_ELT(newElement);
|
||||
[newObject retain];
|
||||
makeHoleAt(self, 0);
|
||||
_contents_array[0] = newElement;
|
||||
return self;
|
||||
_contents_array[0] = newObject;
|
||||
}
|
||||
|
||||
- insertElement: (elt)newElement atIndex: (unsigned)index
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count+1);
|
||||
incrementCount(self);
|
||||
RETAIN_ELT(newElement);
|
||||
[newObject retain];
|
||||
makeHoleAt(self, index);
|
||||
_contents_array[index] = newElement;
|
||||
return self;
|
||||
_contents_array[index] = newObject;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// REMOVING, REPLACING AND SWAPPING;
|
||||
|
||||
- (elt) removeElementAtIndex: (unsigned)index
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
elt ret;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
ret = _contents_array[index];
|
||||
[_contents_array[index] release];
|
||||
fillHoleAt(self, index);
|
||||
decrementCount(self);
|
||||
return AUTORELEASE_ELT(ret);
|
||||
}
|
||||
|
||||
/* We could be more efficient if we override these also.
|
||||
- (elt) removeFirstElement
|
||||
- (elt) removeLastElement; */
|
||||
- removeFirstObject
|
||||
- removeLastObject;
|
||||
If you do, remember, you will have to implement this methods
|
||||
in GapArray also! */
|
||||
|
||||
|
||||
- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
elt ret;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
RETAIN_ELT(newElement);
|
||||
ret = _contents_array[index];
|
||||
_contents_array[index] = newElement;
|
||||
return AUTORELEASE_ELT(ret);
|
||||
[newObject retain];
|
||||
[_contents_array[index] release];
|
||||
_contents_array[index] = newObject;
|
||||
}
|
||||
|
||||
- swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
{
|
||||
elt tmp;
|
||||
id tmp;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index1, _count);
|
||||
CHECK_INDEX_RANGE_ERROR(index2, _count);
|
||||
tmp = _contents_array[index1];
|
||||
_contents_array[index1] = _contents_array[index2];
|
||||
_contents_array[index2] = tmp;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
// GETTING ELEMENTS BY INDEX;
|
||||
|
||||
- (elt) elementAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
return _contents_array[index];
|
||||
}
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (int(*)(elt,elt)) comparisonFunction
|
||||
{
|
||||
return _comparison_function;
|
||||
}
|
||||
|
||||
- (const char *) contentType
|
||||
{
|
||||
return elt_get_encoding(_comparison_function);
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
259
Source/Bag.m
259
Source/Bag.m
|
@ -1,8 +1,8 @@
|
|||
/* Implementation for Objective-C Bag collection object
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
|
@ -24,33 +24,55 @@
|
|||
#include <objects/Bag.h>
|
||||
#include <objects/CollectionPrivate.h>
|
||||
|
||||
#define DEFAULT_BAG_CAPACITY 32
|
||||
|
||||
@implementation Bag
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Bag class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
}
|
||||
// MANAGING CAPACITY;
|
||||
|
||||
/* Eventually we will want to have better capacity management,
|
||||
potentially keep default capacity as a class variable. */
|
||||
|
||||
+ (unsigned) defaultCapacity
|
||||
{
|
||||
return DEFAULT_BAG_CAPACITY;
|
||||
}
|
||||
|
||||
// INITIALIZING AND FREEING;
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
/* Override designated initializer of superclass */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
capacity: (unsigned)aCapacity
|
||||
- initWithCapacity: (unsigned)cap
|
||||
{
|
||||
[super initWithType:contentEncoding
|
||||
capacity:aCapacity];
|
||||
_contents_map = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks,
|
||||
cap);
|
||||
_count = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Override Collection's designated initializer */
|
||||
- initWithObjects: (id*)objs count: (unsigned)count
|
||||
{
|
||||
[self initWithCapacity: count];
|
||||
while (count--)
|
||||
[self addObject: objs[count]];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- _readInit: (TypedStream*)aStream
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[super _readInit:aStream];
|
||||
_count = 0;
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -58,94 +80,70 @@
|
|||
- emptyCopy
|
||||
{
|
||||
Bag *copy = [super emptyCopy];
|
||||
copy->_contents_map = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks,
|
||||
0);
|
||||
copy->_count = 0;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- _empty
|
||||
- (void) dealloc
|
||||
{
|
||||
coll_hash_empty(_contents_hash);
|
||||
NSFreeMapTable (_contents_map);
|
||||
[super _collectionDealloc];
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
NSResetMapTable (_contents_map);
|
||||
_count = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
// ADDING;
|
||||
|
||||
- addElement: (elt)newElement withOccurrences: (unsigned)count
|
||||
- (void) addObject: newObject withOccurrences: (unsigned)count
|
||||
{
|
||||
coll_node_ptr node =
|
||||
coll_hash_node_for_key(_contents_hash, newElement);
|
||||
if (node)
|
||||
node->value.unsigned_int_u += count;
|
||||
else
|
||||
coll_hash_add(&_contents_hash, newElement, count);
|
||||
unsigned new_count = (unsigned) NSMapGet (_contents_map, newObject);
|
||||
new_count += count;
|
||||
NSMapInsert (_contents_map, newObject, (void*)new_count);
|
||||
_count += count;
|
||||
while (count--)
|
||||
RETAIN_ELT(newElement);
|
||||
return self;
|
||||
}
|
||||
|
||||
- addElement: (elt)newElement
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
return [self addElement:newElement withOccurrences:1];
|
||||
[self addObject: newObject withOccurrences: 1];
|
||||
}
|
||||
|
||||
|
||||
// REMOVING AND REPLACING;
|
||||
|
||||
- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count
|
||||
- (void) removeObject: oldObject occurrences: (unsigned)count
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
unsigned c = (unsigned) NSMapGet (_contents_map, oldObject);
|
||||
if (c)
|
||||
{
|
||||
return ELEMENT_NOT_FOUND_ERROR(oldElement);
|
||||
if (c <= count)
|
||||
{
|
||||
NSMapRemove (_contents_map, oldObject);
|
||||
_count -= c;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSMapInsert (_contents_map, oldObject, (void*)(c - count));
|
||||
_count -= count;
|
||||
}
|
||||
}
|
||||
return [self removeElement:oldElement occurrences:count
|
||||
ifAbsentCall:err];
|
||||
}
|
||||
|
||||
- (elt) removeElement:(elt)oldElement occurrences: (unsigned)count
|
||||
ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
coll_node_ptr node =
|
||||
coll_hash_node_for_key(_contents_hash, oldElement);
|
||||
if (!node || node->value.unsigned_int_u < count)
|
||||
{
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
}
|
||||
if (node->value.unsigned_int_u > count)
|
||||
{
|
||||
(node->value.unsigned_int_u) -= count;
|
||||
}
|
||||
else /* (node->value.unsigned_int_u == count) */
|
||||
{
|
||||
coll_hash_remove(_contents_hash, oldElement);
|
||||
}
|
||||
_count -= count;
|
||||
while (count-- > 0)
|
||||
RELEASE_ELT(oldElement);
|
||||
return AUTORELEASE_ELT(oldElement);
|
||||
[self removeObject: oldObject occurrences:1];
|
||||
}
|
||||
|
||||
- (elt) removeElement: (elt)oldElement ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
- (void) uniqueContents
|
||||
{
|
||||
return [self removeElement:oldElement occurrences:1 ifAbsentCall:excFunc];
|
||||
}
|
||||
|
||||
- uniqueContents
|
||||
{
|
||||
void *state = 0;
|
||||
coll_node_ptr node = 0;
|
||||
|
||||
_count = 0;
|
||||
while ((node = coll_hash_next(_contents_hash, &state)))
|
||||
{
|
||||
while ((node->value.unsigned_int_u)-- > 0)
|
||||
RELEASE_ELT(node->key);
|
||||
node->value.unsigned_int_u = 1;
|
||||
_count++;
|
||||
}
|
||||
return self;
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,18 +156,12 @@
|
|||
|
||||
- (unsigned) uniqueCount
|
||||
{
|
||||
return _contents_hash->used;
|
||||
return NSCountMapTable (_contents_map);
|
||||
}
|
||||
|
||||
- (unsigned) occurrencesOfElement: (elt)anElement
|
||||
- (unsigned) occurrencesOfObject: anObject
|
||||
{
|
||||
coll_node_ptr node =
|
||||
coll_hash_node_for_key(_contents_hash, anElement);
|
||||
|
||||
if (node)
|
||||
return node->value.unsigned_int_u;
|
||||
else
|
||||
return 0;
|
||||
return (unsigned) NSMapGet (_contents_map, anObject);
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,34 +169,22 @@
|
|||
|
||||
struct BagEnumState
|
||||
{
|
||||
void *state;
|
||||
coll_node_ptr node;
|
||||
NSMapEnumerator me;
|
||||
id object;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
#define ES ((struct BagEnumState *) *enumState)
|
||||
|
||||
- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
if (!(*enumState))
|
||||
{
|
||||
}
|
||||
else if (ES->count >= ES->node->value.unsigned_int_u)
|
||||
{
|
||||
/* time to get the next different element */
|
||||
ES->node = coll_hash_next(_contents_hash, &(ES->state));
|
||||
ES->count = 0;
|
||||
}
|
||||
if (!(ES->node))
|
||||
{
|
||||
/* at end of enumeration */
|
||||
OBJC_FREE(*enumState);
|
||||
*enumState = 0;
|
||||
return NO;
|
||||
}
|
||||
*anElementPtr = ES->node->key;
|
||||
(ES->count)++;
|
||||
return YES;
|
||||
if (!(ES->count))
|
||||
if (!NSNextMapEnumeratorPair (&(ES->me),
|
||||
(void**) &(ES->object),
|
||||
(void**) &(ES->count)))
|
||||
return NO_OBJECT;
|
||||
ES->count--;
|
||||
return ES->object;
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
|
@ -213,81 +193,16 @@ struct BagEnumState
|
|||
void *vp;
|
||||
void **enumState = &vp;
|
||||
OBJC_MALLOC(*enumState, struct BagEnumState, 1);
|
||||
ES->state = 0;
|
||||
ES->node = coll_hash_next(_contents_hash, &(ES->state));
|
||||
ES->me = NSEnumerateMapTable (_contents_map);
|
||||
ES->object = nil;
|
||||
ES->count = 0;
|
||||
return vp;
|
||||
}
|
||||
|
||||
- freeEnumState: (void**)enumState
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
if (*enumState)
|
||||
OBJC_FREE(*enumState);
|
||||
return self;
|
||||
}
|
||||
|
||||
- withElementsCall: (void(*)(elt))aFunc whileTrue:(BOOL *)flag
|
||||
{
|
||||
int i;
|
||||
void *state = 0;
|
||||
coll_node_ptr node;
|
||||
|
||||
while ((node = coll_hash_next(_contents_hash, &state)))
|
||||
{
|
||||
for (i = 0; i < node->value.unsigned_int_u; i++)
|
||||
{
|
||||
if (!(*flag))
|
||||
return self;
|
||||
(*aFunc)(node->key);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- withElementsCall: (void(*)(elt))aFunc
|
||||
{
|
||||
int i;
|
||||
void *state = 0;
|
||||
coll_node_ptr node;
|
||||
int test = 0;
|
||||
|
||||
while ((node = coll_hash_next(_contents_hash, &state)))
|
||||
{
|
||||
test++;
|
||||
for (i = 0; i < node->value.unsigned_int_u; i++)
|
||||
{
|
||||
(*aFunc)(node->key);
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
// OBJECT-COMPATIBLE MESSAGE NAMES;
|
||||
|
||||
- addObject: newObject withOccurrences: (unsigned)count
|
||||
{
|
||||
return [self addElement:newObject withOccurrences:count];
|
||||
}
|
||||
|
||||
- removeObject: oldObject occurrences: (unsigned)count
|
||||
{
|
||||
id err(arglist_t argFrame)
|
||||
{
|
||||
return ELEMENT_NOT_FOUND_ERROR(oldObject);
|
||||
}
|
||||
return [self removeObject:oldObject occurrences:count ifAbsentCall:err];
|
||||
}
|
||||
|
||||
- removeObject: oldObject occurrences: (unsigned)count
|
||||
ifAbsentCall: (id(*)(arglist_t))excFunc
|
||||
{
|
||||
elt elt_exc(arglist_t argFrame)
|
||||
{
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
}
|
||||
return [self removeElement:oldObject occurrences:count
|
||||
ifAbsentCall:elt_exc].id_u;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Implementation for GNU Objective-C ConstantString object
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993,1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
@ -29,10 +29,9 @@
|
|||
// INITIALIZING;
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- empty
|
||||
- (void) empty
|
||||
{
|
||||
[self shouldNotImplement:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
// REPLACING;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* Implementation for Objective-C Dictionary collection object
|
||||
Copyright (C) 1993,1994, 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
|
@ -28,12 +28,6 @@
|
|||
|
||||
@implementation Dictionary
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Dictionary class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
}
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
||||
/* Eventually we will want to have better capacity management,
|
||||
|
@ -47,61 +41,35 @@
|
|||
// INITIALIZING;
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
keyType: (const char *)keyEncoding
|
||||
capacity: (unsigned)aCapacity
|
||||
- initWithCapacity: (unsigned)cap
|
||||
{
|
||||
[super initWithType:contentEncoding
|
||||
keyType:keyEncoding];
|
||||
_contents_hash =
|
||||
coll_hash_new(POWER_OF_TWO(aCapacity),
|
||||
elt_get_hash_function(keyEncoding),
|
||||
elt_get_comparison_function(keyEncoding));
|
||||
_comparison_function = elt_get_comparison_function(contentEncoding);
|
||||
_contents_hash = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
cap);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Override the KeyedCollection designated initializer */
|
||||
- initWithObjects: (id*)objects forKeys: (id*)keys count: (unsigned)c
|
||||
{
|
||||
[self initWithCapacity: c];
|
||||
while (c--)
|
||||
[self putObject: objects[c] atKey: keys[c]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
return [self initWithCapacity: DEFAULT_DICTIONARY_CAPACITY];
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
- _initCollectionWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
+ newWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- _writeInit: (TypedStream*)aStream
|
||||
{
|
||||
const char *ce = [self contentType];
|
||||
const char *ke = [self keyType];
|
||||
|
||||
[super _writeInit:aStream];
|
||||
/* This implicitly archives the key's comparison and hash functions */
|
||||
objc_write_type(aStream, @encode(char*), &ke);
|
||||
objc_write_type(aStream, @encode(unsigned int), &(_contents_hash->size));
|
||||
/* This implicitly archives the content's comparison function */
|
||||
objc_write_type(aStream, @encode(char*), &ce);
|
||||
return self;
|
||||
}
|
||||
|
||||
- _readInit: (TypedStream*)aStream
|
||||
{
|
||||
char *keyEncoding, *contentEncoding;
|
||||
unsigned int size;
|
||||
|
||||
[super _readInit:aStream];
|
||||
objc_read_type(aStream, @encode(char*), &keyEncoding);
|
||||
objc_read_type(aStream, @encode(unsigned int), &size);
|
||||
_contents_hash =
|
||||
coll_hash_new(size,
|
||||
elt_get_hash_function(keyEncoding),
|
||||
elt_get_comparison_function(keyEncoding));
|
||||
objc_read_type(aStream, @encode(char*), &contentEncoding);
|
||||
_comparison_function = elt_get_comparison_function(contentEncoding);
|
||||
_contents_hash = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
0);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -110,181 +78,105 @@
|
|||
- emptyCopy
|
||||
{
|
||||
Dictionary *copy = [super emptyCopy];
|
||||
copy->_contents_hash =
|
||||
coll_hash_new(_contents_hash->size,
|
||||
_contents_hash->hash_func,
|
||||
_contents_hash->compare_func);
|
||||
copy->_contents_hash = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
0);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* To make sure that former KeyedCollection init'ers go through
|
||||
Dictionary init, we override the designated initializer for
|
||||
KeyedCollection. */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
keyType: (const char *)keyEncoding
|
||||
- (void) dealloc
|
||||
{
|
||||
return [self initWithType:contentEncoding
|
||||
keyType:keyEncoding
|
||||
capacity:[[self class] defaultCapacity]];
|
||||
}
|
||||
|
||||
- initWithType: (const char *)contentEncoding
|
||||
capacity: (unsigned)aCapacity
|
||||
{
|
||||
return [self initWithType:contentEncoding
|
||||
keyType:@encode(id)
|
||||
capacity:aCapacity];
|
||||
}
|
||||
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
return [self initWithType:@encode(id)
|
||||
capacity:aCapacity];
|
||||
}
|
||||
|
||||
- (void) _collectionDealloc
|
||||
{
|
||||
coll_hash_delete(_contents_hash);
|
||||
NSFreeMapTable (_contents_hash);
|
||||
[super _collectionDealloc];
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- _empty
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
coll_hash_empty(_contents_hash);
|
||||
return self;
|
||||
NSResetMapTable (_contents_hash);
|
||||
}
|
||||
|
||||
|
||||
// ADDING OR REPLACING;
|
||||
|
||||
- addElement: (elt)anElement
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
return [self shouldNotImplement:_cmd];
|
||||
[self shouldNotImplement: _cmd];
|
||||
/* or should I make up some default behavior here?
|
||||
Base it on object conforming to <Associating> protocol, perhaps */
|
||||
}
|
||||
|
||||
- putElement: (elt)newContentElement atKey: (elt)aKey
|
||||
- (void) putObject: newObject atKey: aKey
|
||||
{
|
||||
coll_node_ptr node = coll_hash_node_for_key(_contents_hash, aKey);
|
||||
if (node)
|
||||
{
|
||||
RELEASE_ELT(node->value);
|
||||
node->value = newContentElement;
|
||||
}
|
||||
else
|
||||
coll_hash_add(&_contents_hash, aKey,
|
||||
newContentElement);
|
||||
RETAIN_ELT(newContentElement);
|
||||
return self;
|
||||
NSMapInsert (_contents_hash, aKey, newObject);
|
||||
}
|
||||
|
||||
|
||||
// REMOVING;
|
||||
|
||||
- (elt) removeElementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
- (void) removeObjectAtKey: aKey
|
||||
{
|
||||
coll_node_ptr node = coll_hash_node_for_key(_contents_hash, aKey);
|
||||
elt ret;
|
||||
|
||||
if (node)
|
||||
{
|
||||
ret = node->value;
|
||||
coll_hash_remove(_contents_hash, aKey);
|
||||
return AUTORELEASE_ELT(ret);
|
||||
}
|
||||
else
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
NSMapRemove (_contents_hash, aKey);
|
||||
}
|
||||
|
||||
- (elt) removeElement: (elt)oldElement ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
{
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
}
|
||||
elt key = [self keyElementOfElement:oldElement ifAbsentCall:err];
|
||||
return [self removeElementAtKey:key];
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// GETTING ELEMENTS;
|
||||
|
||||
- (elt) elementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
- objectAtKey: aKey
|
||||
{
|
||||
coll_node_ptr node = coll_hash_node_for_key(_contents_hash, aKey);
|
||||
if (node)
|
||||
return node->value;
|
||||
else
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
return NSMapGet (_contents_hash, aKey);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (int(*)(elt,elt)) comparisonFunction
|
||||
- (BOOL) containsKey: aKey
|
||||
{
|
||||
return _comparison_function;
|
||||
}
|
||||
|
||||
- (const char *) contentType
|
||||
{
|
||||
return elt_get_encoding(_comparison_function);
|
||||
}
|
||||
|
||||
- (const char *) keyType
|
||||
{
|
||||
return elt_get_encoding(_contents_hash->compare_func);
|
||||
}
|
||||
|
||||
- (BOOL) includesKey: (elt)aKey
|
||||
{
|
||||
if (coll_hash_node_for_key(_contents_hash, aKey))
|
||||
if (NSMapGet (_contents_hash, aKey))
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return NSCountMapTable (_contents_hash);
|
||||
}
|
||||
|
||||
// ENUMERATIONS;
|
||||
|
||||
- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr
|
||||
withEnumState: (void**)enumState
|
||||
- nextObjectAndKey: (id*)aKeyPtr withEnumState: (void**)enumState
|
||||
{
|
||||
coll_node_ptr node = coll_hash_next(_contents_hash, enumState);
|
||||
if (node)
|
||||
{
|
||||
*aKeyPtr = node->key;
|
||||
*anElementPtr = node->value;
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
id o;
|
||||
if (!NSNextMapEnumeratorPair (*enumState, (void**)aKeyPtr, (void**)&o))
|
||||
return NO_OBJECT;
|
||||
return o;
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
return (void*)0;
|
||||
void *es;
|
||||
NSMapEnumerator me;
|
||||
|
||||
OBJC_MALLOC (es, NSMapEnumerator, 1);
|
||||
#if 1
|
||||
*((NSMapEnumerator*)es) = NSEnumerateMapTable (_contents_hash);
|
||||
#else
|
||||
me = NSEnumerateMapTable (_contents_hash);
|
||||
memcpy (es, &me, sizeof (NSMapEnumerator));
|
||||
#endif
|
||||
return es;
|
||||
}
|
||||
|
||||
- freeEnumState: (void**)enumState
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
if (*enumState)
|
||||
OBJC_FREE(*enumState);
|
||||
return self;
|
||||
OBJC_FREE (*enumState);
|
||||
}
|
||||
|
||||
|
||||
- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc
|
||||
whileTrue: (BOOL *)flag
|
||||
{
|
||||
void *state = 0;
|
||||
coll_node_ptr node = 0;
|
||||
|
||||
while (flag && (node = coll_hash_next(_contents_hash, &state)))
|
||||
(*aFunc)(node->key, node->value);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/* Implementation for Objective-C GapArray collection object
|
||||
Copyright (C) 1993,1994, 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Kresten Krab Thorup <krab@iesd.auc.dk>
|
||||
Dept. of Mathematics and Computer Science, Aalborg U., Denmark
|
||||
|
||||
Overhauled by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
|
@ -27,19 +29,11 @@
|
|||
|
||||
@implementation GapArray
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [GapArray class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
}
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
/* Override designated initializer of superclass */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
capacity: (unsigned)aCapacity
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
[super initWithType:contentEncoding
|
||||
capacity:aCapacity];
|
||||
[super initWithCapacity: aCapacity];
|
||||
_gap_start = 0;
|
||||
_gap_size = aCapacity;
|
||||
return self;
|
||||
|
@ -58,14 +52,6 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- _readInit: (TypedStream*)aStream
|
||||
{
|
||||
[super _readInit: aStream];
|
||||
_gap_start = 0;
|
||||
_gap_size = _capacity;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
|
||||
- emptyCopy
|
||||
|
@ -76,15 +62,14 @@
|
|||
return copy;
|
||||
}
|
||||
|
||||
- _empty
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
[super _empty];
|
||||
[super _collectionEmpty];
|
||||
_gap_start = 0;
|
||||
_gap_size = _capacity;
|
||||
return self;
|
||||
}
|
||||
|
||||
- setCapacity: (unsigned)newCapacity
|
||||
- (void) setCapacity: (unsigned)newCapacity
|
||||
{
|
||||
if (newCapacity > _count)
|
||||
{
|
||||
|
@ -92,80 +77,58 @@
|
|||
[super setCapacity: newCapacity]; /* resize */
|
||||
_gap_size = _capacity - _gap_start;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (elt) removeElementAtIndex: (unsigned)index
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
elt res;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
res = _contents_array[GAP_TO_BASIC (index)];
|
||||
[_contents_array[GAP_TO_BASIC (index)] release];
|
||||
gapFillHoleAt (self, index);
|
||||
decrementCount(self);
|
||||
return AUTORELEASE_ELT(res);
|
||||
}
|
||||
|
||||
- (elt) removeFirstElement
|
||||
{
|
||||
elt res = _contents_array[GAP_TO_BASIC (0)];
|
||||
gapFillHoleAt (self, 0);
|
||||
decrementCount(self);
|
||||
return AUTORELEASE_ELT(res);
|
||||
}
|
||||
|
||||
- (elt) removeLastElement
|
||||
{
|
||||
return [self removeElementAtIndex: _count-1];
|
||||
}
|
||||
|
||||
- (elt) elementAtIndex: (unsigned)index
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
return _contents_array[GAP_TO_BASIC(index)];
|
||||
}
|
||||
|
||||
- appendElement: (elt)newElement
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
RETAIN_ELT(newElement);
|
||||
[newObject retain];
|
||||
gapMakeHoleAt (self, _count-1);
|
||||
_contents_array[_count-1] = newElement;
|
||||
return self;
|
||||
_contents_array[_count-1] = newObject;
|
||||
}
|
||||
|
||||
- prependElement: (elt)newElement
|
||||
- (void) prependObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
gapMakeHoleAt (self, 0);
|
||||
_contents_array[0] = newElement;
|
||||
return self;
|
||||
_contents_array[0] = newObject;
|
||||
}
|
||||
|
||||
- insertElement: (elt)newElement atIndex: (unsigned)index
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count+1);
|
||||
incrementCount(self);
|
||||
RETAIN_ELT(newElement);
|
||||
[newObject retain];
|
||||
gapMakeHoleAt (self, index);
|
||||
_contents_array[index] = newElement;
|
||||
return self;
|
||||
_contents_array[index] = newObject;
|
||||
}
|
||||
|
||||
- (elt) replaceElementAtIndex: (unsigned)index with: (elt)newElement
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
elt ret;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
RETAIN_ELT(newElement);
|
||||
ret = _contents_array[GAP_TO_BASIC(index)];
|
||||
_contents_array[GAP_TO_BASIC(index)] = newElement;
|
||||
return AUTORELEASE_ELT(ret);
|
||||
[newObject retain];
|
||||
[_contents_array[GAP_TO_BASIC(index)] release];
|
||||
_contents_array[GAP_TO_BASIC(index)] = newObject;
|
||||
}
|
||||
|
||||
- swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
{
|
||||
elt tmp;
|
||||
id tmp;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index1, _count);
|
||||
CHECK_INDEX_RANGE_ERROR(index2, _count);
|
||||
|
@ -174,7 +137,6 @@
|
|||
tmp = _contents_array[index1];
|
||||
_contents_array[index1] = _contents_array[index2];
|
||||
_contents_array[index2] = tmp;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* Implementation for Objective-C Heap object
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
|||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* This class could be improved by somehow making is a subclass of
|
||||
IndexedCollection, but not OrderedCollection. */
|
||||
|
||||
#include <objects/Heap.h>
|
||||
#include <objects/ArrayPrivate.h>
|
||||
|
||||
|
@ -31,20 +34,20 @@
|
|||
@implementation Heap
|
||||
|
||||
/* We could take out the recursive call to make it a little more efficient */
|
||||
- heapifyFromIndex: (unsigned)index
|
||||
- (void) heapifyFromIndex: (unsigned)index
|
||||
{
|
||||
unsigned right, left, largest;
|
||||
elt tmp;
|
||||
id tmp;
|
||||
|
||||
right = HEAP_RIGHT(index);
|
||||
left = HEAP_LEFT(index);
|
||||
if (left <= _count
|
||||
&& COMPARE_ELEMENTS(_contents_array[left],_contents_array[index]) > 0)
|
||||
&& [_contents_array[left] compare: _contents_array[index]] > 0)
|
||||
largest = left;
|
||||
else
|
||||
largest = index;
|
||||
if (right <= _count
|
||||
&& COMPARE_ELEMENTS(_contents_array[right],_contents_array[largest]) > 0)
|
||||
&& [_contents_array[right] compare: _contents_array[largest]] > 0)
|
||||
largest = right;
|
||||
if (largest != index)
|
||||
{
|
||||
|
@ -53,47 +56,41 @@
|
|||
_contents_array[largest] = tmp;
|
||||
[self heapifyFromIndex:largest];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- heapify
|
||||
- (void) heapify
|
||||
{
|
||||
int i;
|
||||
|
||||
// could use objc_msg_lookup here;
|
||||
for (i = _count / 2; i >= 1; i--)
|
||||
[self heapifyFromIndex:i];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (elt) removeFirstElement
|
||||
- (void) removeFirstObject
|
||||
{
|
||||
elt ret;
|
||||
|
||||
if (_count == 0)
|
||||
NO_ELEMENT_FOUND_ERROR();
|
||||
ret = _contents_array[0];
|
||||
return;
|
||||
[_contents_array[0] release];
|
||||
_contents_array[0] = _contents_array[_count-1];
|
||||
decrementCount(self);
|
||||
[self heapifyFromIndex:0];
|
||||
return AUTORELEASE_ELT(ret);
|
||||
}
|
||||
|
||||
- addElement: (elt)newElement
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
int i;
|
||||
|
||||
incrementCount(self);
|
||||
RETAIN_ELT(newElement);
|
||||
[newObject retain];
|
||||
for (i = _count-1;
|
||||
i > 0
|
||||
&& COMPARE_ELEMENTS(_contents_array[HEAP_PARENT(i)], newElement) < 0;
|
||||
&& [_contents_array[HEAP_PARENT(i)] compare: newObject] < 0;
|
||||
i = HEAP_PARENT(i))
|
||||
{
|
||||
_contents_array[i] = _contents_array[HEAP_PARENT(i)];
|
||||
}
|
||||
_contents_array[i] = newElement;
|
||||
return self;
|
||||
_contents_array[i] = newObject;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,517 +27,236 @@
|
|||
#include <objects/Array.h>
|
||||
#include <objects/NSString.h>
|
||||
|
||||
@implementation KeyedCollection
|
||||
@implementation KeyEnumerator
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [KeyedCollection class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
}
|
||||
/* xxx What should be here? */
|
||||
|
||||
@end
|
||||
|
||||
// NON-OBJECT ELEMENT METHOD NAMES;
|
||||
@implementation ConstantKeyedCollection
|
||||
|
||||
|
||||
// INITIALIZING;
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
keyType: (const char *)keyEncoding
|
||||
/* This is the designated initializer */
|
||||
- initWithObjects: (id*)objects forKeys: (id*)keys count: (unsigned)c
|
||||
{
|
||||
[super initWithType:contentEncoding];
|
||||
if (!elt_get_comparison_function(contentEncoding))
|
||||
[self error:"There is no elt comparison function for type encoding %s",
|
||||
keyEncoding];
|
||||
return self;
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- initKeyType: (const char *)keyEncoding
|
||||
{
|
||||
// default contents are objects;
|
||||
return [self initWithType:@encode(id) keyType:keyEncoding];
|
||||
}
|
||||
|
||||
/* Override designated initializer of superclass */
|
||||
- initWithType: (const char *)contentEncoding
|
||||
{
|
||||
// default keys are objects;
|
||||
return [self initWithType:contentEncoding
|
||||
keyType:@encode(id)];
|
||||
}
|
||||
|
||||
// ADDING OR REPLACING;
|
||||
|
||||
- putElement: (elt)newContentElement atKey: (elt)aKey
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- addContentsOf: (id <KeyedCollecting>)aKeyedCollection
|
||||
{
|
||||
id (*putElementAtKeyImp)(id,SEL,elt,elt) = (id(*)(id,SEL,elt,elt))
|
||||
objc_msg_lookup(self, @selector(putElement:atKey:));
|
||||
void doIt(elt k, elt c)
|
||||
{
|
||||
(*putElementAtKeyImp)(self, @selector(putElement:atKey:),
|
||||
c, k);
|
||||
}
|
||||
[aKeyedCollection withKeyElementsAndContentElementsCall:doIt];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* The right thing? Or should this be subclass responsibility? */
|
||||
- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
{
|
||||
return ELEMENT_NOT_FOUND_ERROR(aKey);
|
||||
}
|
||||
return [self replaceElementAtKey:aKey with:newContentElement
|
||||
ifAbsentCall:err];
|
||||
}
|
||||
|
||||
- (elt) replaceElementAtKey: (elt)aKey with: (elt)newContentElement
|
||||
ifAbsentCall: (elt(*)(arglist_t))excFunc;
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
{
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
}
|
||||
elt ret;
|
||||
|
||||
ret = [self removeElementAtKey:aKey ifAbsentCall:err];
|
||||
[self putElement:newContentElement atKey:aKey];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- swapAtKeys: (elt)key1 : (elt)key2
|
||||
{
|
||||
/* Use two tmp's so that when we add reference counting, the count will
|
||||
stay correct. */
|
||||
elt tmp1 = [self removeElementAtKey:key1];
|
||||
elt tmp2 = [self removeElementAtKey:key2];
|
||||
[self putElement:tmp2 atKey:key1];
|
||||
[self putElement:tmp1 atKey:key2];
|
||||
return self;
|
||||
}
|
||||
|
||||
// REMOVING;
|
||||
|
||||
- (elt) removeElementAtKey: (elt)aKey
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
{
|
||||
return ELEMENT_NOT_FOUND_ERROR(aKey);
|
||||
}
|
||||
return [self removeElementAtKey:aKey ifAbsentCall:err];
|
||||
}
|
||||
|
||||
- (elt) removeElementAtKey: (elt)aKey
|
||||
ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- removeObjectAtKey: (elt)aKey
|
||||
{
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
return [self removeElementAtKey:aKey].id_u;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// GETTING ELEMENTS AND KEYS;
|
||||
|
||||
- (elt) elementAtKey: (elt)aKey
|
||||
- objectAtKey: aKey
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
{
|
||||
return ELEMENT_NOT_FOUND_ERROR(aKey);
|
||||
}
|
||||
return [self elementAtKey:aKey ifAbsentCall:err];
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (elt) elementAtKey: (elt)aKey ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
- keyOfObject: aContentObject
|
||||
{
|
||||
return [self subclassResponsibility:_cmd];
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (elt) keyElementOfElement: (elt)aContent
|
||||
{
|
||||
elt err(arglist_t argFrame)
|
||||
{
|
||||
return ELEMENT_NOT_FOUND_ERROR(aContent);
|
||||
}
|
||||
return [self keyElementOfElement:aContent ifAbsentCall:err];
|
||||
}
|
||||
|
||||
- (elt) keyElementOfElement: (elt)aContent
|
||||
ifAbsentCall: (elt(*)(arglist_t))excFunc
|
||||
{
|
||||
elt theKey;
|
||||
BOOL notDone = YES;
|
||||
int (*cf)(elt,elt) = [self comparisonFunction];
|
||||
void doIt(elt key, elt content)
|
||||
{
|
||||
if (!((*cf)(aContent, content)))
|
||||
{
|
||||
theKey = key;
|
||||
notDone = NO;
|
||||
}
|
||||
}
|
||||
[self withKeyElementsAndContentElementsCall:doIt whileTrue:¬Done];
|
||||
if (notDone)
|
||||
RETURN_BY_CALLING_EXCEPTION_FUNCTION(excFunc);
|
||||
return theKey;
|
||||
}
|
||||
|
||||
- objectAtKey: (elt)aKey
|
||||
{
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
return [self elementAtKey:aKey].id_u;
|
||||
}
|
||||
|
||||
- keyObjectOfObject: aContent
|
||||
{
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
return [self keyElementOfElement:aContent].id_u;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (const char *) keyType
|
||||
- (BOOL) containsKey: aKey
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return "";
|
||||
if ([self objectAtKey: aKey] == NO_OBJECT)
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) includesKey: (elt)aKey
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
// COPYING;
|
||||
|
||||
- shallowCopyAs: (Class)aCollectionClass
|
||||
{
|
||||
id (*putElementAtKeyImp)(id,SEL,elt,elt);
|
||||
id newColl;
|
||||
|
||||
void addKeysAndContents(const elt key, elt content)
|
||||
{
|
||||
putElementAtKeyImp(newColl, @selector(putElement:atKey:),
|
||||
content, key);
|
||||
}
|
||||
|
||||
if ([(id)aCollectionClass conformsToProtocol:@protocol(KeyedCollecting)])
|
||||
{
|
||||
newColl = [self emptyCopyAs:aCollectionClass];
|
||||
putElementAtKeyImp = (id(*)(id,SEL,elt,elt))
|
||||
objc_msg_lookup(newColl, @selector(putElement:atKey:));
|
||||
[self withKeyElementsAndContentElementsCall:addKeysAndContents];
|
||||
return newColl;
|
||||
}
|
||||
else
|
||||
return [super shallowCopyAs:aCollectionClass];
|
||||
}
|
||||
|
||||
|
||||
// ENUMERATING;
|
||||
|
||||
- (BOOL) getNextKey: (elt*)aKeyPtr content: (elt*)anElementPtr
|
||||
withEnumState: (void**)enumState;
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) getNextElement:(elt *)anElementPtr withEnumState: (void**)enumState
|
||||
{
|
||||
elt key;
|
||||
return [self getNextKey:&key content:anElementPtr
|
||||
withEnumState:enumState];
|
||||
}
|
||||
|
||||
- withKeyElementsCall: (void(*)(const elt))aFunc
|
||||
{
|
||||
void doIt(elt key, elt content)
|
||||
{
|
||||
(*aFunc)(key);
|
||||
}
|
||||
[self withKeyElementsAndContentElementsCall:doIt];
|
||||
return self;
|
||||
}
|
||||
|
||||
- safeWithKeyElementsCall: (void(*)(const elt))aFunc
|
||||
{
|
||||
id tmpColl = [[Array alloc] initWithType:[self keyType]
|
||||
capacity:[self count]];
|
||||
void addKey(elt k, elt c)
|
||||
{
|
||||
[tmpColl addElement:k];
|
||||
}
|
||||
[self withKeyElementsAndContentElementsCall:addKey];
|
||||
[tmpColl withElementsCall:aFunc];
|
||||
[tmpColl release];
|
||||
return self;
|
||||
}
|
||||
|
||||
- withKeyObjectsCall: (void(*)(id))aFunc
|
||||
{
|
||||
void doIt(elt key, elt content)
|
||||
{
|
||||
(*aFunc)(key.id_u);
|
||||
}
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
[self withKeyElementsAndContentElementsCall:doIt];
|
||||
return self;
|
||||
}
|
||||
|
||||
- safeWithKeyObjectsCall: (void(*)(id))aFunc
|
||||
{
|
||||
void doIt(elt key)
|
||||
{
|
||||
(*aFunc)(key.id_u);
|
||||
}
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
[self safeWithKeyElementsCall:doIt];
|
||||
return self;
|
||||
}
|
||||
|
||||
- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc
|
||||
{
|
||||
BOOL flag = YES;
|
||||
|
||||
[self withKeyElementsAndContentElementsCall:aFunc whileTrue:&flag];
|
||||
return self;
|
||||
}
|
||||
|
||||
- safeWithKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc
|
||||
{
|
||||
BOOL flag = YES;
|
||||
|
||||
[self safeWithKeyElementsAndContentElementsCall:aFunc whileTrue:&flag];
|
||||
return self;
|
||||
}
|
||||
|
||||
- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc
|
||||
{
|
||||
BOOL flag = YES;
|
||||
void doIt(elt k, elt c)
|
||||
{
|
||||
(*aFunc)(k.id_u, c.id_u);
|
||||
}
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
[self withKeyElementsAndContentElementsCall:doIt whileTrue:&flag];
|
||||
return self;
|
||||
}
|
||||
|
||||
- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc
|
||||
{
|
||||
BOOL flag = YES;
|
||||
void doIt(elt k, elt c)
|
||||
{
|
||||
(*aFunc)(k.id_u, c.id_u);
|
||||
}
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
[self safeWithKeyElementsAndContentElementsCall:doIt whileTrue:&flag];
|
||||
return self;
|
||||
}
|
||||
|
||||
- withKeyElementsAndContentElementsCall: (void(*)(const elt,elt))aFunc
|
||||
whileTrue: (BOOL *)flag
|
||||
{
|
||||
void *s = [self newEnumState];
|
||||
elt key, content;
|
||||
|
||||
while (*flag && [self getNextKey:&key content:&content withEnumState:&s])
|
||||
(*aFunc)(key, content);
|
||||
[self freeEnumState:&s];
|
||||
return self;
|
||||
}
|
||||
|
||||
- withKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc
|
||||
whileTrue: (BOOL *)flag
|
||||
{
|
||||
void doIt(elt k, elt c)
|
||||
{
|
||||
(*aFunc)(k.id_u, c.id_u);
|
||||
}
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
[self withKeyElementsAndContentElementsCall:doIt whileTrue:flag];
|
||||
return self;
|
||||
}
|
||||
|
||||
- safeWithKeyObjectsAndContentObjectsCall: (void(*)(id,id))aFunc
|
||||
whileTrue: (BOOL *)flag
|
||||
{
|
||||
void doIt(elt k, elt c)
|
||||
{
|
||||
(*aFunc)(k.id_u, c.id_u);
|
||||
}
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
[self safeWithKeyElementsAndContentElementsCall:doIt whileTrue:flag];
|
||||
return self;
|
||||
}
|
||||
|
||||
- safeWithKeyElementsAndContentElementsCall: (void(*)(elt,elt))aFunc
|
||||
whileTrue: (BOOL *)flag
|
||||
{
|
||||
int i, count = [self count];
|
||||
id keyTmpColl = [[Array alloc] initWithType:[self keyType]
|
||||
capacity:count];
|
||||
id contentTmpColl = [[Array alloc] initWithType:[self contentType]
|
||||
capacity:count];
|
||||
void appendKeyAndContent(elt k, elt c)
|
||||
{
|
||||
[keyTmpColl appendElement:k];
|
||||
[contentTmpColl appendElement:c];
|
||||
}
|
||||
[self withKeyElementsAndContentElementsCall:appendKeyAndContent];
|
||||
for (i = 0; *flag && i < count; i++)
|
||||
(*aFunc)([keyTmpColl elementAtIndex:i], [contentTmpColl elementAtIndex:i]);
|
||||
[keyTmpColl release];
|
||||
[contentTmpColl release];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
// ADDING OR REPLACING;
|
||||
|
||||
- putObject: newContentObject atKey: (elt)aKey
|
||||
{
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
return [self putElement:newContentObject atKey:aKey];
|
||||
}
|
||||
|
||||
- replaceObjectAtKey: (elt)aKey with: newContentObject
|
||||
{
|
||||
CHECK_CONTAINS_OBJECTS_ERROR();
|
||||
return [self replaceElementAtKey:aKey with:newContentObject].id_u;
|
||||
}
|
||||
|
||||
|
||||
// GETTING COLLECTIONS OF CONTENTS SEPARATELY;
|
||||
|
||||
- shallowCopyKeysAs: aCollectionClass;
|
||||
{
|
||||
id newColl = [self emptyCopyAs:aCollectionClass];
|
||||
id(*addElementImp)(id,SEL,elt) = (id(*)(id,SEL,elt))
|
||||
objc_msg_lookup(newColl, @selector(addElement:));
|
||||
void doIt(elt e)
|
||||
{
|
||||
addElementImp(newColl, @selector(addElement:), e);
|
||||
}
|
||||
|
||||
[self withKeyElementsCall:doIt];
|
||||
return self;
|
||||
}
|
||||
|
||||
- shallowCopyContentsAs: aCollectionClass
|
||||
{
|
||||
return [super shallowCopyAs:aCollectionClass];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ENUMERATIONS;
|
||||
|
||||
- printForDebugger
|
||||
- (id <Enumerating>) keyEnumerator
|
||||
{
|
||||
const char *kd = [self keyType];
|
||||
const char *cd = [self contentType];
|
||||
void doIt(const elt key, elt content)
|
||||
{
|
||||
printf("(");
|
||||
elt_fprintf_elt(stdout, kd, key);
|
||||
printf(",");
|
||||
elt_fprintf_elt(stdout, cd, content);
|
||||
printf(") ");
|
||||
}
|
||||
[self withKeyElementsAndContentElementsCall:doIt];
|
||||
printf(" :%s\n", [self name]);
|
||||
return self;
|
||||
return [[[KeyEnumerator alloc] initWithCollection: self]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- withKeysInvoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
id o, k;
|
||||
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
[anInvocation invokeWithObject: k];
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
}
|
||||
|
||||
- withKeysInvoke: (id <Invoking>)anInvocation
|
||||
whileTrue: (BOOL *)flag
|
||||
{
|
||||
id o, k;
|
||||
|
||||
FOR_KEYED_COLLECTION_WHILE_TRUE(self, o, k, *flag)
|
||||
{
|
||||
[anInvocation invokeWithObject: k];
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
}
|
||||
|
||||
/* Override this Collection method */
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
id k;
|
||||
return [self nextObjectAndKey: &k withEnumState: enumState];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// LOW-LEVEL ENUMERATING;
|
||||
|
||||
- nextObjectAndKey: (id*)keyPtr withEnumState: (void**)enumState
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// COPYING;
|
||||
|
||||
- shallowCopyValuesAs: (Class)aConstantCollectingClass
|
||||
{
|
||||
int count = [self count];
|
||||
id contents[count];
|
||||
id k;
|
||||
int i = 0;
|
||||
id o;
|
||||
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
contents[i++] = o;
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
return [[aConstantCollectingClass alloc]
|
||||
initWithObjects: contents count: count];
|
||||
}
|
||||
|
||||
- shallowCopyKeysAs: (Class)aCollectingClass;
|
||||
{
|
||||
int count = [self count];
|
||||
id contents[count];
|
||||
id k;
|
||||
int i = 0;
|
||||
id o;
|
||||
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
contents[i++] = k;
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
return [[aCollectingClass alloc]
|
||||
initWithObjects: contents count: count];
|
||||
}
|
||||
|
||||
- copyValuesAs: (Class)aCollectingClass
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
- copyKeysAs: (Class)aCollectingClass;
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// ARCHIVING
|
||||
|
||||
- (void) _encodeContentsWithCoder: (id <Encoding>)aCoder
|
||||
{
|
||||
unsigned int count = [self count];
|
||||
const char *ce = [self contentType];
|
||||
const char *ke = [self keyType];
|
||||
void archiveKeyAndContent(elt key, elt content)
|
||||
{
|
||||
[aCoder encodeValueOfObjCType:ke
|
||||
at:elt_get_ptr_to_member(ke, &key)
|
||||
withName:@"KeyedCollection key element"];
|
||||
[aCoder encodeValueOfObjCType:ce
|
||||
at:elt_get_ptr_to_member(ce, &content)
|
||||
withName:@"KeyedCollection content element"];
|
||||
}
|
||||
id o, k;
|
||||
|
||||
[aCoder encodeValueOfCType:@encode(unsigned)
|
||||
at:&count
|
||||
withName:@"Collection element count"];
|
||||
[self withKeyElementsAndContentElementsCall:archiveKeyAndContent];
|
||||
[aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: @"Collection content count"];
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
[aCoder encodeObject: k
|
||||
withName: @"KeyedCollection key"];
|
||||
[aCoder encodeObject: o
|
||||
withName:@"KeyedCollection content"];
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) _decodeContentsWithCoder: (id <Decoding>)aCoder
|
||||
{
|
||||
unsigned int count, i;
|
||||
elt newKey, newContent;
|
||||
const char *ce = [self contentType];
|
||||
const char *ke = [self keyType];
|
||||
id *objs, *keys;
|
||||
|
||||
[aCoder decodeValueOfCType:@encode(unsigned)
|
||||
at:&count
|
||||
withName:NULL];
|
||||
OBJC_MALLOC(objs, id, count);
|
||||
OBJC_MALLOC(keys, id, count);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
[aCoder decodeValueOfObjCType:ke
|
||||
at:elt_get_ptr_to_member(ke, &newKey)
|
||||
withName:NULL];
|
||||
[aCoder decodeValueOfObjCType:ce
|
||||
at:elt_get_ptr_to_member(ce, &newContent)
|
||||
withName:NULL];
|
||||
[self putElement:newContent atKey:newKey];
|
||||
[aCoder decodeObjectAt: &(objs[i])
|
||||
withName: NULL];
|
||||
[aCoder decodeObjectAt: &(keys[i])
|
||||
withName: NULL];
|
||||
}
|
||||
[self initWithObjects: objs forKeys: keys count: count];
|
||||
OBJC_FREE(objs);
|
||||
OBJC_FREE(keys);
|
||||
}
|
||||
|
||||
|
||||
- _writeContents: (TypedStream*)aStream
|
||||
- (id <String>) description
|
||||
{
|
||||
unsigned int count = [self count];
|
||||
const char *ce = [self contentType];
|
||||
const char *ke = [self keyType];
|
||||
void archiveKeyAndContent(elt key, elt content)
|
||||
id s = [NSMutableString new];
|
||||
id o, k;
|
||||
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
objc_write_types(aStream, ke,
|
||||
elt_get_ptr_to_member(ke, &key));
|
||||
objc_write_types(aStream, ce,
|
||||
elt_get_ptr_to_member(ce, &content));
|
||||
[s appendFormat: @"(%@,%@) ", [k description], [o description]];
|
||||
}
|
||||
|
||||
objc_write_type(aStream, @encode(unsigned int), &count);
|
||||
[self withKeyElementsAndContentElementsCall:archiveKeyAndContent];
|
||||
return self;
|
||||
}
|
||||
|
||||
- _readContents: (TypedStream*)aStream
|
||||
{
|
||||
unsigned int count, i;
|
||||
elt newKey, newContent;
|
||||
const char *ce = [self contentType];
|
||||
const char *ke = [self keyType];
|
||||
|
||||
objc_read_type(aStream, @encode(unsigned int), &count);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
objc_read_types(aStream, ke,
|
||||
elt_get_ptr_to_member(ke, &newKey));
|
||||
objc_read_types(aStream, ce,
|
||||
elt_get_ptr_to_member(ce, &newContent));
|
||||
[self putElement:newContent atKey:newKey];
|
||||
}
|
||||
return self;
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
[s appendFormat: @" :%s\n", [self name]];
|
||||
return [s autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation KeyedCollection
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [KeyedCollection class])
|
||||
class_add_behavior(self, [Collection class]);
|
||||
}
|
||||
|
||||
// ADDING;
|
||||
- (void) putObject: newContentObject atKey: aKey
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// REPLACING AND SWAPPING;
|
||||
|
||||
- (void) replaceObjectAtKey: aKey with: newContentObject
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (void) swapObjectsAtKeys: key1 : key2
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// REMOVING;
|
||||
- (void) removeObjectAtKey: aKey
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* Implementation for GNU Objective-C MutableCString object
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: January 1995
|
||||
Created: January 1995
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
|
@ -71,7 +71,6 @@ stringDecrementCountAndFillHoleAt(MutableCStringStruct *self,
|
|||
/* This is the designated initializer for this class */
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
{
|
||||
[super initWithType:@encode(char)];
|
||||
_count = 0;
|
||||
_capacity = capacity;
|
||||
OBJC_MALLOC(_contents_chars, char, _capacity+1);
|
||||
|
@ -89,11 +88,10 @@ stringDecrementCountAndFillHoleAt(MutableCStringStruct *self,
|
|||
|
||||
/* xxx This should be made to return void, but we need to change
|
||||
IndexedCollecting and its conformers */
|
||||
- removeRange: (IndexRange)range
|
||||
- (void) removeRange: (IndexRange)range
|
||||
{
|
||||
stringDecrementCountAndFillHoleAt((MutableCStringStruct*)self,
|
||||
range.location, range.length);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) insertString: (String*)string atIndex: (unsigned)index
|
||||
|
@ -166,6 +164,7 @@ stringDecrementCountAndFillHoleAt(MutableCStringStruct *self,
|
|||
return _contents_chars[index];
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* For IndexedCollecting protocol */
|
||||
|
||||
- insertElement: (elt)newElement atIndex: (unsigned)index
|
||||
|
@ -202,4 +201,6 @@ stringDecrementCountAndFillHoleAt(MutableCStringStruct *self,
|
|||
return ret_elt;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
|
@ -43,10 +43,9 @@
|
|||
|
||||
/* Subclasses need to implemented the next two methods */
|
||||
|
||||
- removeRange: (IndexRange)range
|
||||
- (void) removeRange: (IndexRange)range
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) insertString: (String*)string atIndex: (unsigned)index
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
if (objects[i] == nil)
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"Tried to add nil"];
|
||||
[self initWithType: @encode(id) capacity: count];
|
||||
[self initWithCapacity: count];
|
||||
while (count--)
|
||||
[self addObject: [objects[count] retain]];
|
||||
return self;
|
||||
|
@ -69,7 +69,7 @@
|
|||
if (index >= self->_count)
|
||||
[NSException raise: NSRangeException
|
||||
format: @"Index out of bounds"];
|
||||
return self->_contents_array[index].id_u;
|
||||
return self->_contents_array[index];
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,12 +88,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
- initWithCapacity: (unsigned)numItems
|
||||
{
|
||||
return [self initWithType: @encode(id) capacity: numItems];
|
||||
}
|
||||
|
||||
/* Comes in from Array behavior
|
||||
- initWithCapacity:
|
||||
- (void) addObject: anObject
|
||||
- (void) insertObject: anObject atIndex: (unsigned)index
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Concrete implementation of NSCountedSet based on GNU Bag class
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: Sep 1995
|
||||
|
@ -49,11 +49,7 @@
|
|||
|
||||
- nextObject
|
||||
{
|
||||
elt e;
|
||||
if ([bag getNextElement:&e withEnumState:&enum_state])
|
||||
return e.id_u;
|
||||
else
|
||||
return nil;
|
||||
return [bag nextObjectWithEnumState: &enum_state];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
|
@ -90,19 +86,9 @@
|
|||
autorelease];
|
||||
}
|
||||
|
||||
- (void) addObject: anObject
|
||||
{
|
||||
[self addElement:anObject];
|
||||
}
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
[self removeElement:anObject];
|
||||
}
|
||||
|
||||
- (unsigned int) countForObject: anObject
|
||||
{
|
||||
return [self occurrencesOfElement:anObject];
|
||||
return [self occurrencesOfObject: anObject];
|
||||
}
|
||||
|
||||
/* To deal with behavior over-enthusiasm. Will be fixed later. */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* Concrete implementation of NSDictionary based on GNU Dictionary class
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: April 1995
|
||||
Created: April 1995
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
|
@ -49,11 +49,8 @@
|
|||
|
||||
- nextObject
|
||||
{
|
||||
elt k, c;
|
||||
if ([dictionary getNextKey:&k content:&c withEnumState:&enum_state])
|
||||
return k.id_u;
|
||||
else
|
||||
return nil;
|
||||
id k;
|
||||
return [dictionary nextObjectAndKey: &k withEnumState: &enum_state];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
|
@ -71,11 +68,9 @@
|
|||
|
||||
- nextObject
|
||||
{
|
||||
elt k, c;
|
||||
if ([dictionary getNextKey:&k content:&c withEnumState:&enum_state])
|
||||
return c.id_u;
|
||||
else
|
||||
return nil;
|
||||
id k;
|
||||
[dictionary nextObjectAndKey: &k withEnumState: &enum_state];
|
||||
return k;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -85,63 +80,21 @@
|
|||
|
||||
+ (void) initialize
|
||||
{
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
{
|
||||
done = 1;
|
||||
class_add_behavior([NSGDictionary class], [Dictionary class]);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithObjects: (id*)objects
|
||||
forKeys: (NSString**)keys
|
||||
count: (unsigned)count
|
||||
{
|
||||
char * content_encoding = @encode(id);
|
||||
char * key_encoding = @encode(id);
|
||||
CALL_METHOD_IN_CLASS([KeyedCollection class], initWithType:keyType:,
|
||||
content_encoding, key_encoding);
|
||||
_contents_hash =
|
||||
coll_hash_new(POWER_OF_TWO(count),
|
||||
elt_get_hash_function(key_encoding),
|
||||
elt_get_comparison_function(key_encoding));
|
||||
_comparison_function = elt_get_comparison_function(content_encoding);
|
||||
while (count--)
|
||||
{
|
||||
[keys[count] retain];
|
||||
[objects[count] retain];
|
||||
coll_hash_add(&_contents_hash, keys[count], objects[count]);
|
||||
}
|
||||
return self;
|
||||
if (self == [NSGDictionary class])
|
||||
class_add_behavior([NSGDictionary class], [Dictionary class]);
|
||||
}
|
||||
|
||||
/*
|
||||
Comes from Dictionary.m
|
||||
- initWithObjects: (id*)objects
|
||||
forKeys: (NSString**)keys
|
||||
count: (unsigned)count
|
||||
- (unsigned) count
|
||||
- objectForKey: (NSString*)aKey
|
||||
- (NSEnumerator*) keyEnumerator
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
*/
|
||||
|
||||
- objectForKey: (NSString*)aKey
|
||||
{
|
||||
elt ret_nil(arglist_t a)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self elementAtKey:aKey ifAbsentCall:ret_nil].id_u;
|
||||
}
|
||||
|
||||
- (NSEnumerator*) keyEnumerator
|
||||
{
|
||||
return [[[NSGDictionaryKeyEnumerator alloc] initWithDictionary:self]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
{
|
||||
return [[[NSGDictionaryObjectEnumerator alloc] initWithDictionary:self]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSGMutableDictionary
|
||||
|
@ -163,16 +116,12 @@
|
|||
|
||||
- (void) setObject:anObject forKey:(NSString *)aKey
|
||||
{
|
||||
[self putElement:anObject atKey:aKey];
|
||||
[self putObject: anObject atKey: aKey];
|
||||
}
|
||||
|
||||
- (void) removeObjectForKey:(NSString *)aKey
|
||||
{
|
||||
elt do_nothing (arglist_t a)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
[self removeElementAtKey:aKey ifAbsentCall:do_nothing];
|
||||
[self removeObjectAtKey: aKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* Concrete implementation of NSSet based on GNU Set class
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: Sep 1995
|
||||
Created: September 1995
|
||||
|
||||
This file is part of the GNU Objective C Class Library.
|
||||
|
||||
|
@ -43,17 +43,13 @@
|
|||
[super init];
|
||||
set = d;
|
||||
[set retain];
|
||||
enum_state = 0;
|
||||
enum_state = [set newEnumState];
|
||||
return self;
|
||||
}
|
||||
|
||||
- nextObject
|
||||
{
|
||||
elt e;
|
||||
if ([set getNextElement:&e withEnumState:&enum_state])
|
||||
return e.id_u;
|
||||
else
|
||||
return nil;
|
||||
return [set nextObjectWithEnumState: &enum_state];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
|
@ -79,20 +75,14 @@
|
|||
}
|
||||
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithObjects: (id*)objects
|
||||
count: (unsigned)count
|
||||
{
|
||||
[self initWithType:@encode(id)
|
||||
capacity:count];
|
||||
while (count--)
|
||||
[self addObject:objects[count]];
|
||||
return self;
|
||||
}
|
||||
/* This is the designated initializer
|
||||
- initWithObjects: (id*)objects
|
||||
count: (unsigned)count
|
||||
Implemented by behavior. */
|
||||
|
||||
- member: anObject
|
||||
{
|
||||
return coll_hash_value_for_key(_contents_hash, anObject).id_u;
|
||||
[self containsObject: anObject];
|
||||
}
|
||||
|
||||
- (NSEnumerator*) objectEnumerator
|
||||
|
@ -121,28 +111,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithCapacity: (unsigned)numItems
|
||||
{
|
||||
return [self initWithType:@encode(id)
|
||||
capacity:numItems];
|
||||
}
|
||||
/* This is the designated initializer
|
||||
- initWithCapacity: (unsigned)numItems
|
||||
implemented by behavior. */
|
||||
|
||||
- (void) addObject: anObject
|
||||
{
|
||||
[self addElement:anObject];
|
||||
}
|
||||
/* Implemented by behavior:
|
||||
- (void) addObject: newObject;
|
||||
- (void) removeObject: anObject
|
||||
*/
|
||||
|
||||
- (void) removeAllObjects
|
||||
{
|
||||
[self empty];
|
||||
}
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
[self removeElement:anObject];
|
||||
}
|
||||
|
||||
/* To deal with behavior over-enthusiasm. Will be fixed later. */
|
||||
- (BOOL) isEqual: other
|
||||
{
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSCharacterSet.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <objects/IndexedCollection.h>
|
||||
#include <objects/IndexedCollectionPrivate.h>
|
||||
#include <objects/String.h>
|
||||
|
@ -953,12 +954,10 @@ handle_printf_atsign (FILE *stream,
|
|||
|
||||
@implementation NSString (GNU)
|
||||
|
||||
- (elt) elementAtIndex: (unsigned)index
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
elt ret_elt;
|
||||
CHECK_INDEX_RANGE_ERROR(index, [self cStringLength]);
|
||||
ret_elt.char_u = [self _cStringContents][index];
|
||||
return ret_elt;
|
||||
return [NSNumber numberWithChar: [self _cStringContents][index]];
|
||||
}
|
||||
|
||||
/* The rest are handled by the class_add_behavior() call in +initialize. */
|
||||
|
|
Loading…
Reference in a new issue