mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
nbloat reduction
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6713 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
3383434169
commit
dd07375316
77 changed files with 80 additions and 10776 deletions
|
@ -1,38 +0,0 @@
|
|||
/* Implementation of GNU Objective-C class for writing objects to files
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: January 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Archiver.h>
|
||||
|
||||
/* Eventually some functionality may be moved out of Encoder and
|
||||
Decoder and into these objects.
|
||||
|
||||
These class should be used as concrete classes, not the Coder,
|
||||
Encoder or Decoder classes. */
|
||||
|
||||
@implementation Archiver
|
||||
@end
|
||||
|
||||
@implementation Unarchiver
|
||||
@end
|
263
Source/Array.m
263
Source/Array.m
|
@ -1,263 +0,0 @@
|
|||
/* Implementation for Objective-C Array collection object
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/ArrayPrivate.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/OrderedCollection.h>
|
||||
#include <base/behavior.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])
|
||||
class_add_behavior (self, [OrderedCollection class]);
|
||||
}
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
||||
/* Eventually we will want to have better capacity management,
|
||||
potentially keep default capacity as a class variable. */
|
||||
|
||||
+ (unsigned) defaultCapacity
|
||||
{
|
||||
return DEFAULT_ARRAY_CAPACITY;
|
||||
}
|
||||
|
||||
+ (int) defaultGrowFactor
|
||||
{
|
||||
return DEFAULT_ARRAY_GROW_FACTOR;
|
||||
}
|
||||
|
||||
/* This is the designated initializer for this class */
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
_grow_factor = [[self class] defaultGrowFactor];
|
||||
_count = 0;
|
||||
_capacity = (aCapacity < 1) ? 1 : aCapacity;
|
||||
OBJC_MALLOC(_contents_array, id, _capacity);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) _encodeCollectionWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[super _encodeCollectionWithCoder:coder];
|
||||
[coder encodeValueOfCType:@encode(unsigned)
|
||||
at:&_grow_factor
|
||||
withName:@"Array Grow Factor"];
|
||||
[coder encodeValueOfCType:@encode(unsigned)
|
||||
at:&_capacity
|
||||
withName:@"Array Capacity"];
|
||||
}
|
||||
|
||||
- _initCollectionWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
[super _initCollectionWithCoder:coder];
|
||||
[coder decodeValueOfCType:@encode(unsigned)
|
||||
at:&_grow_factor
|
||||
withName:NULL];
|
||||
_count = 0;
|
||||
[coder decodeValueOfCType:@encode(unsigned)
|
||||
at:&_capacity
|
||||
withName:NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Override superclass' designated initializer to call ours */
|
||||
- initWithObjects: (id*)objs count: (unsigned)c
|
||||
{
|
||||
int i;
|
||||
[self initWithCapacity: c];
|
||||
for (i = 0; i < c; i++)
|
||||
[self insertObject: objs[i] atIndex: i]; // xxx this most efficient method?
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) empty
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _count; i++)
|
||||
[_contents_array[i] release];
|
||||
_count = 0;
|
||||
/* Note this may not work for subclassers. Beware. */
|
||||
}
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
||||
/* This is the only method that changes the value of the instance
|
||||
variable _capacity, except for "-initDescription:capacity:" */
|
||||
|
||||
- (void) setCapacity: (unsigned)newCapacity
|
||||
{
|
||||
if (newCapacity > _count) {
|
||||
_capacity = newCapacity;
|
||||
OBJC_REALLOC(_contents_array, id, _capacity);
|
||||
}
|
||||
}
|
||||
|
||||
- (int) growFactor
|
||||
{
|
||||
return _grow_factor;
|
||||
}
|
||||
|
||||
- (void) setGrowFactor: (int)aNum;
|
||||
{
|
||||
_grow_factor = aNum;
|
||||
}
|
||||
|
||||
|
||||
// ADDING;
|
||||
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
/* Check to make sure that anObject is not nil, first. */
|
||||
if (newObject == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Array: object to add is nil"
|
||||
];
|
||||
}
|
||||
|
||||
/* Now we can add it. */
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
_contents_array[_count-1] = newObject;
|
||||
}
|
||||
|
||||
- (void) prependObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
makeHoleAt(self, 0);
|
||||
_contents_array[0] = newObject;
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count+1);
|
||||
|
||||
/* Check to make sure that anObject is not nil, first. */
|
||||
if (newObject == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Array: object to insert is nil"
|
||||
];
|
||||
}
|
||||
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
makeHoleAt(self, index);
|
||||
_contents_array[index] = newObject;
|
||||
}
|
||||
|
||||
|
||||
// REMOVING, REPLACING AND SWAPPING;
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
[_contents_array[index] release];
|
||||
fillHoleAt(self, index);
|
||||
decrementCount(self);
|
||||
}
|
||||
|
||||
/* We could be more efficient if we override these also.
|
||||
- removeFirstObject
|
||||
- removeLastObject;
|
||||
If you do, remember, you will have to implement this methods
|
||||
in GapArray also! */
|
||||
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
[newObject retain];
|
||||
[_contents_array[index] release];
|
||||
_contents_array[index] = newObject;
|
||||
}
|
||||
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@end
|
211
Source/Bag.m
211
Source/Bag.m
|
@ -1,211 +0,0 @@
|
|||
/* Implementation for Objective-C Bag collection object
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Bag.h>
|
||||
#include <base/CollectionPrivate.h>
|
||||
|
||||
#define DEFAULT_BAG_CAPACITY 32
|
||||
|
||||
@implementation Bag
|
||||
|
||||
// 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 */
|
||||
- initWithCapacity: (unsigned)cap
|
||||
{
|
||||
_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 */
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
Bag *copy = [super emptyCopy];
|
||||
copy->_contents_map = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks,
|
||||
0);
|
||||
copy->_count = 0;
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
NSFreeMapTable (_contents_map);
|
||||
[super _collectionDealloc];
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
NSResetMapTable (_contents_map);
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
// ADDING;
|
||||
|
||||
- (void) addObject: newObject withOccurrences: (unsigned)count
|
||||
{
|
||||
unsigned new_count = (unsigned) NSMapGet (_contents_map, newObject);
|
||||
new_count += count;
|
||||
NSMapInsert (_contents_map, newObject, (void*)new_count);
|
||||
_count += count;
|
||||
}
|
||||
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
[self addObject: newObject withOccurrences: 1];
|
||||
}
|
||||
|
||||
|
||||
// REMOVING AND REPLACING;
|
||||
|
||||
- (void) removeObject: oldObject occurrences: (unsigned)count
|
||||
{
|
||||
unsigned c = (unsigned) NSMapGet (_contents_map, oldObject);
|
||||
if (c)
|
||||
{
|
||||
if (c <= count)
|
||||
{
|
||||
NSMapRemove (_contents_map, oldObject);
|
||||
_count -= c;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSMapInsert (_contents_map, oldObject, (void*)(c - count));
|
||||
_count -= count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
[self removeObject: oldObject occurrences:1];
|
||||
}
|
||||
|
||||
- (void) uniqueContents
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
- (unsigned) uniqueCount
|
||||
{
|
||||
return NSCountMapTable (_contents_map);
|
||||
}
|
||||
|
||||
- (unsigned) occurrencesOfObject: anObject
|
||||
{
|
||||
return (unsigned) NSMapGet (_contents_map, anObject);
|
||||
}
|
||||
|
||||
|
||||
// ENUMERATING;
|
||||
|
||||
struct BagEnumState
|
||||
{
|
||||
NSMapEnumerator me;
|
||||
id object;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
#define ES ((struct BagEnumState *) *enumState)
|
||||
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
if (!(ES->count))
|
||||
if (!NSNextMapEnumeratorPair (&(ES->me),
|
||||
(void**) &(ES->object),
|
||||
(void**) &(ES->count)))
|
||||
return NO_OBJECT;
|
||||
ES->count--;
|
||||
return ES->object;
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
/* init for start of enumeration. */
|
||||
void *vp;
|
||||
void **enumState = &vp;
|
||||
OBJC_MALLOC(*enumState, struct BagEnumState, 1);
|
||||
ES->me = NSEnumerateMapTable (_contents_map);
|
||||
ES->object = nil;
|
||||
ES->count = 0;
|
||||
return vp;
|
||||
}
|
||||
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
if (*enumState)
|
||||
OBJC_FREE(*enumState);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -1,607 +0,0 @@
|
|||
/* Implementation for Objective-C BinaryTree collection object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/BinaryTree.h>
|
||||
#include <base/IndexedCollectionPrivate.h>
|
||||
#include <base/BinaryTreeNode.h>
|
||||
#include <base/NSString.h>
|
||||
|
||||
/* the sentinal */
|
||||
static id nilBinaryTreeNode;
|
||||
|
||||
@implementation BinaryTree
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [BinaryTree class])
|
||||
{
|
||||
nilBinaryTreeNode = [[BinaryTreeNode alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- init
|
||||
{
|
||||
_count = 0;
|
||||
_contents_root = [self nilNode];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
/* xxx See Collection _decodeContentsWithCoder:.
|
||||
We shouldn't do an -addElement. finishEncodingInterconnectedObjects
|
||||
should take care of all that. */
|
||||
|
||||
- _initCollectionWithCoder: aCoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
[super _initCollectionWithCoder:aCoder];
|
||||
_count = 0;
|
||||
_contents_root = [self nilNode];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) _encodeContentsWithCoder: (id <Encoding>)aCoder
|
||||
{
|
||||
[aCoder startEncodingInterconnectedObjects];
|
||||
[super _encodeContentsWithCoder:aCoder];
|
||||
[aCoder finishEncodingInterconnectedObjects];
|
||||
}
|
||||
|
||||
- (void) _decodeContentsWithCoder: (id <Decoding>)aCoder
|
||||
{
|
||||
[aCoder startDecodingInterconnectedObjects];
|
||||
[super _decodeContentsWithCoder:aCoder];
|
||||
[aCoder finishDecodingInterconnectedObjects];
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
BinaryTree *copy = [super emptyCopy];
|
||||
copy->_count = 0;
|
||||
copy->_contents_root = [self nilNode];
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) _empty
|
||||
{
|
||||
_count = 0;
|
||||
_contents_root = [self nilNode];
|
||||
}
|
||||
|
||||
- nilNode
|
||||
{
|
||||
return nilBinaryTreeNode;
|
||||
}
|
||||
|
||||
- rootNode
|
||||
{
|
||||
return _contents_root;
|
||||
}
|
||||
|
||||
- leftmostNodeFromNode: aNode
|
||||
{
|
||||
id left;
|
||||
|
||||
if (aNode && aNode != [self nilNode])
|
||||
{
|
||||
while ((left = [aNode leftNode]) != [self nilNode])
|
||||
aNode = left;
|
||||
}
|
||||
return aNode;
|
||||
}
|
||||
|
||||
- rightmostNodeFromNode: aNode
|
||||
{
|
||||
id right;
|
||||
|
||||
if (aNode && aNode != [self nilNode])
|
||||
while ((right = [aNode rightNode]) != [self nilNode])
|
||||
{
|
||||
aNode = right;
|
||||
}
|
||||
return aNode;
|
||||
}
|
||||
|
||||
- firstObject
|
||||
{
|
||||
return [self leftmostNodeFromNode: _contents_root];
|
||||
}
|
||||
|
||||
- lastObject
|
||||
{
|
||||
return [self rightmostNodeFromNode: _contents_root];
|
||||
}
|
||||
|
||||
/* This is correct only if the tree is sorted. How to deal with this? */
|
||||
- maxObject
|
||||
{
|
||||
return [self rightmostNodeFromNode: _contents_root];
|
||||
}
|
||||
|
||||
/* This is correct only is the tree is sorted. How to deal with this? */
|
||||
- minObject
|
||||
{
|
||||
return [self leftmostNodeFromNode: _contents_root];
|
||||
}
|
||||
|
||||
- successorOfObject: anObject
|
||||
{
|
||||
id tmp;
|
||||
|
||||
/* Make sure we actually own the anObject. */
|
||||
NSAssert([anObject binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
// here tmp is the right node;
|
||||
if ((tmp = [anObject rightNode]) != [self nilNode])
|
||||
return [self leftmostNodeFromNode: tmp];
|
||||
// here tmp is the parent;
|
||||
tmp = [anObject parentNode];
|
||||
while (tmp != [self nilNode] && anObject == [tmp rightNode])
|
||||
{
|
||||
anObject = tmp;
|
||||
tmp = [tmp parentNode];
|
||||
}
|
||||
if (tmp == [self nilNode])
|
||||
return NO_OBJECT;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// I should make sure that [_contents_root parentNode] == [self nilNode];
|
||||
// Perhaps I should make [_contents_root parentNode] == binaryTreeObj ??;
|
||||
|
||||
- predecessorObject: anObject
|
||||
{
|
||||
id tmp;
|
||||
|
||||
/* Make sure we actually own the anObject. */
|
||||
NSAssert([anObject binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
// here tmp is the left node;
|
||||
if ((tmp = [anObject leftNode]) != [self nilNode])
|
||||
return [self rightmostNodeFromNode:tmp];
|
||||
// here tmp is the parent;
|
||||
tmp = [anObject parentNode];
|
||||
while (tmp != [self nilNode] && anObject == [tmp leftNode])
|
||||
{
|
||||
anObject = tmp;
|
||||
tmp = [tmp parentNode];
|
||||
}
|
||||
if (tmp == [self nilNode])
|
||||
return NO_OBJECT;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* This relies on [_contents_root parentNode] == [self nilNode] */
|
||||
- rootFromNode: aNode
|
||||
{
|
||||
id parentNode;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([aNode binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
while ((parentNode = [aNode parentNode]) != [self nilNode])
|
||||
aNode = parentNode;
|
||||
return aNode;
|
||||
}
|
||||
|
||||
/* This relies on [_contents_root parentNode] == [self nilNode] */
|
||||
- (unsigned) depthOfNode: aNode
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([aNode binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
if (aNode == nil || aNode == [self nilNode])
|
||||
[self error:"in %s, Can't find depth of nil node", sel_get_name(_cmd)];
|
||||
do
|
||||
{
|
||||
aNode = [aNode parentNode];
|
||||
count++;
|
||||
}
|
||||
while (aNode != [self nilNode]);
|
||||
return count;
|
||||
}
|
||||
|
||||
- (unsigned) heightOfNode: aNode
|
||||
{
|
||||
unsigned leftHeight, rightHeight;
|
||||
id tmpNode;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([aNode binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
if (aNode == nil || aNode == [self nilNode])
|
||||
{
|
||||
[self error:"in %s, Can't find height of nil node", sel_get_name(_cmd)];
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftHeight = ((tmpNode = [aNode leftNode])
|
||||
?
|
||||
(1 + [self heightOfNode:tmpNode])
|
||||
:
|
||||
0);
|
||||
rightHeight = ((tmpNode = [aNode rightNode])
|
||||
?
|
||||
(1 + [self heightOfNode:tmpNode])
|
||||
:
|
||||
0);
|
||||
return MAX(leftHeight, rightHeight);
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) nodeCountUnderNode: aNode
|
||||
{
|
||||
unsigned count = 0;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([aNode binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
if ([aNode leftNode] != [self nilNode])
|
||||
count += 1 + [self nodeCountUnderNode:[aNode leftNode]];
|
||||
if ([aNode rightNode] != [self nilNode])
|
||||
count += 1 + [self nodeCountUnderNode:[aNode rightNode]];
|
||||
return count;
|
||||
}
|
||||
|
||||
- leftRotateAroundNode: aNode
|
||||
{
|
||||
id y;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([aNode binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
y = [aNode rightNode];
|
||||
if (y == [self nilNode])
|
||||
return self;
|
||||
[aNode setRightNode:[y leftNode]];
|
||||
if ([y leftNode] != [self nilNode])
|
||||
[[y leftNode] setParentNode:aNode];
|
||||
[y setParentNode:[aNode parentNode]];
|
||||
if ([aNode parentNode] == [self nilNode])
|
||||
_contents_root = y;
|
||||
else
|
||||
{
|
||||
if (NODE_IS_LEFTCHILD(aNode))
|
||||
[[aNode parentNode] setLeftNode:y];
|
||||
else
|
||||
[[aNode parentNode] setRightNode:y];
|
||||
}
|
||||
[y setLeftNode:aNode];
|
||||
[aNode setParentNode:y];
|
||||
return self;
|
||||
}
|
||||
|
||||
- rightRotateAroundNode: aNode
|
||||
{
|
||||
id y;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([aNode binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
y = [aNode leftNode];
|
||||
if (y == [self nilNode])
|
||||
return self;
|
||||
[aNode setLeftNode:[y rightNode]];
|
||||
if ([y rightNode] != [self nilNode])
|
||||
[[y rightNode] setParentNode:aNode];
|
||||
[y setParentNode:[aNode parentNode]];
|
||||
if ([aNode parentNode] == [self nilNode])
|
||||
_contents_root = y;
|
||||
else
|
||||
{
|
||||
if (NODE_IS_RIGHTCHILD(aNode))
|
||||
[[aNode parentNode] setRightNode:y];
|
||||
else
|
||||
[[aNode parentNode] setLeftNode:y];
|
||||
}
|
||||
[y setRightNode:aNode];
|
||||
[aNode setParentNode:y];
|
||||
return self;
|
||||
}
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
id ret;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
ret = [self firstObject];
|
||||
// Not very efficient; Should be rewritten;
|
||||
while (index--)
|
||||
ret = [self successorOfObject: ret];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void) sortAddObject: newObject
|
||||
{
|
||||
id theParent, tmpChild;
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject binaryTree] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setBinaryTree: self];
|
||||
|
||||
[newObject setLeftNode:[self nilNode]];
|
||||
[newObject setRightNode:[self nilNode]];
|
||||
theParent = [self nilNode];
|
||||
tmpChild = _contents_root;
|
||||
while (tmpChild != [self nilNode])
|
||||
{
|
||||
theParent = tmpChild;
|
||||
if ([newObject compare: theParent] < 0)
|
||||
tmpChild = [tmpChild leftNode];
|
||||
else
|
||||
tmpChild = [tmpChild rightNode];
|
||||
}
|
||||
[newObject setParentNode:theParent];
|
||||
if (theParent == [self nilNode])
|
||||
_contents_root = newObject;
|
||||
else
|
||||
{
|
||||
if ([newObject compare: theParent] < 0)
|
||||
[theParent setLeftNode:newObject];
|
||||
else
|
||||
[theParent setRightNode:newObject];
|
||||
}
|
||||
_count++;
|
||||
}
|
||||
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
// By default insert in sorted order.
|
||||
[self sortAddObject: newObject];
|
||||
}
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
id x, y;
|
||||
|
||||
/* Make sure we actually own the aNode. */
|
||||
NSAssert([oldObject binaryTree] == self, NSInternalInconsistencyException);
|
||||
|
||||
/* Extract the oldObject and sew up the cut. */
|
||||
if ([oldObject leftNode] == [self nilNode]
|
||||
|| [oldObject rightNode] == [self nilNode])
|
||||
y = oldObject;
|
||||
else
|
||||
y = [self successorOfObject: oldObject];
|
||||
|
||||
if ([y leftNode] != [self nilNode])
|
||||
x = [y leftNode];
|
||||
else
|
||||
x = [y rightNode];
|
||||
|
||||
if (x != [self nilNode])
|
||||
[x setParentNode: [y parentNode]];
|
||||
|
||||
if ([y parentNode] == [self nilNode])
|
||||
_contents_root = x;
|
||||
else
|
||||
{
|
||||
if (y == [[y parentNode] leftNode])
|
||||
[[y parentNode] setLeftNode: x];
|
||||
else
|
||||
[[y parentNode] setRightNode: x];
|
||||
}
|
||||
|
||||
if (y != oldObject)
|
||||
{
|
||||
/* put y in the place of oldObject */
|
||||
[y setParentNode: [oldObject parentNode]];
|
||||
[y setLeftNode: [oldObject leftNode]];
|
||||
[y setRightNode: [oldObject rightNode]];
|
||||
if (oldObject == [[oldObject parentNode] leftNode])
|
||||
[[oldObject parentNode] setLeftNode: y];
|
||||
else
|
||||
[[oldObject parentNode] setRightNode: y];
|
||||
[[oldObject leftNode] setParentNode: y];
|
||||
[[oldObject rightNode] setParentNode: y];
|
||||
}
|
||||
_count--;
|
||||
|
||||
/* Release ownership of the object. */
|
||||
#if 0
|
||||
[oldObject setRightNode: [self nilNode]];
|
||||
[oldObject setLeftNode: [self nilNode]];
|
||||
[oldObject setParentNode: [self nilNode]];
|
||||
#else
|
||||
[oldObject setLeftNode: NO_OBJECT];
|
||||
[oldObject setRightNode: NO_OBJECT];
|
||||
[oldObject setParentNode: NO_OBJECT];
|
||||
#endif
|
||||
[oldObject setBinaryTree: NO_OBJECT];
|
||||
[oldObject release];
|
||||
}
|
||||
|
||||
|
||||
// ENUMERATING;
|
||||
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
if (!(*enumState))
|
||||
*enumState = [self leftmostNodeFromNode:_contents_root];
|
||||
else
|
||||
*enumState = [self successorOfObject:*enumState];
|
||||
return (id) *enumState;
|
||||
}
|
||||
|
||||
- prevObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
if (!(*enumState))
|
||||
*enumState = [self rightmostNodeFromNode:_contents_root];
|
||||
else
|
||||
*enumState = [self predecessorObject:*enumState];
|
||||
return (id) *enumState;
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
|
||||
/* replace this with something better eventually */
|
||||
- _tmpPrintFromNode: aNode indent: (int)count
|
||||
{
|
||||
printf("%-*s", count, "");
|
||||
printf("%s\n", [[aNode description] cString]);
|
||||
printf("%-*s.", count, "");
|
||||
if ([aNode leftNode] != [self nilNode])
|
||||
[self _tmpPrintFromNode:[aNode leftNode] indent:count+2];
|
||||
else
|
||||
printf("\n");
|
||||
printf("%-*s.", count, "");
|
||||
if ([aNode rightNode] != [self nilNode])
|
||||
[self _tmpPrintFromNode:[aNode rightNode] indent:count+2];
|
||||
else
|
||||
printf("\n");
|
||||
return self;
|
||||
}
|
||||
|
||||
- binaryTreePrintForDebugger
|
||||
{
|
||||
[self _tmpPrintFromNode:_contents_root indent:0];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
/* These methods removed because they belong to an
|
||||
OrderedCollection implementation, not an IndexedCollection
|
||||
implementation. */
|
||||
|
||||
#if 0
|
||||
// NOTE: This gives you the power to put elements in unsorted order;
|
||||
- insertObject: newObject before: oldObject
|
||||
{
|
||||
id tmp;
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setBinaryTree: self];
|
||||
|
||||
[newObject setRightNode:[self nilNode]];
|
||||
[newObject setLeftNode:[self nilNode]];
|
||||
if ((tmp = [oldObject leftNode]) != [self nilNode])
|
||||
{
|
||||
[(tmp = [self rightmostNodeFromNode:tmp]) setRightNode:newObject];
|
||||
[newObject setParentNode:tmp];
|
||||
}
|
||||
else if (newObject != [self nilNode])
|
||||
{
|
||||
[oldObject setLeftNode:newObject];
|
||||
[newObject setParentNode:oldObject];
|
||||
}
|
||||
else
|
||||
{
|
||||
_contents_root = newObject;
|
||||
[newObject setParentNode:[self nilNode]];
|
||||
}
|
||||
_count++;
|
||||
RETAIN_ELT(newObject);
|
||||
return self;
|
||||
}
|
||||
|
||||
// NOTE: This gives you the power to put elements in unsorted order;
|
||||
- insertObject: newObject after: oldObject
|
||||
{
|
||||
id tmp;
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setBinaryTree: self];
|
||||
|
||||
[newObject setRightNode:[self nilNode]];
|
||||
[newObject setLeftNode:[self nilNode]];
|
||||
if ((tmp = [oldObject rightNode]) != [self nilNode])
|
||||
{
|
||||
[(tmp = [self leftmostNodeFromNode:tmp]) setLeftNode:newObject];
|
||||
[newObject setParentNode:tmp];
|
||||
}
|
||||
else if (newObject != [self nilNode])
|
||||
{
|
||||
[oldObject setRightNode:newObject];
|
||||
[newObject setParentNode:oldObject];
|
||||
}
|
||||
else
|
||||
{
|
||||
_contents_root = newObject;
|
||||
[newObject setParentNode:[self nilNode]];
|
||||
}
|
||||
_count++;
|
||||
RETAIN_ELT(newObject);
|
||||
return self;
|
||||
}
|
||||
|
||||
// NOTE: This gives you the power to put elements in unsorted order;
|
||||
- insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count+1);
|
||||
|
||||
if (index == _count)
|
||||
[self appendObject:newObject];
|
||||
else
|
||||
[self insertObject:newObject before:[self ObjectAtIndex:index]];
|
||||
return self;
|
||||
}
|
||||
|
||||
// NOTE: This gives you the power to put elements in unsorted order;
|
||||
- appendObject: newObject
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setBinaryTree: self];
|
||||
|
||||
_contents_root = newObject;
|
||||
_count = 1;
|
||||
[newObject setLeftNode:[self nilNode]];
|
||||
[newObject setRightNode:[self nilNode]];
|
||||
[newObject setParentNode:[self nilNode]];
|
||||
}
|
||||
else
|
||||
[self insertObject:newObject after:[self lastObject]];
|
||||
return self;
|
||||
}
|
||||
#endif
|
|
@ -1,104 +0,0 @@
|
|||
/* Implementation for Objective-C BinaryTreeNode object
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/BinaryTreeNode.h>
|
||||
#include <base/NSString.h>
|
||||
|
||||
@implementation BinaryTreeNode
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [BinaryTreeNode class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_left = _right = _parent = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[super encodeWithCoder:(id)aCoder];
|
||||
[aCoder encodeObjectReference:_right withName:@"Right BinaryTree Node"];
|
||||
[aCoder encodeObjectReference:_left withName:@"Left BinaryTree Node"];
|
||||
[aCoder encodeObjectReference:_parent withName:@"Parent BinaryTree Node"];
|
||||
[aCoder encodeObjectReference:_binary_tree
|
||||
withName:@"BinaryTree"];
|
||||
}
|
||||
|
||||
- initWithCoder: aCoder
|
||||
{
|
||||
[super initWithCoder:aCoder];
|
||||
[aCoder decodeObjectAt:&_right withName:NULL];
|
||||
[aCoder decodeObjectAt:&_left withName:NULL];
|
||||
[aCoder decodeObjectAt:&_parent withName:NULL];
|
||||
[aCoder decodeObjectAt:&_binary_tree withName:NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- leftNode
|
||||
{
|
||||
return _left;
|
||||
}
|
||||
|
||||
- rightNode
|
||||
{
|
||||
return _right;
|
||||
}
|
||||
|
||||
- parentNode
|
||||
{
|
||||
return _parent;
|
||||
}
|
||||
|
||||
- (void) setLeftNode: aNode
|
||||
{
|
||||
_left = aNode;
|
||||
}
|
||||
|
||||
- (void) setRightNode: aNode
|
||||
{
|
||||
_right = aNode;
|
||||
}
|
||||
|
||||
- (void) setParentNode: aNode
|
||||
{
|
||||
_parent = aNode;
|
||||
}
|
||||
|
||||
- binaryTree
|
||||
{
|
||||
return _binary_tree;
|
||||
}
|
||||
|
||||
- (void) setBinaryTree: anObject
|
||||
{
|
||||
_binary_tree = anObject;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,197 +0,0 @@
|
|||
/* Implementation for Objective-C CircularArray collection object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <base/CircularArray.h>
|
||||
#include <base/CircularArrayPrivate.h>
|
||||
|
||||
@implementation CircularArray
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
[super initWithCapacity:aCapacity];
|
||||
_start_index = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- _initCollectionWithCoder: coder
|
||||
{
|
||||
[super _initCollectionWithCoder:coder];
|
||||
_start_index = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
|
||||
- emptyCopy
|
||||
{
|
||||
CircularArray *copy = [super emptyCopy];
|
||||
copy->_start_index = 0;
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void) empty
|
||||
{
|
||||
[super empty];
|
||||
_start_index = 0;
|
||||
}
|
||||
|
||||
/* This is the only method that changes the value of the instance
|
||||
variable _capacity, except for "-initWithCapacity:" */
|
||||
|
||||
- (void) setCapacity: (unsigned)newCapacity
|
||||
{
|
||||
id *new_contents;
|
||||
int i;
|
||||
|
||||
if (newCapacity > _count) {
|
||||
/* This could be more efficient */
|
||||
OBJC_MALLOC(new_contents, id, newCapacity);
|
||||
for (i = 0; i < _count; i++)
|
||||
new_contents[i] = _contents_array[CIRCULAR_TO_BASIC(i)];
|
||||
OBJC_FREE(_contents_array);
|
||||
_contents_array = new_contents;
|
||||
_start_index = 0;
|
||||
_capacity = newCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
unsigned basicIndex;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
basicIndex = CIRCULAR_TO_BASIC(index);
|
||||
[_contents_array[basicIndex] release];
|
||||
circularFillHoleAt(self, basicIndex);
|
||||
decrementCount(self);
|
||||
}
|
||||
|
||||
- (void) removeFirstObject
|
||||
{
|
||||
if (!_count)
|
||||
return;
|
||||
[_contents_array[_start_index] release];
|
||||
_start_index = (_start_index + 1) % _capacity;
|
||||
decrementCount(self);
|
||||
}
|
||||
|
||||
- (void) removeLastObject
|
||||
{
|
||||
if (!_count)
|
||||
return;
|
||||
[_contents_array[CIRCULAR_TO_BASIC(_count-1)] release];
|
||||
decrementCount(self);
|
||||
}
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
return _contents_array[CIRCULAR_TO_BASIC(index)];
|
||||
}
|
||||
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
_contents_array[CIRCULAR_TO_BASIC(_count-1)] = newObject;
|
||||
}
|
||||
|
||||
- (void) prependElement: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
_start_index = (_capacity + _start_index - 1) % _capacity;
|
||||
_contents_array[_start_index] = newObject;
|
||||
}
|
||||
|
||||
- (void) insertElement: newObject atIndex: (unsigned)index
|
||||
{
|
||||
unsigned basicIndex;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count+1);
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
basicIndex = CIRCULAR_TO_BASIC(index);
|
||||
circularMakeHoleAt(self, basicIndex);
|
||||
_contents_array[basicIndex] = newObject;
|
||||
}
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
unsigned basicIndex;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
[newObject retain];
|
||||
basicIndex = CIRCULAR_TO_BASIC(index);
|
||||
[_contents_array[basicIndex] release];
|
||||
_contents_array[basicIndex] = newObject;
|
||||
}
|
||||
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
{
|
||||
id tmp;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index1, _count);
|
||||
CHECK_INDEX_RANGE_ERROR(index2, _count);
|
||||
index1 = CIRCULAR_TO_BASIC(index1);
|
||||
index2 = CIRCULAR_TO_BASIC(index2);
|
||||
tmp = _contents_array[index1];
|
||||
_contents_array[index1] = _contents_array[index2];
|
||||
_contents_array[index2] = tmp;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* just temporary for debugging */
|
||||
- circularArrayPrintForDebugger
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("_start_index=%d, _count=%d, _capacity=%d\n",
|
||||
_start_index, _count, _capacity);
|
||||
for (i = 0; i < _capacity; i++)
|
||||
{
|
||||
printf("%3d ", i);
|
||||
}
|
||||
printf("\n");
|
||||
for (i = 0; i < _capacity; i++)
|
||||
{
|
||||
printf("%3d ", _contents_array[i].int_t);
|
||||
}
|
||||
printf("\n");
|
||||
for (i = 0; i < _capacity; i++)
|
||||
{
|
||||
printf("%3d ", _contents_array[CIRCULAR_TO_BASIC(i)].int_t);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
|
@ -1,839 +0,0 @@
|
|||
/* Implementation for Objective-C Collection object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Collection.h>
|
||||
#include <base/CollectionPrivate.h>
|
||||
#include <stdarg.h>
|
||||
#include <base/Bag.h> /* for -contentsEqual: */
|
||||
#include <base/Array.h> /* for -safeWithElementsCall: */
|
||||
#include <base/Coder.h>
|
||||
#include <base/NSString.h>
|
||||
|
||||
@implementation Enumerator
|
||||
|
||||
- initWithCollection: coll
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
collection = [coll retain];
|
||||
enum_state = [coll newEnumState];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- nextObject
|
||||
{
|
||||
return [collection nextObjectWithEnumState: &enum_state];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[collection freeEnumState: &enum_state];
|
||||
[collection release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ConstantCollection
|
||||
|
||||
|
||||
// INITIALIZING AND RELEASING;
|
||||
|
||||
- init
|
||||
{
|
||||
return [self initWithObjects: NULL count: 0];
|
||||
}
|
||||
|
||||
// This is the designated initializer of this class;
|
||||
- initWithObjects: (id*)objc count: (unsigned)c
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithObjects: firstObject, ...
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, firstObject);
|
||||
self = [self initWithObjects:firstObject rest:ap];
|
||||
va_end(ap);
|
||||
return self;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
/* Subclasses can override this for efficiency. For example, Array can
|
||||
init itself with enough capacity to hold aCollection. */
|
||||
- initWithContentsOf: (id <Collecting>)aCollection
|
||||
{
|
||||
int count = [aCollection count];
|
||||
id contents_array[count];
|
||||
id o;
|
||||
int i = 0;
|
||||
|
||||
FOR_COLLECTION(aCollection, o)
|
||||
{
|
||||
contents_array[i++] = o;
|
||||
}
|
||||
END_FOR_COLLECTION(aCollection);
|
||||
return [self initWithObjects: contents_array count: count];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
/* xxx Get rid of this since Set, Bag, Dictionary, and String
|
||||
subclasses don't want to use it? */
|
||||
[self _collectionReleaseContents];
|
||||
[self _collectionDealloc];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
// QUERYING COUNTS;
|
||||
|
||||
- (BOOL) isEmpty
|
||||
{
|
||||
return ([self count] == 0);
|
||||
}
|
||||
|
||||
// Inefficient, so should be overridden in subclasses;
|
||||
- (unsigned) count
|
||||
{
|
||||
unsigned n = 0;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Potentially inefficient, may be overridden in subclasses;
|
||||
- (BOOL) containsObject: anObject
|
||||
{
|
||||
id o;
|
||||
FOR_COLLECTION (self, o)
|
||||
{
|
||||
if ([anObject isEqual: o])
|
||||
return YES;
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (unsigned) occurrencesOfObject: anObject
|
||||
{
|
||||
unsigned count = 0;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
if ([anObject isEqual: o])
|
||||
count++;
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// COMPARISON WITH OTHER COLLECTIONS;
|
||||
|
||||
- (BOOL) isSubsetOf: (id <Collecting>)aCollection
|
||||
{
|
||||
id o;
|
||||
FOR_COLLECTION (self, o)
|
||||
{
|
||||
if (![aCollection containsObject: o])
|
||||
return NO;
|
||||
}
|
||||
END_FOR_COLLECTION (self);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) isDisjointFrom: (id <Collecting>)aCollection
|
||||
{
|
||||
// Use objc_msg_lookup here also;
|
||||
BOOL flag = YES;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION_WHILE_TRUE(self, o, flag)
|
||||
{
|
||||
if (![aCollection containsObject: o])
|
||||
flag = NO;
|
||||
}
|
||||
END_FOR_COLLECTION_WHILE_TRUE(self);
|
||||
return !flag;
|
||||
}
|
||||
|
||||
// xxx How do we want to compare unordered contents?? ;
|
||||
- (int) compareContentsOf: (id <Collecting>)aCollection
|
||||
{
|
||||
if ([self contentsEqual:aCollection])
|
||||
return 0;
|
||||
if (self > aCollection)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (BOOL) isEqual: anObject
|
||||
{
|
||||
if (self == anObject)
|
||||
return YES;
|
||||
if ( [self contentsEqual: anObject] )
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Deal with this in IndexedCollection also ;
|
||||
// How do we want to compare collections? ;
|
||||
- (int) compare: anObject
|
||||
{
|
||||
if ([self isEqual:anObject])
|
||||
return 0;
|
||||
if (self > anObject)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
- (BOOL) contentsEqual: (id <Collecting>)aCollection
|
||||
{
|
||||
id bag, o;
|
||||
BOOL flag;
|
||||
|
||||
if ([self count] != [aCollection count])
|
||||
return NO;
|
||||
bag = [[Bag alloc] initWithContentsOf:aCollection];
|
||||
flag = YES;
|
||||
FOR_COLLECTION_WHILE_TRUE (self, o, flag)
|
||||
{
|
||||
if ([bag containsObject: o])
|
||||
[bag removeObject: o];
|
||||
else
|
||||
flag = NO;
|
||||
}
|
||||
END_FOR_COLLECTION_WHILE_TRUE(self);
|
||||
if ((!flag) || [bag count])
|
||||
flag = NO;
|
||||
else
|
||||
flag = YES;
|
||||
[bag release];
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
// PROPERTIES OF CONTENTS;
|
||||
|
||||
- (BOOL) trueForAllObjectsByInvoking: (id <Invoking>)anInvocation
|
||||
{
|
||||
BOOL flag = YES;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION_WHILE_TRUE(self, o, flag)
|
||||
{
|
||||
[anInvocation invokeWithObject: o];
|
||||
if (![anInvocation returnValueIsTrue])
|
||||
flag = NO;
|
||||
}
|
||||
END_FOR_COLLECTION_WHILE_TRUE(self);
|
||||
return flag;
|
||||
}
|
||||
|
||||
- (BOOL) trueForAnyObjectsByInvoking: (id <Invoking>)anInvocation;
|
||||
{
|
||||
BOOL flag = YES;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION_WHILE_TRUE(self, o, flag)
|
||||
{
|
||||
[anInvocation invokeWithObject: o];
|
||||
if ([anInvocation returnValueIsTrue])
|
||||
flag = NO;
|
||||
}
|
||||
END_FOR_COLLECTION_WHILE_TRUE(self);
|
||||
return !flag;
|
||||
}
|
||||
|
||||
- detectObjectByInvoking: (id <Invoking>)anInvocation;
|
||||
{
|
||||
BOOL flag = YES;
|
||||
id detectedObject = nil;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION_WHILE_TRUE(self, o, flag)
|
||||
{
|
||||
[anInvocation invokeWithObject: o];
|
||||
if ([anInvocation returnValueIsTrue])
|
||||
{
|
||||
flag = NO;
|
||||
detectedObject = o;
|
||||
}
|
||||
}
|
||||
END_FOR_COLLECTION_WHILE_TRUE(self);
|
||||
if (flag)
|
||||
return NO_OBJECT;
|
||||
else
|
||||
return detectedObject;
|
||||
}
|
||||
|
||||
- maxObject
|
||||
{
|
||||
id o, max = nil;
|
||||
BOOL firstTime = YES;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
firstTime = NO;
|
||||
max = o;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([o compare: max] > 0)
|
||||
max = o;
|
||||
}
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
return max;
|
||||
}
|
||||
|
||||
- minObject
|
||||
{
|
||||
id o, min = nil;
|
||||
BOOL firstTime = YES;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
firstTime = NO;
|
||||
min = o;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ([o compare: min] < 0)
|
||||
min = o;
|
||||
}
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
return min;
|
||||
}
|
||||
|
||||
/* Consider adding:
|
||||
- maxObjectByInvoking: (id <Invoking>)anInvocation;
|
||||
- minObjectByInvoking: (id <Invoking>)anInvocation;
|
||||
*/
|
||||
|
||||
|
||||
// ENUMERATING;
|
||||
|
||||
- (id <Enumerating>) objectEnumerator
|
||||
{
|
||||
return [[[Enumerator alloc] initWithCollection: self]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- (void) withObjectsInvoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[anInvocation invokeWithObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) withObjectsInvoke: (id <Invoking>)anInvocation whileTrue:(BOOL *)flag;
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION_WHILE_TRUE(self, o, *flag)
|
||||
{
|
||||
[anInvocation invokeWithObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION_WHILE_TRUE(self);
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerform: (SEL)aSel
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[o performSelector: aSel];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerform: (SEL)aSel withObject: argObject
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[o performSelector: aSel withObject: argObject];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FILTERED ENUMERATING;
|
||||
|
||||
- (void) withObjectsTrueByInvoking: (id <Invoking>)testInvocation
|
||||
invoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[testInvocation invokeWithObject: o];
|
||||
if ([testInvocation returnValueIsTrue])
|
||||
[anInvocation invokeWithObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) withObjectsFalseByInvoking: (id <Invoking>)testInvocation
|
||||
invoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[testInvocation invokeWithObject: o];
|
||||
if (![testInvocation returnValueIsTrue])
|
||||
[anInvocation invokeWithObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) withObjectsTransformedByInvoking: (id <Invoking>)transInvocation
|
||||
invoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[transInvocation invokeWithObject: o];
|
||||
[anInvocation invokeWithObject: [transInvocation objectReturnValue]];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// LOW-LEVEL ENUMERATING;
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
- nextObjectWithEnumState: (void**)enumState;
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
*enumState = (void*)0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// COPYING;
|
||||
|
||||
- allocCopy
|
||||
{
|
||||
return NSCopyObject (self, 0, [self zone]);
|
||||
}
|
||||
|
||||
// the copy to be filled by -shallowCopyAs: etc... ;
|
||||
- emptyCopy
|
||||
{
|
||||
// This will copy all instance vars;
|
||||
// Subclasses will have to change instance vars like Array's _contents_array;
|
||||
return [self allocCopy];
|
||||
}
|
||||
|
||||
// the copy to be filled by -shallowCopyAs: etc... ;
|
||||
- emptyCopyAs: (Class)aCollectionClass
|
||||
{
|
||||
if (aCollectionClass == [self species])
|
||||
return [self emptyCopy];
|
||||
else
|
||||
return [[(id)aCollectionClass alloc] init];
|
||||
}
|
||||
|
||||
- shallowCopy
|
||||
{
|
||||
return [self shallowCopyAs:[self species]];
|
||||
}
|
||||
|
||||
- shallowCopyAs: (Class)aCollectionClass
|
||||
{
|
||||
id newColl = [self emptyCopyAs:aCollectionClass];
|
||||
//#warning fix this addContentsOf for ConstantCollection
|
||||
[newColl addContentsOf:self];
|
||||
return newColl;
|
||||
}
|
||||
|
||||
/* We can avoid the ugly [self safeWithElementsCall:doIt];
|
||||
in -deepen with something like this instead.
|
||||
This fits with a scheme in which we get rid of the -deepen method, an
|
||||
idea that I like since calling deepen on an object that has not just
|
||||
been -shallowCopy'ed can cause major memory leakage. */
|
||||
- copyAs: (id <Collecting>)aCollectionClass
|
||||
{
|
||||
id newColl = [self emptyCopyAs: (Class)aCollectionClass];
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
//#warning fix this addObject for ConstantCollection
|
||||
id n = [o copy];
|
||||
[newColl addObject:n];
|
||||
[n release];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
return newColl;
|
||||
}
|
||||
|
||||
- species
|
||||
{
|
||||
return [self class];
|
||||
}
|
||||
|
||||
|
||||
// EXTRAS;
|
||||
|
||||
- (const char *) libobjectsLicense
|
||||
{
|
||||
const char *licenseString =
|
||||
"Copyright (C) 1993,1994,1995,1996 Free Software Foundation, Inc.\n"
|
||||
"\n"
|
||||
"Chief Maintainer: Andrew McCallum <mccallum@gnu.ai.mit.edu>\n"
|
||||
"\n"
|
||||
"This object is part of the GNUstep Base Library.\n"
|
||||
"\n"
|
||||
"This library is free software; you can redistribute it and/or\n"
|
||||
"modify it under the terms of the GNU Library General Public\n"
|
||||
"License as published by the Free Software Foundation; either\n"
|
||||
"version 2 of the License, or (at your option) any later version.\n"
|
||||
"\n"
|
||||
"This library is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
|
||||
"Library General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU Library General Public\n"
|
||||
"License along with this library; if not, write to the Free\n"
|
||||
"Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.\n";
|
||||
return licenseString;
|
||||
}
|
||||
|
||||
- printForDebugger
|
||||
{
|
||||
id o;
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
printf("%s ", [[o description] cString]);
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
printf(": %s\n", object_get_class_name (self));
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[self _encodeCollectionWithCoder:aCoder];
|
||||
[self _encodeContentsWithCoder:aCoder];
|
||||
}
|
||||
|
||||
- initWithCoder: aCoder
|
||||
{
|
||||
[self _initCollectionWithCoder:aCoder];
|
||||
[self _decodeContentsWithCoder:aCoder];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation ConstantCollection (ArchivingHelpers)
|
||||
|
||||
- (void) _encodeCollectionWithCoder: aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
// there are no instance vars;
|
||||
return;
|
||||
}
|
||||
|
||||
- _initCollectionWithCoder: aCoder
|
||||
{
|
||||
// there are no instance vars;
|
||||
return [super initWithCoder:aCoder];
|
||||
}
|
||||
|
||||
- (void) _encodeContentsWithCoder: (id <Encoding>)aCoder
|
||||
{
|
||||
unsigned int count = [self count];
|
||||
id o;
|
||||
|
||||
[aCoder encodeValueOfCType: @encode(unsigned)
|
||||
at: &count
|
||||
withName: @"Collection content count"];
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[aCoder encodeObject: o
|
||||
withName:@"Collection element"];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) _decodeContentsWithCoder: (id <Decoding>)aCoder
|
||||
{
|
||||
id *content_array;
|
||||
unsigned int count, i;
|
||||
|
||||
[aCoder decodeValueOfCType:@encode(unsigned)
|
||||
at:&count
|
||||
withName:NULL];
|
||||
content_array = alloca (sizeof (id) * count);
|
||||
for (i = 0; i < count; i++)
|
||||
[aCoder decodeObjectAt: &(content_array[i])
|
||||
withName:NULL];
|
||||
[self initWithObjects: content_array count: count];
|
||||
for (i = 0; i < count; i++)
|
||||
[content_array[i] release];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation ConstantCollection (DeallocationHelpers)
|
||||
|
||||
/* This must work without sending any messages to content objects.
|
||||
Content objects already may be dealloc'd when this is executed. */
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) _collectionReleaseContents
|
||||
{
|
||||
int c = [self count];
|
||||
if (c)
|
||||
{
|
||||
id *array = (id*) alloca (c * sizeof(id));
|
||||
int i = 0;
|
||||
void *es = [self newEnumState];
|
||||
id o;
|
||||
while ((o = [self nextObjectWithEnumState:&es]))
|
||||
{
|
||||
array[i++] = o;
|
||||
}
|
||||
[self freeEnumState: &es];
|
||||
for (i = 0; i < c; i++)
|
||||
[array[i] release];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _collectionDealloc
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation Collection
|
||||
|
||||
// ADDING;
|
||||
|
||||
- (void) addObject: anObject
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) addObjectIfAbsent: newObject;
|
||||
{
|
||||
if (![self containsObject: newObject])
|
||||
[self addObject: newObject];
|
||||
}
|
||||
|
||||
- (void) addContentsOf: (id <Collecting>)aCollection
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(aCollection, o)
|
||||
{
|
||||
[self addObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(aCollection);
|
||||
}
|
||||
|
||||
- (void) addContentsIfAbsentOf: (id <Collecting>)aCollection
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(aCollection, o)
|
||||
{
|
||||
if (![self containsObject:o])
|
||||
[self addObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(aCollection);
|
||||
}
|
||||
|
||||
- (void) addWithObjects: (id*)objc count: (unsigned)c
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
- (void) addObjects: firstObject, ...
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
- (void) addObjects: firstObject rest: (va_list)ap
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// REMOVING AND REPLACING;
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (void) removeAllOccurrencesOfObject: oldObject
|
||||
{
|
||||
while ([self containsObject: oldObject])
|
||||
[self removeObject: oldObject];
|
||||
}
|
||||
|
||||
- (void) removeContentsIn: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(aCollection, o)
|
||||
{
|
||||
[self removeObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(aCollection);
|
||||
}
|
||||
|
||||
- (void) removeContentsNotIn: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
if (![aCollection containsObject: o])
|
||||
[self removeObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) uniqueContents
|
||||
{
|
||||
id cp = [self shallowCopy];
|
||||
int count;
|
||||
id o;
|
||||
|
||||
FOR_COLLECTION(cp, o)
|
||||
{
|
||||
count = [self occurrencesOfObject: o];
|
||||
if (!count)
|
||||
continue;
|
||||
while (count--)
|
||||
[self removeObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(cp);
|
||||
}
|
||||
|
||||
/* May be inefficient. Could be overridden; */
|
||||
- (void) empty
|
||||
{
|
||||
if ([self isEmpty])
|
||||
return;
|
||||
[self _collectionReleaseContents];
|
||||
[self _collectionEmpty];
|
||||
}
|
||||
|
||||
|
||||
// REPLACING;
|
||||
|
||||
- (void) replaceObject: oldObject withObject: newObject
|
||||
{
|
||||
if ([newObject isEqual: newObject])
|
||||
return;
|
||||
[oldObject retain];
|
||||
[self removeObject: oldObject];
|
||||
[self addObject: newObject];
|
||||
[oldObject release];
|
||||
}
|
||||
|
||||
- (void) replaceAllOccurrencesOfObject: oldObject withObject: newObject
|
||||
{
|
||||
if ([oldObject isEqual: newObject])
|
||||
return;
|
||||
while ([self containsObject: oldObject])
|
||||
[self replaceObject: oldObject withObject: newObject];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,210 +0,0 @@
|
|||
/* Implementation of Objective-C "collection of delegates" object
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNU Objective-C Collection library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/DelegatePool.h>
|
||||
#include <base/NSString.h>
|
||||
|
||||
@implementation DelegatePool
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+ alloc
|
||||
{
|
||||
return (id)class_create_instance(self);
|
||||
}
|
||||
|
||||
+ new
|
||||
{
|
||||
return [[self alloc] init];
|
||||
}
|
||||
|
||||
/* This is the designated initializer for this class. */
|
||||
- init
|
||||
{
|
||||
_list = [[Array alloc] init];
|
||||
_send_behavior = SEND_TO_ALL;
|
||||
_last_message_had_receivers = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[anEncoder encodeValueOfCType:@encode(unsigned char)
|
||||
at:&_send_behavior
|
||||
withName:@"DelegatePool Send Behavior"];
|
||||
[anEncoder encodeObject:_list
|
||||
withName:@"DelegatePool Collection of Delegates"];
|
||||
}
|
||||
|
||||
+ newWithCoder: aDecoder
|
||||
{
|
||||
/* xxx Should be:
|
||||
DelegatePool *n = NSAllocateObject(self, 0, [aDecoder objectZone]); */
|
||||
DelegatePool *n = (id) NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
[aDecoder decodeValueOfCType:@encode(unsigned char)
|
||||
at:&(n->_send_behavior)
|
||||
withName:NULL];
|
||||
[aDecoder decodeObjectAt:&(n->_list)
|
||||
withName:NULL];
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
- write: (TypedStream*)aStream
|
||||
{
|
||||
objc_write_type(aStream, @encode(unsigned char), &_send_behavior);
|
||||
objc_write_object(aStream, _list);
|
||||
return self;
|
||||
}
|
||||
|
||||
- read: (TypedStream*)aStream
|
||||
{
|
||||
objc_write_type(aStream, @encode(unsigned char), &_send_behavior);
|
||||
objc_read_object(aStream, &_list);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_list release];
|
||||
#if NeXT_runtime
|
||||
object_dispose((Object*)self);
|
||||
#else
|
||||
NSDeallocateObject((NSObject*)self);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// MANIPULATING COLLECTION OF DELEGATES;
|
||||
|
||||
- (void) delegatePoolAddObject: anObject
|
||||
{
|
||||
[_list addObject: anObject];
|
||||
}
|
||||
|
||||
- (void) delegatePoolAddObjectIfAbsent: anObject
|
||||
{
|
||||
[_list addObjectIfAbsent: anObject];
|
||||
}
|
||||
|
||||
- (void) delegatePoolRemoveObject: anObject
|
||||
{
|
||||
[_list removeObject:anObject];
|
||||
}
|
||||
|
||||
- (BOOL) delegatePoolIncludesObject: anObject
|
||||
{
|
||||
return [_list containsObject:anObject];
|
||||
}
|
||||
|
||||
- delegatePoolCollection
|
||||
{
|
||||
return _list;
|
||||
}
|
||||
|
||||
- (unsigned char) delegatePoolSendBehavior
|
||||
{
|
||||
return _send_behavior;
|
||||
}
|
||||
|
||||
- (void) delegatePoolSetSendBehavior: (unsigned char)b
|
||||
{
|
||||
_send_behavior = b;
|
||||
}
|
||||
|
||||
- (BOOL) delegatePoolLastMessageHadReceivers
|
||||
{
|
||||
return _last_message_had_receivers;
|
||||
}
|
||||
|
||||
// FOR PASSING ALL OTHER MESSAGES TO DELEGATES;
|
||||
|
||||
- forward: (SEL)aSel :(arglist_t)argFrame
|
||||
{
|
||||
void *ret = 0;
|
||||
id delegate;
|
||||
|
||||
_last_message_had_receivers = NO;
|
||||
switch (_send_behavior)
|
||||
{
|
||||
case SEND_TO_ALL:
|
||||
FOR_ARRAY(_list, delegate)
|
||||
{
|
||||
if ([delegate respondsTo:aSel])
|
||||
{
|
||||
ret = [delegate performv:aSel :argFrame];
|
||||
_last_message_had_receivers = YES;
|
||||
}
|
||||
}
|
||||
END_FOR_ARRAY (_list);
|
||||
break;
|
||||
|
||||
case SEND_TO_FIRST_RESPONDER:
|
||||
FOR_ARRAY(_list, delegate)
|
||||
{
|
||||
if ([delegate respondsTo:aSel])
|
||||
{
|
||||
_last_message_had_receivers = YES;
|
||||
return [delegate performv:aSel :argFrame];
|
||||
}
|
||||
}
|
||||
END_FOR_ARRAY (_list);
|
||||
break;
|
||||
|
||||
case SEND_UNTIL_YES:
|
||||
FOR_ARRAY(_list, delegate)
|
||||
{
|
||||
if ([delegate respondsTo:aSel])
|
||||
{
|
||||
_last_message_had_receivers = YES;
|
||||
if ((ret = [delegate performv:aSel :argFrame]))
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
END_FOR_ARRAY (_list);
|
||||
break;
|
||||
|
||||
case SEND_UNTIL_NO:
|
||||
FOR_ARRAY(_list, delegate)
|
||||
{
|
||||
if ([delegate respondsTo:aSel])
|
||||
{
|
||||
_last_message_had_receivers = YES;
|
||||
if (!(ret = [delegate performv:aSel :argFrame]))
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
END_FOR_ARRAY (_list);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,209 +0,0 @@
|
|||
/* Implementation for Objective-C Dictionary collection object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Dictionary.h>
|
||||
#include <base/CollectionPrivate.h>
|
||||
#include <Foundation/NSCharacterSet.h>
|
||||
|
||||
#define DEFAULT_DICTIONARY_CAPACITY 32
|
||||
|
||||
@implementation Dictionary
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
||||
/* Eventually we will want to have better capacity management,
|
||||
potentially keep default capacity as a class variable. */
|
||||
|
||||
+ (unsigned) defaultCapacity
|
||||
{
|
||||
return DEFAULT_DICTIONARY_CAPACITY;
|
||||
}
|
||||
|
||||
// INITIALIZING;
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithCapacity: (unsigned)cap
|
||||
{
|
||||
_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 */
|
||||
|
||||
- _initCollectionWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
_contents_hash = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
0);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
|
||||
- emptyCopy
|
||||
{
|
||||
Dictionary *copy = [super emptyCopy];
|
||||
copy->_contents_hash = NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
0);
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void) _collectionReleaseContents
|
||||
{
|
||||
if (_contents_hash) {
|
||||
NSFreeMapTable (_contents_hash);
|
||||
_contents_hash = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self _collectionReleaseContents];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
NSResetMapTable (_contents_hash);
|
||||
}
|
||||
|
||||
|
||||
// ADDING OR REPLACING;
|
||||
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
/* or should I make up some default behavior here?
|
||||
Base it on object conforming to <Associating> protocol, perhaps */
|
||||
}
|
||||
|
||||
- (void) putObject: newObject atKey: aKey
|
||||
{
|
||||
NSMapInsert (_contents_hash, aKey, newObject);
|
||||
}
|
||||
|
||||
|
||||
// REMOVING;
|
||||
|
||||
- (void) removeObjectAtKey: aKey
|
||||
{
|
||||
NSMapRemove (_contents_hash, aKey);
|
||||
}
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
/* xxx Could be more efficient! */
|
||||
int count = [self count];
|
||||
id keys_to_remove[count];
|
||||
int num_keys_to_remove = 0;
|
||||
id o, k;
|
||||
NSMapEnumerator me = NSEnumerateMapTable (_contents_hash);
|
||||
|
||||
/* Find all the keys with corresponding objects that equal oldObject. */
|
||||
while (NSNextMapEnumeratorPair (&me, (void**)&k, (void**)&o))
|
||||
if ([oldObject isEqual: o])
|
||||
keys_to_remove[num_keys_to_remove++] = k;
|
||||
/* Remove them. */
|
||||
while (num_keys_to_remove--)
|
||||
[self removeObjectAtKey: keys_to_remove[num_keys_to_remove]];
|
||||
}
|
||||
|
||||
|
||||
// GETTING ELEMENTS;
|
||||
|
||||
- (NSArray*) allKeys
|
||||
{
|
||||
return NSAllMapTableKeys(_contents_hash);
|
||||
}
|
||||
|
||||
- (NSArray*) allValues
|
||||
{
|
||||
return NSAllMapTableValues(_contents_hash);
|
||||
}
|
||||
|
||||
- objectAtKey: aKey
|
||||
{
|
||||
return NSMapGet (_contents_hash, aKey);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (BOOL) containsKey: aKey
|
||||
{
|
||||
if (NSMapGet (_contents_hash, aKey))
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return NSCountMapTable (_contents_hash);
|
||||
}
|
||||
|
||||
// ENUMERATIONS;
|
||||
|
||||
- nextObjectAndKey: (id*)aKeyPtr withEnumState: (void**)enumState
|
||||
{
|
||||
id o;
|
||||
if (!NSNextMapEnumeratorPair (*enumState, (void**)aKeyPtr, (void**)&o))
|
||||
return NO_OBJECT;
|
||||
return o;
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
void *me;
|
||||
|
||||
OBJC_MALLOC (me, NSMapEnumerator, 1);
|
||||
*((NSMapEnumerator*)me) = NSEnumerateMapTable (_contents_hash);
|
||||
return me;
|
||||
}
|
||||
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
OBJC_FREE (*enumState);
|
||||
}
|
||||
|
||||
@end
|
|
@ -69,42 +69,17 @@ FILE_AUTHORS = \
|
|||
# The GNU source files
|
||||
|
||||
GNU_MFILES = \
|
||||
Archiver.m \
|
||||
Array.m \
|
||||
Bag.m \
|
||||
BinaryCStream.m \
|
||||
BinaryTree.m \
|
||||
BinaryTreeNode.m \
|
||||
CircularArray.m \
|
||||
Collection.m \
|
||||
ConnectedCoder.m \
|
||||
Coder.m \
|
||||
CStream.m \
|
||||
Decoder.m \
|
||||
DelegatePool.m \
|
||||
Dictionary.m \
|
||||
Encoder.m \
|
||||
GapArray.m \
|
||||
GetDefEncoding.m \
|
||||
Heap.m \
|
||||
IndexedCollection.m \
|
||||
Invocation.m \
|
||||
KeyedCollection.m \
|
||||
LinkedList.m \
|
||||
LinkedListNode.m \
|
||||
MachPort.m \
|
||||
MappedCollector.m \
|
||||
MemoryStream.m \
|
||||
NotificationDispatcher.m \
|
||||
OrderedCollection.m \
|
||||
Port.m \
|
||||
Queue.m \
|
||||
RawCStream.m \
|
||||
RBTree.m \
|
||||
RBTreeNode.m \
|
||||
Set.m \
|
||||
SplayTree.m \
|
||||
Stack.m \
|
||||
StdioStream.m \
|
||||
Stream.m \
|
||||
TcpPort.m \
|
||||
|
@ -137,11 +112,6 @@ mframe.m \
|
|||
objc-gnu2next.m
|
||||
|
||||
GNU_EXTRAS_MFILES = \
|
||||
Magnitude.m \
|
||||
Random.m \
|
||||
RNGAdditiveCongruential.m \
|
||||
RNGBerkeley.m \
|
||||
Time.m
|
||||
|
||||
GNU_CFILES = \
|
||||
md5.c \
|
||||
|
@ -163,59 +133,23 @@ fast.x \
|
|||
GSUnion.h \
|
||||
GSIArray.h \
|
||||
GSIMap.h \
|
||||
Archiver.h \
|
||||
Array.h \
|
||||
ArrayPrivate.h \
|
||||
Bag.h \
|
||||
BinaryCStream.h \
|
||||
BinaryTree.h \
|
||||
BinaryTreeNode.h \
|
||||
CircularArray.h \
|
||||
CircularArrayPrivate.h \
|
||||
Coder.h \
|
||||
CoderPrivate.h \
|
||||
Coding.h \
|
||||
Collecting.h \
|
||||
Collection.h \
|
||||
CollectionPrivate.h \
|
||||
ConnectedCoder.h \
|
||||
CStream.h \
|
||||
CStreaming.h \
|
||||
DelegatePool.h \
|
||||
Dictionary.h \
|
||||
Enumerating.h \
|
||||
GapArray.h \
|
||||
GapArrayPrivate.h \
|
||||
GetDefEncoding.h \
|
||||
Heap.h \
|
||||
IndexedCollecting.h \
|
||||
IndexedCollection.h \
|
||||
IndexedCollectionPrivate.h \
|
||||
InvalidationListening.h \
|
||||
Invocation.h \
|
||||
Invoking.h \
|
||||
KeyedCollecting.h \
|
||||
KeyedCollection.h \
|
||||
LinkedList.h \
|
||||
LinkedListNode.h \
|
||||
Locking.h \
|
||||
MachPort.h \
|
||||
MappedCollector.h \
|
||||
MemoryStream.h \
|
||||
NotificationDispatcher.h \
|
||||
Ordering.h \
|
||||
OrderedCollecting.h \
|
||||
OrderedCollection.h \
|
||||
Port.h \
|
||||
Queue.h \
|
||||
RBTree.h \
|
||||
RBTreeNode.h \
|
||||
RawCStream.h \
|
||||
Retaining.h \
|
||||
RunLoop.h \
|
||||
Set.h \
|
||||
SplayTree.h \
|
||||
Stack.h \
|
||||
StdioStream.h \
|
||||
Stream.h \
|
||||
Streaming.h \
|
||||
|
@ -245,13 +179,6 @@ objc-gnu2next.h \
|
|||
preface.h
|
||||
|
||||
GNU_EXTRAS_HFILES = \
|
||||
all.h \
|
||||
Magnitude.h \
|
||||
Random.h \
|
||||
RNGAdditiveCongruential.h \
|
||||
RNGBerkeley.h \
|
||||
RandomGenerating.h \
|
||||
Time.h
|
||||
|
||||
# GNUStep source files
|
||||
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
/* Implementation for Objective-C GapArray collection object
|
||||
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: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <base/GapArray.h>
|
||||
#include <base/GapArrayPrivate.h>
|
||||
|
||||
@implementation GapArray
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
/* Override designated initializer of superclass */
|
||||
- initWithCapacity: (unsigned)aCapacity
|
||||
{
|
||||
[super initWithCapacity: aCapacity];
|
||||
_gap_start = 0;
|
||||
_gap_size = aCapacity;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
+ newWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
|
||||
- emptyCopy
|
||||
{
|
||||
GapArray *copy = [super emptyCopy];
|
||||
copy->_gap_start = 0;
|
||||
copy->_gap_size = copy->_capacity;
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void) empty
|
||||
{
|
||||
[super empty];
|
||||
_gap_start = 0;
|
||||
_gap_size = _capacity;
|
||||
}
|
||||
|
||||
- (void) setCapacity: (unsigned)newCapacity
|
||||
{
|
||||
if (newCapacity > _count)
|
||||
{
|
||||
gapMoveGapTo (self, _capacity-_gap_size); /* move gap to end */
|
||||
[super setCapacity: newCapacity]; /* resize */
|
||||
_gap_size = _capacity - _gap_start;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
[_contents_array[GAP_TO_BASIC (index)] release];
|
||||
gapFillHoleAt (self, index);
|
||||
decrementCount(self);
|
||||
}
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
return _contents_array[GAP_TO_BASIC(index)];
|
||||
}
|
||||
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
gapMakeHoleAt (self, _count-1);
|
||||
_contents_array[_count-1] = newObject;
|
||||
}
|
||||
|
||||
- (void) prependObject: newObject
|
||||
{
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
gapMakeHoleAt (self, 0);
|
||||
_contents_array[0] = newObject;
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count+1);
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
gapMakeHoleAt (self, index);
|
||||
_contents_array[index] = newObject;
|
||||
}
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
[newObject retain];
|
||||
[_contents_array[GAP_TO_BASIC(index)] release];
|
||||
_contents_array[GAP_TO_BASIC(index)] = newObject;
|
||||
}
|
||||
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
{
|
||||
id tmp;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index1, _count);
|
||||
CHECK_INDEX_RANGE_ERROR(index2, _count);
|
||||
index1 = GAP_TO_BASIC(index1);
|
||||
index2 = GAP_TO_BASIC(index2);
|
||||
tmp = _contents_array[index1];
|
||||
_contents_array[index1] = _contents_array[index2];
|
||||
_contents_array[index2] = tmp;
|
||||
}
|
||||
|
||||
@end
|
||||
|
102
Source/Heap.m
102
Source/Heap.m
|
@ -1,102 +0,0 @@
|
|||
/* Implementation for Objective-C Heap object
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/* This class could be improved by somehow making is a subclass of
|
||||
IndexedCollection, but not OrderedCollection. */
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Heap.h>
|
||||
#include <base/ArrayPrivate.h>
|
||||
|
||||
#define HEAP_PARENT(i) (i/2)
|
||||
#define HEAP_LEFT(i) (2 * i)
|
||||
#define HEAP_RIGHT(i) ((2 * i) + 1)
|
||||
|
||||
@implementation Heap
|
||||
|
||||
/* We could take out the recursive call to make it a little more efficient */
|
||||
- (void) heapifyFromIndex: (unsigned)index
|
||||
{
|
||||
unsigned right, left, largest;
|
||||
id tmp;
|
||||
|
||||
right = HEAP_RIGHT(index);
|
||||
left = HEAP_LEFT(index);
|
||||
if (left < _count
|
||||
&& [_contents_array[index] compare: _contents_array[left]] > 0)
|
||||
largest = left;
|
||||
else
|
||||
largest = index;
|
||||
if (right < _count
|
||||
&& [_contents_array[largest] compare: _contents_array[right]] > 0)
|
||||
largest = right;
|
||||
if (largest != index)
|
||||
{
|
||||
tmp = _contents_array[index];
|
||||
_contents_array[index] = _contents_array[largest];
|
||||
_contents_array[largest] = tmp;
|
||||
[self heapifyFromIndex:largest];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) heapify
|
||||
{
|
||||
int i;
|
||||
|
||||
// could use objc_msg_lookup here;
|
||||
for (i = _count / 2; i >= 1; i--)
|
||||
[self heapifyFromIndex:i];
|
||||
}
|
||||
|
||||
- (void) removeFirstObject
|
||||
{
|
||||
if (_count == 0)
|
||||
return;
|
||||
[_contents_array[0] release];
|
||||
_contents_array[0] = _contents_array[_count-1];
|
||||
decrementCount(self);
|
||||
[self heapifyFromIndex:0];
|
||||
}
|
||||
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
int i;
|
||||
|
||||
incrementCount(self);
|
||||
[newObject retain];
|
||||
for (i = _count-1;
|
||||
i > 0
|
||||
&& [newObject compare: _contents_array[HEAP_PARENT(i)]] < 0;
|
||||
i = HEAP_PARENT(i))
|
||||
{
|
||||
_contents_array[i] = _contents_array[HEAP_PARENT(i)];
|
||||
}
|
||||
_contents_array[i] = newObject;
|
||||
}
|
||||
|
||||
- (id) minObject
|
||||
{
|
||||
return [self firstObject];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,466 +0,0 @@
|
|||
/* Implementation for Objective-C IndexedCollection object
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/IndexedCollection.h>
|
||||
#include <base/IndexedCollectionPrivate.h>
|
||||
#include <stdio.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/behavior.h>
|
||||
|
||||
@implementation ReverseEnumerator
|
||||
|
||||
- nextObject
|
||||
{
|
||||
return [collection prevObjectWithEnumState: &enum_state];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation ConstantIndexedCollection
|
||||
|
||||
|
||||
// GETTING MEMBERS BY INDEX;
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- firstObject
|
||||
{
|
||||
if ([self isEmpty])
|
||||
return nil;
|
||||
return [self objectAtIndex: 0];
|
||||
}
|
||||
|
||||
- lastObject
|
||||
{
|
||||
if ([self isEmpty])
|
||||
return nil;
|
||||
return [self objectAtIndex: [self count]-1];
|
||||
}
|
||||
|
||||
|
||||
// GETTING MEMBERS BY NEIGHBOR;
|
||||
|
||||
/* Should be overriden by linked-list-type classes */
|
||||
- successorOfObject: anObject
|
||||
{
|
||||
int last = [self count] - 1;
|
||||
int index = [self indexOfObject: anObject];
|
||||
if (index == last)
|
||||
return nil;
|
||||
return [self objectAtIndex: index+1];
|
||||
}
|
||||
|
||||
/* Should be overriden by linked-list-type classes */
|
||||
- predecessorOfObject: anObject
|
||||
{
|
||||
int index = [self indexOfObject: anObject];
|
||||
if (index == 0)
|
||||
return nil;
|
||||
return [self objectAtIndex: index-1];
|
||||
}
|
||||
|
||||
|
||||
// GETTING INDICES BY MEMBER;
|
||||
|
||||
- (unsigned) indexOfObject: anObject
|
||||
{
|
||||
int i, count = [self count];
|
||||
for (i = 0; i < count; i++)
|
||||
if ([anObject isEqual: [self objectAtIndex:i]])
|
||||
return i;
|
||||
return NO_INDEX;
|
||||
}
|
||||
|
||||
- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange
|
||||
{
|
||||
int i;
|
||||
|
||||
/* xxx check that aRange is within count */
|
||||
for (i = aRange.location; i < aRange.location+aRange.length; i++)
|
||||
if ([anObject isEqual: [self objectAtIndex:i]])
|
||||
return i - aRange.location;
|
||||
return NO_INDEX;
|
||||
}
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (BOOL) contentsEqualInOrder: (id <ConstantIndexedCollecting>)aColl
|
||||
{
|
||||
id o1, o2;
|
||||
void *s1, *s2;
|
||||
|
||||
if ([self count] != [aColl count])
|
||||
return NO;
|
||||
s1 = [self newEnumState];
|
||||
s2 = [aColl newEnumState];
|
||||
while ((o1 = [self nextObjectWithEnumState:&s1])
|
||||
&& (o2 = [aColl nextObjectWithEnumState:&s2]))
|
||||
{
|
||||
if (![o1 isEqual: o2])
|
||||
{
|
||||
[self freeEnumState:&s1];
|
||||
[aColl freeEnumState:&s2];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
[self freeEnumState:&s1];
|
||||
[aColl freeEnumState:&s2];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int) compareInOrderContentsOf: (id <Collecting>)aCollection
|
||||
{
|
||||
void *es1 = [self newEnumState];
|
||||
void *es2 = [aCollection newEnumState];
|
||||
id o1, o2;
|
||||
int comparison;
|
||||
while ((o1 = [self nextObjectWithEnumState:&es1])
|
||||
&& (o2 = [aCollection nextObjectWithEnumState:&es2]))
|
||||
{
|
||||
if ((comparison = [o1 compare: o2]))
|
||||
{
|
||||
[self freeEnumState:&es1];
|
||||
[aCollection freeEnumState:&es2];
|
||||
return comparison;
|
||||
}
|
||||
}
|
||||
if ((comparison = ([self count] - [aCollection count])))
|
||||
return comparison;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (unsigned) indexOfFirstDifference: (id <ConstantIndexedCollecting>)aColl
|
||||
{
|
||||
unsigned i = 0;
|
||||
BOOL flag = YES;
|
||||
void *enumState = [self newEnumState];
|
||||
id o1, o2;
|
||||
FOR_INDEXED_COLLECTION_WHILE_TRUE(self, o1, flag)
|
||||
{
|
||||
if ((!(o2 = [self nextObjectWithEnumState: &enumState]))
|
||||
|| [o1 isEqual: o2])
|
||||
flag = NO;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
END_FOR_INDEXED_COLLECTION_WHILE_TRUE(self);
|
||||
[self freeEnumState: &enumState];
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Could be more efficient */
|
||||
- (unsigned) indexOfFirstIn: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
unsigned index = 0;
|
||||
BOOL flag = YES;
|
||||
id o;
|
||||
|
||||
FOR_INDEXED_COLLECTION_WHILE_TRUE(self, o, flag)
|
||||
{
|
||||
if ([aCollection containsObject: o])
|
||||
flag = NO;
|
||||
else
|
||||
index++;
|
||||
}
|
||||
END_FOR_INDEXED_COLLECTION(self);
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Could be more efficient */
|
||||
- (unsigned) indexOfFirstNotIn: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
unsigned index = 0;
|
||||
BOOL flag = YES;
|
||||
id o;
|
||||
|
||||
FOR_INDEXED_COLLECTION_WHILE_TRUE(self, o, flag)
|
||||
{
|
||||
if (![aCollection containsObject: o])
|
||||
flag = NO;
|
||||
else
|
||||
index++;
|
||||
}
|
||||
END_FOR_INDEXED_COLLECTION(self);
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
// ENUMERATING;
|
||||
|
||||
- (id <Enumerating>) reverseObjectEnumerator
|
||||
{
|
||||
return [[[ReverseEnumerator alloc] initWithCollection: self]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- (void) withObjectsInRange: (IndexRange)aRange
|
||||
invoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
int i;
|
||||
for (i = aRange.location; i < aRange.location + aRange.length; i++)
|
||||
[anInvocation invokeWithObject: [self objectAtIndex: i]];
|
||||
}
|
||||
|
||||
- (void) withObjectsInReverseInvoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
int i, count = [self count];
|
||||
for (i = count-1; i >= 0; i--)
|
||||
[anInvocation invokeWithObject: [self objectAtIndex: i]];
|
||||
}
|
||||
|
||||
- (void) withObjectsInReverseInvoke: (id <Invoking>)anInvocation
|
||||
whileTrue:(BOOL *)flag
|
||||
{
|
||||
int i, count = [self count];
|
||||
for (i = count-1; *flag && i >= 0; i--)
|
||||
[anInvocation invokeWithObject: [self objectAtIndex: i]];
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerformInReverse: (SEL)aSel
|
||||
{
|
||||
id o;
|
||||
FOR_INDEXED_COLLECTION_REVERSE(self, o)
|
||||
{
|
||||
[o performSelector: aSel];
|
||||
}
|
||||
END_FOR_INDEXED_COLLECTION_REVERSE(self);
|
||||
}
|
||||
|
||||
- (void) makeObjectsPerformInReverse: (SEL)aSel withObject: argObject
|
||||
{
|
||||
id o;
|
||||
FOR_INDEXED_COLLECTION_REVERSE(self, o)
|
||||
{
|
||||
[o performSelector: aSel withObject: argObject];
|
||||
}
|
||||
END_FOR_INDEXED_COLLECTION_REVERSE(self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// LOW-LEVEL ENUMERATING;
|
||||
|
||||
- prevObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
/* *(int*)enumState is the index of the element that was returned
|
||||
last time -prevObjectWithEnumState: or -nextObjectWithEnumState
|
||||
was called. In -newEnumState, *(int*)enumState is initialized to
|
||||
-2; The implementation of -newEnumState can be found below. */
|
||||
|
||||
/* If there are not objects in this collection, or we are being
|
||||
asked for the object before the first object, return nil. */
|
||||
if ([self isEmpty] || ((*(int*)enumState) == 0)
|
||||
|| ((*(int*)enumState) == -1))
|
||||
{
|
||||
(*(int*)enumState) = -1;
|
||||
return NO_OBJECT;
|
||||
}
|
||||
|
||||
if (*(int*)enumState == -2)
|
||||
/* enumState was just initialized by -newEnumState, start
|
||||
at the end of the sequence. */
|
||||
*(int*)enumState = [self count]-1;
|
||||
else
|
||||
/* ...otherwise go the previous index. */
|
||||
(*(int*)enumState)--;
|
||||
|
||||
return [self objectAtIndex:(*(unsigned*)enumState)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// COPYING;
|
||||
|
||||
- shallowCopyRange: (IndexRange)aRange
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- shallowCopyInReverse
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- shallowCopyInReverseRange: (IndexRange)aRange
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
// OVERRIDE SOME COLLECTION METHODS;
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
return (void*) -2;
|
||||
}
|
||||
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
/* *(int*)enumState is the index of the element that was returned
|
||||
last time -prevObjectWithEnumState: or -nextObjectWithEnumState
|
||||
was called. In -newEnumState, *(int*)enumState is initialized to
|
||||
-2. */
|
||||
|
||||
/* If there are not objects in this collection, or we are being
|
||||
asked for the object after the last object, return nil. */
|
||||
if ([self isEmpty] || ((*(int*)enumState) >= (int)([self count]-1)))
|
||||
{
|
||||
(*(int*)enumState) = [self count];
|
||||
return NO_OBJECT;
|
||||
}
|
||||
|
||||
if (*(int*)enumState == -2)
|
||||
/* enumState was just initialized by -newEnumState, start
|
||||
at the beginning of the sequence. */
|
||||
*(int*)enumState = 0;
|
||||
else
|
||||
/* ...otherwise go the next index. */
|
||||
(*(int*)enumState)++;
|
||||
|
||||
return [self objectAtIndex:(*(unsigned*)enumState)];
|
||||
}
|
||||
|
||||
/* is this what we want? */
|
||||
- (BOOL) isEqual: anObject
|
||||
{
|
||||
if (self == anObject)
|
||||
return YES;
|
||||
if ([anObject class] == [self class]
|
||||
&& [self count] != [anObject count]
|
||||
&& [self contentsEqualInOrder: anObject] )
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation IndexedCollection
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [IndexedCollection class])
|
||||
class_add_behavior(self, [Collection class]);
|
||||
}
|
||||
|
||||
|
||||
// REPLACING;
|
||||
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
|
||||
// REMOVING;
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (void) removeFirstObject
|
||||
{
|
||||
[self removeObjectAtIndex: 0];
|
||||
}
|
||||
|
||||
- (void) removeLastObject
|
||||
{
|
||||
[self removeObjectAtIndex: [self count]-1];
|
||||
}
|
||||
|
||||
- (void) removeRange: (IndexRange)aRange
|
||||
{
|
||||
int count = aRange.length;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(aRange.location, [self count]);
|
||||
CHECK_INDEX_RANGE_ERROR(aRange.location+aRange.length-1, [self count]);
|
||||
while (count--)
|
||||
[self removeObjectAtIndex: aRange.location];
|
||||
}
|
||||
|
||||
|
||||
// SORTING;
|
||||
|
||||
- (void) sortContents
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
- (void) sortAddObject: newObject
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
// OVERRIDE SOME COLLECTION METHODS;
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
unsigned index;
|
||||
|
||||
/* Retain the object. Yuck, but necessary in case the array holds
|
||||
the last reference to anObject. */
|
||||
/* xxx Is there an alternative to this expensive retain/release? */
|
||||
[anObject retain];
|
||||
|
||||
for (index = [self indexOfObject: anObject];
|
||||
index != NO_INDEX;
|
||||
index = [self indexOfObject: anObject])
|
||||
[self removeObjectAtIndex: index];
|
||||
|
||||
[anObject release];
|
||||
}
|
||||
|
||||
- (void) replaceObject: oldObject withObject: newObject
|
||||
{
|
||||
unsigned index;
|
||||
|
||||
/* Retain the object. Yuck, but necessary in case the array holds
|
||||
the last reference to anObject. */
|
||||
/* xxx Is there an alternative to this expensive retain/release? */
|
||||
[oldObject retain];
|
||||
|
||||
for (index = [self indexOfObject: oldObject];
|
||||
index != NO_INDEX;
|
||||
index = [self indexOfObject: oldObject])
|
||||
[self replaceObjectAtIndex: index withObject: newObject];
|
||||
|
||||
[oldObject release];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
@ -1,861 +0,0 @@
|
|||
/* Implementation for Objective-C Invocation object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <mframe.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Invocation.h>
|
||||
#include <Foundation/DistributedObjects.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSConnection.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
extern BOOL sel_types_match(const char* t1, const char* t2);
|
||||
|
||||
/* xxx We are currently retaining the return value.
|
||||
We shouldn't always do this. Make is an option. */
|
||||
|
||||
/* Deal with strrchr: */
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
#include <string.h>
|
||||
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
|
||||
#if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
|
||||
#define rindex strrchr
|
||||
#define bcopy(s, d, n) memcpy ((d), (s), (n))
|
||||
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
|
||||
#define bzero(s, n) memset ((s), 0, (n))
|
||||
#else /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
#include <strings.h>
|
||||
/* memory.h and strings.h conflict on some systems. */
|
||||
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
|
||||
/* xxx Perhaps make this an ivar. */
|
||||
#define return_retained 0
|
||||
|
||||
@implementation Invocation
|
||||
|
||||
- initWithReturnType: (const char *)enc
|
||||
{
|
||||
int l = strlen(enc);
|
||||
OBJC_MALLOC(return_type, char, l + 1);
|
||||
memcpy(return_type, enc, l);
|
||||
return_type[l] = '\0';
|
||||
enc = objc_skip_type_qualifiers (return_type);
|
||||
if (*enc != 'v')
|
||||
{
|
||||
/* Work around bug in objc_sizeof_type; it doesn't handle void type */
|
||||
return_size = objc_sizeof_type (enc);
|
||||
return_value = objc_calloc (1, return_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return_size = 0;
|
||||
return_value = NULL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[super encodeWithCoder: coder];
|
||||
[coder encodeValueOfCType: @encode(char*)
|
||||
at: &return_type
|
||||
withName: @"Invocation return type"];
|
||||
[coder encodeValueOfCType: @encode(unsigned)
|
||||
at: &return_size
|
||||
withName: @"Invocation return size"];
|
||||
if (return_size)
|
||||
[coder encodeValueOfObjCType: return_type
|
||||
at: return_value
|
||||
withName: @"Invocation return value"];
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
[coder decodeValueOfCType: @encode(char*)
|
||||
at: &return_type
|
||||
withName: NULL];
|
||||
[coder decodeValueOfCType: @encode(unsigned)
|
||||
at: &return_size
|
||||
withName: NULL];
|
||||
if (return_size)
|
||||
{
|
||||
return_value = objc_malloc (return_size);
|
||||
[coder decodeValueOfObjCType: return_type
|
||||
at: return_value
|
||||
withName: NULL];
|
||||
}
|
||||
else
|
||||
return_value = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (Class) classForConnectedCoder: coder
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy,
|
||||
i.e. as our own class, not a Proxy class. */
|
||||
return [self class];
|
||||
}
|
||||
|
||||
/* Next two methods for OPENSTEP */
|
||||
- (Class) classForPortCoder
|
||||
{
|
||||
return [self class];
|
||||
}
|
||||
- replacementObjectForPortCoder: coder
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) invokeWithObject: anObj
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (const char *) returnType
|
||||
{
|
||||
return return_type;
|
||||
}
|
||||
|
||||
- (unsigned) returnSize
|
||||
{
|
||||
return return_size;
|
||||
}
|
||||
|
||||
- (void) getReturnValue: (void *)addr
|
||||
{
|
||||
if (return_value)
|
||||
memcpy (addr, return_value, return_size);
|
||||
/* xxx what if it hasn't been invoked yet, and there isn't
|
||||
a return value yet. */
|
||||
}
|
||||
|
||||
- (void) setReturnValue: (void*)addr
|
||||
{
|
||||
if (return_value)
|
||||
{
|
||||
if (return_retained && *return_type == _C_ID)
|
||||
{
|
||||
[*(id*)return_value release];
|
||||
*(id*)return_value = *(id*)addr;
|
||||
[*(id*)return_value retain];
|
||||
}
|
||||
else
|
||||
memcpy (return_value, addr, return_size);
|
||||
}
|
||||
}
|
||||
|
||||
- objectReturnValue
|
||||
{
|
||||
switch (*return_type)
|
||||
{
|
||||
#define CASE_RETURN(C,T,S) \
|
||||
case C: return [NSNumber numberWith ## S: *(T*)return_value]
|
||||
CASE_RETURN (_C_LNG, long, Long);
|
||||
CASE_RETURN (_C_ULNG, unsigned long, UnsignedLong);
|
||||
CASE_RETURN (_C_INT, int, Int);
|
||||
CASE_RETURN (_C_UINT, unsigned int, UnsignedInt);
|
||||
CASE_RETURN (_C_SHT, short, Short);
|
||||
CASE_RETURN (_C_USHT, unsigned short, UnsignedShort);
|
||||
CASE_RETURN (_C_CHR, char, Char);
|
||||
CASE_RETURN (_C_UCHR, unsigned char, UnsignedChar);
|
||||
CASE_RETURN (_C_FLT, float, Float);
|
||||
CASE_RETURN (_C_DBL, double, Double);
|
||||
#undef CASE_RETURN
|
||||
case _C_PTR:
|
||||
return [NSNumber numberWithUnsignedLong: (long) *(void**)return_value];
|
||||
case _C_CHARPTR:
|
||||
return [NSString stringWithCString: *(char**)return_value];
|
||||
case _C_ID:
|
||||
return *(id*)return_value;
|
||||
case 'v':
|
||||
return nil;
|
||||
default:
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
return 0;
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (int) intReturnValue
|
||||
{
|
||||
switch (*return_type)
|
||||
{
|
||||
#define CASE_RETURN(_C,_T) case _C: return (int) *(_T*)return_value
|
||||
CASE_RETURN (_C_LNG, long);
|
||||
CASE_RETURN (_C_ULNG, unsigned long);
|
||||
CASE_RETURN (_C_INT, int);
|
||||
CASE_RETURN (_C_UINT, unsigned int);
|
||||
CASE_RETURN (_C_SHT, short);
|
||||
CASE_RETURN (_C_USHT, unsigned short);
|
||||
CASE_RETURN (_C_CHR, char);
|
||||
CASE_RETURN (_C_UCHR, unsigned char);
|
||||
CASE_RETURN (_C_CHARPTR, char*);
|
||||
CASE_RETURN (_C_FLT, float);
|
||||
CASE_RETURN (_C_DBL, double);
|
||||
CASE_RETURN (_C_PTR, void*);
|
||||
#undef CASE_RETURN
|
||||
case _C_ID:
|
||||
return [*(id*)return_value intValue];
|
||||
case 'v':
|
||||
return 0;
|
||||
default:
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL) returnValueIsTrue
|
||||
{
|
||||
switch (return_size)
|
||||
{
|
||||
case sizeof(char):
|
||||
return (*(char*)return_value != 0);
|
||||
case sizeof(short):
|
||||
return (*(short*)return_value != 0);
|
||||
case sizeof(int):
|
||||
return (*(int*)return_value != 0);
|
||||
}
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < return_size; i++)
|
||||
if (*((char*)return_value + i) != 0)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (return_retained && *return_type == _C_ID)
|
||||
[*(id*)return_value release];
|
||||
OBJC_FREE(return_type);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static int
|
||||
types_get_size_of_stack_arguments(const char *types)
|
||||
{
|
||||
const char* type = objc_skip_typespec (types);
|
||||
return atoi(type);
|
||||
}
|
||||
|
||||
static int
|
||||
types_get_size_of_register_arguments(const char *types)
|
||||
{
|
||||
const char* type = strrchr(types, '+');
|
||||
if (type)
|
||||
return atoi(++type) + sizeof(void*);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To fix temporary bug in method_get_next_argument() on m68k */
|
||||
static char*
|
||||
my_method_get_next_argument (arglist_t argframe,
|
||||
const char **type)
|
||||
{
|
||||
const char *t = objc_skip_argspec (*type);
|
||||
|
||||
if (*t == '\0')
|
||||
return 0;
|
||||
|
||||
*type = t;
|
||||
t = objc_skip_typespec (t);
|
||||
|
||||
if (*t == '+')
|
||||
return argframe->arg_regs + atoi(++t);
|
||||
else
|
||||
/* xxx What's going on here? This -8 needed on my 68k NeXT box. */
|
||||
#if m68k
|
||||
return argframe->arg_ptr + (atoi(t) - 8);
|
||||
#else
|
||||
return argframe->arg_ptr + atoi(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
@implementation ArgframeInvocation
|
||||
|
||||
- (void) _retainArguments
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument (argframe, &tmptype)))
|
||||
{
|
||||
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||
if (*tmptype == _C_ID)
|
||||
[*(id*)datum retain];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _initArgframeFrom: (arglist_t)frame
|
||||
withType: (const char*)type
|
||||
retainArgs: (BOOL)f
|
||||
{
|
||||
int stack_argsize, reg_argsize;
|
||||
|
||||
/* allocate the argframe */
|
||||
stack_argsize = types_get_size_of_stack_arguments (type);
|
||||
reg_argsize = types_get_size_of_register_arguments(type);
|
||||
argframe = (arglist_t) objc_calloc (1 ,sizeof(char*) + reg_argsize);
|
||||
if (stack_argsize)
|
||||
argframe->arg_ptr = objc_calloc (1, stack_argsize);
|
||||
else
|
||||
argframe->arg_ptr = 0;
|
||||
|
||||
/* copy the frame into the argframe */
|
||||
if (frame)
|
||||
{
|
||||
memcpy((char*)argframe + sizeof(char*),
|
||||
(char*)frame + sizeof(char*),
|
||||
reg_argsize);
|
||||
memcpy(argframe->arg_ptr, frame->arg_ptr, stack_argsize);
|
||||
if (f)
|
||||
{
|
||||
[self _retainArguments];
|
||||
args_retained = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- initWithArgframe: (arglist_t)frame type: (const char *)type
|
||||
{
|
||||
/* xxx we are just using the return part. Does this matter? */
|
||||
[super initWithReturnType: type];
|
||||
[self _initArgframeFrom: frame withType: type retainArgs: NO];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
[super encodeWithCoder: coder];
|
||||
tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument(argframe, &tmptype)))
|
||||
{
|
||||
[coder encodeValueOfObjCType: tmptype
|
||||
at: datum
|
||||
withName: @"Invocation Argframe argument"];
|
||||
}
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
self = [super initWithCoder: coder];
|
||||
[self _initArgframeFrom: NULL withType: return_type retainArgs: NO];
|
||||
tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument(argframe, &tmptype)))
|
||||
{
|
||||
[coder decodeValueOfObjCType: tmptype
|
||||
at: datum
|
||||
withName: NULL];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithType: (const char *)e
|
||||
{
|
||||
[self initWithArgframe:NULL type:e];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) retainArguments
|
||||
{
|
||||
if (!args_retained)
|
||||
{
|
||||
if (argframe)
|
||||
[self _retainArguments];
|
||||
args_retained = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) argumentsRetained
|
||||
{
|
||||
return args_retained;
|
||||
}
|
||||
|
||||
- (const char *) argumentTypeAtIndex: (unsigned)i
|
||||
{
|
||||
const char *tmptype = return_type;
|
||||
|
||||
do
|
||||
{
|
||||
tmptype = objc_skip_argspec (tmptype);
|
||||
}
|
||||
while (i--);
|
||||
return tmptype;
|
||||
}
|
||||
|
||||
- (unsigned) argumentSizeAtIndex: (unsigned)i
|
||||
{
|
||||
return objc_sizeof_type ([self argumentTypeAtIndex:i]);
|
||||
}
|
||||
|
||||
- (void) getArgument: (void*)addr atIndex: (unsigned)i
|
||||
{
|
||||
const char *tmptype = return_type;
|
||||
void *datum;
|
||||
|
||||
do
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
while (i-- && datum);
|
||||
/* xxx Give error msg for null datum */
|
||||
memcpy (addr, datum, objc_sizeof_type(tmptype));
|
||||
}
|
||||
|
||||
- (void) setArgument:(const void *)addr atIndex: (unsigned)i
|
||||
{
|
||||
const char *tmptype = return_type;
|
||||
void *datum;
|
||||
|
||||
do
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
while (i--);
|
||||
memcpy (datum, addr, objc_sizeof_type(tmptype));
|
||||
}
|
||||
|
||||
- (void) setArgumentAtIndex: (unsigned)i
|
||||
toValueAt: (const void*)addr
|
||||
{
|
||||
[self setArgument: addr atIndex: i];
|
||||
}
|
||||
|
||||
- (void) _deallocArgframe
|
||||
{
|
||||
if (argframe)
|
||||
{
|
||||
if (argframe->arg_ptr)
|
||||
objc_free (argframe->arg_ptr);
|
||||
objc_free (argframe);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
void *datum;
|
||||
const char *tmptype = return_type;
|
||||
while ((datum = my_method_get_next_argument(argframe, &tmptype)))
|
||||
{
|
||||
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||
if (args_retained && *tmptype == _C_ID)
|
||||
[*(id*)datum release];
|
||||
}
|
||||
[self _deallocArgframe];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#if 0
|
||||
- resetArgframeWithReturnType: (const char*)encoding
|
||||
{
|
||||
[self _deallocArgframe];
|
||||
[self _allocArgframe];
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@implementation MethodInvocation
|
||||
|
||||
- (void) _initTargetAndSelPointers
|
||||
{
|
||||
const char *tmptype = return_type;
|
||||
target_pointer = (id*) my_method_get_next_argument (argframe, &tmptype);
|
||||
sel_pointer = (SEL*) my_method_get_next_argument (argframe, &tmptype);
|
||||
}
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithArgframe: (arglist_t)frame type: (const char*)t
|
||||
{
|
||||
[super initWithArgframe: frame type: t];
|
||||
[self _initTargetAndSelPointers];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithArgframe: (arglist_t)frame selector: (SEL)sel
|
||||
{
|
||||
const char *sel_type;
|
||||
|
||||
if (! (sel_type = sel_get_type (sel)) )
|
||||
sel_type = sel_get_type ( sel_get_any_typed_uid (sel_get_name (sel)));
|
||||
/* xxx Try harder to get this type by looking up the method in the target.
|
||||
Hopefully the target can be found in the FRAME. */
|
||||
if (!sel_type)
|
||||
[NSException raise: @"SelectorWithoutType"
|
||||
format: @"Couldn't find encoding type for selector %s.",
|
||||
sel_get_name (sel)];
|
||||
[self initWithArgframe: frame type: sel_type];
|
||||
if (!frame)
|
||||
*sel_pointer = sel;
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
[self _initTargetAndSelPointers];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithSelector: (SEL)s
|
||||
{
|
||||
[self initWithArgframe: NULL selector: s];
|
||||
*sel_pointer = s;
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithTarget: target selector: (SEL)s, ...
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
va_list ap;
|
||||
|
||||
[self initWithArgframe: NULL selector: s];
|
||||
tmptype = return_type;
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
if (args_retained)
|
||||
[target retain];
|
||||
*((id*)datum) = target;
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
*((SEL*)datum) = s;
|
||||
datum = my_method_get_next_argument(argframe, &tmptype);
|
||||
va_start (ap, s);
|
||||
while (datum)
|
||||
{
|
||||
#define CASE_TYPE(_C,_T) case _C: *(_T*)datum = va_arg (ap, _T); break
|
||||
switch (*tmptype)
|
||||
{
|
||||
case _C_ID:
|
||||
*(id*)datum = va_arg (ap, id);
|
||||
if (args_retained)
|
||||
[*(id*)datum retain];
|
||||
break;
|
||||
CASE_TYPE(_C_CLASS, Class);
|
||||
CASE_TYPE(_C_SEL, SEL);
|
||||
CASE_TYPE(_C_LNG, long);
|
||||
CASE_TYPE(_C_ULNG, unsigned long);
|
||||
CASE_TYPE(_C_INT, int);
|
||||
CASE_TYPE(_C_UINT, unsigned int);
|
||||
case _C_SHT:
|
||||
*(short*)datum = (short)va_arg(ap, int);
|
||||
break;
|
||||
case _C_USHT:
|
||||
*(unsigned short*)datum = (unsigned short)va_arg(ap, int);
|
||||
break;
|
||||
CASE_TYPE(_C_CHR, int);
|
||||
case _C_UCHR:
|
||||
*(unsigned char*)datum = (unsigned char)va_arg(ap, int);
|
||||
break;
|
||||
case _C_FLT:
|
||||
*(float*)datum = (float)va_arg(ap, int);
|
||||
break;
|
||||
CASE_TYPE(_C_DBL, double);
|
||||
CASE_TYPE(_C_CHARPTR, char*);
|
||||
CASE_TYPE(_C_PTR, void*);
|
||||
default:
|
||||
{
|
||||
int copysize;
|
||||
copysize = objc_sizeof_type(tmptype);
|
||||
memcpy(datum, (char *)va_arg(ap, int), copysize);
|
||||
} /* default */
|
||||
}
|
||||
datum = my_method_get_next_argument (argframe, &tmptype);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
void *ret;
|
||||
IMP imp;
|
||||
id target;
|
||||
id cl;
|
||||
SEL sel;
|
||||
|
||||
/* xxx This could be more efficient by using my_method_get_next_argument
|
||||
instead of -target and -selector. Or, even better, caching the
|
||||
memory offsets of the target and selector in the argframe. */
|
||||
|
||||
target = *target_pointer;
|
||||
if (target == nil)
|
||||
return;
|
||||
|
||||
cl = object_get_class (target);
|
||||
sel = *sel_pointer;
|
||||
/* xxx Perhaps we could speed things up by making this an ivar,
|
||||
and caching it. */
|
||||
imp = get_imp (cl, sel);
|
||||
NSAssert(imp, NSInternalInconsistencyException);
|
||||
ret = __builtin_apply((void(*)(void))imp,
|
||||
argframe,
|
||||
types_get_size_of_stack_arguments(return_type));
|
||||
if (return_size)
|
||||
{
|
||||
if (*return_type == _C_ID)
|
||||
{
|
||||
id old = *(id*)return_value;
|
||||
|
||||
mframe_decode_return(return_type, return_value, ret);
|
||||
|
||||
if (return_retained && (*(id*)return_value != old))
|
||||
{
|
||||
[old release];
|
||||
[*(id*)return_value retain];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mframe_decode_return(return_type, return_value, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) invokeWithTarget: t
|
||||
{
|
||||
[self setTarget: t];
|
||||
[self invoke];
|
||||
}
|
||||
|
||||
- (void) invokeWithObject: anObj
|
||||
{
|
||||
[self invokeWithTarget: anObj];
|
||||
}
|
||||
|
||||
- (SEL) selector
|
||||
{
|
||||
return *sel_pointer;
|
||||
}
|
||||
|
||||
- (void) setSelector: (SEL)s
|
||||
{
|
||||
SEL mysel = [self selector];
|
||||
if (mysel == (SEL)0)
|
||||
/* XXX Type check is needed! (masata-y@is.aist-nara.ac.jp) */
|
||||
*sel_pointer = sel_get_any_typed_uid (sel_get_name (s));
|
||||
else if (sel_types_match(sel_get_type(mysel), sel_get_type(s)))
|
||||
*sel_pointer = s;
|
||||
else
|
||||
{
|
||||
/* We need to reallocate the argframe */
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
}
|
||||
|
||||
- target
|
||||
{
|
||||
return *target_pointer;
|
||||
}
|
||||
|
||||
- (void) setTarget: t
|
||||
{
|
||||
if (*target_pointer != t)
|
||||
{
|
||||
if (args_retained)
|
||||
{
|
||||
[*target_pointer release];
|
||||
[t retain];
|
||||
}
|
||||
*target_pointer = t;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ObjectMethodInvocation
|
||||
|
||||
- (void) _initArgObjectPointer
|
||||
{
|
||||
const char *tmptype;
|
||||
void *datum;
|
||||
|
||||
tmptype = return_type;
|
||||
my_method_get_next_argument (argframe, &tmptype);
|
||||
my_method_get_next_argument (argframe, &tmptype);
|
||||
do
|
||||
{
|
||||
datum = my_method_get_next_argument (argframe, &tmptype);
|
||||
tmptype = objc_skip_type_qualifiers (tmptype);
|
||||
}
|
||||
while (datum && tmptype && *tmptype != _C_ID);
|
||||
if (*tmptype != _C_ID)
|
||||
[self error: "This method does not have an object argument."];
|
||||
arg_object_pointer = (id*) datum;
|
||||
}
|
||||
|
||||
- initWithArgframe: (arglist_t)frame selector: (SEL)sel
|
||||
{
|
||||
[super initWithArgframe: frame selector: sel];
|
||||
[self _initArgObjectPointer];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
[self _initArgObjectPointer];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) invokeWithObject: anObject
|
||||
{
|
||||
if (*arg_object_pointer != anObject)
|
||||
{
|
||||
if (args_retained)
|
||||
{
|
||||
[*arg_object_pointer release];
|
||||
[anObject retain];
|
||||
}
|
||||
*arg_object_pointer = anObject;
|
||||
}
|
||||
[self invoke];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation VoidFunctionInvocation
|
||||
|
||||
#if 0
|
||||
- initWithFunction: (void(*)())f
|
||||
argframe: (arglist_t)frame type: (const char *)e
|
||||
{
|
||||
[super initWithArgframe: frame type: e];
|
||||
function = f;
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
- initWithVoidFunction: (void(*)())f
|
||||
{
|
||||
[super initWithReturnType: "v"];
|
||||
function = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Encode ourself as a proxies across Connection's; we can't encode
|
||||
a function across the wire. */
|
||||
- classForPortCoder
|
||||
{
|
||||
return [NSDistantObject class];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
}
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
(*function) ();
|
||||
}
|
||||
|
||||
- (void) invokeWithObject
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ObjectFunctionInvocation
|
||||
|
||||
- initWithObjectFunction: (id(*)(id))f
|
||||
{
|
||||
[super initWithReturnType: "@"];
|
||||
function = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Encode ourself as a proxies across Connection's; we can't encode
|
||||
a function across the wire. */
|
||||
- classForPortCoder
|
||||
{
|
||||
return [NSDistantObject class];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)coder
|
||||
{
|
||||
[self shouldNotImplement: _cmd];
|
||||
}
|
||||
|
||||
- (void) invoke
|
||||
{
|
||||
[self invokeWithObject: nil];
|
||||
}
|
||||
|
||||
- (void) invokeWithObject: anObject
|
||||
{
|
||||
id r;
|
||||
|
||||
r = (*function) (anObject);
|
||||
if (*(id*)return_value != r)
|
||||
{
|
||||
if (return_retained)
|
||||
{
|
||||
[*(id*)return_value release];
|
||||
[r retain];
|
||||
}
|
||||
*(id*)return_value = r;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* Many other kinds of Invocations are possible:
|
||||
SchemeInvocation, TclInvocation */
|
||||
|
||||
#if 0
|
||||
@implementation CurriedInvocation
|
||||
@end
|
||||
|
||||
What is this nonsense?
|
||||
@interface StreamInvocation
|
||||
@interface LogInvocation
|
||||
@interface PrintingInvocation
|
||||
{
|
||||
Stream *stream;
|
||||
char *format_string;
|
||||
}
|
||||
@end
|
||||
#endif
|
|
@ -1,280 +0,0 @@
|
|||
/* Implementation for Objective-C KeyedCollection collection object
|
||||
Copyright (C) 1993,1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/KeyedCollection.h>
|
||||
#include <base/CollectionPrivate.h>
|
||||
#include <stdio.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/behavior.h>
|
||||
|
||||
@implementation KeyEnumerator
|
||||
|
||||
- nextObject
|
||||
{
|
||||
id k;
|
||||
[collection nextObjectAndKey: &k withEnumState: &enum_state];
|
||||
return k;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ConstantKeyedCollection
|
||||
|
||||
|
||||
// INITIALIZING;
|
||||
|
||||
/* This is the designated initializer */
|
||||
- initWithObjects: (id*)objects forKeys: (id*)keys count: (unsigned)c
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
// GETTING ELEMENTS AND KEYS;
|
||||
|
||||
- objectAtKey: aKey
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- keyOfObject: aContentObject
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (BOOL) containsKey: aKey
|
||||
{
|
||||
if ([self objectAtKey: aKey] == NO_OBJECT)
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
// ENUMERATIONS;
|
||||
|
||||
- (id <Enumerating>) keyEnumerator
|
||||
{
|
||||
return [[[KeyEnumerator alloc] initWithCollection: self]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- (void) withKeysInvoke: (id <Invoking>)anInvocation
|
||||
{
|
||||
id o, k;
|
||||
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
[anInvocation invokeWithObject: k];
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
}
|
||||
|
||||
- (void) 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];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- copyKeysAs: (Class)aCollectingClass;
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
// ARCHIVING
|
||||
|
||||
- (void) _encodeContentsWithCoder: (id <Encoding>)aCoder
|
||||
{
|
||||
unsigned int count = [self count];
|
||||
id o, k;
|
||||
|
||||
[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;
|
||||
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 decodeObjectAt: &(keys[i])
|
||||
withName: NULL];
|
||||
[aCoder decodeObjectAt: &(objs[i])
|
||||
withName: NULL];
|
||||
}
|
||||
[self initWithObjects: objs forKeys: keys count: count];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
[keys[i] release];
|
||||
[objs[i] release];
|
||||
}
|
||||
OBJC_FREE(objs);
|
||||
OBJC_FREE(keys);
|
||||
}
|
||||
|
||||
- (NSString*) description
|
||||
{
|
||||
id s = [NSMutableString new];
|
||||
id o, k;
|
||||
|
||||
FOR_KEYED_COLLECTION(self, o, k)
|
||||
{
|
||||
[s appendFormat: @"(%@,%@) ", [k description], [o description]];
|
||||
}
|
||||
END_FOR_KEYED_COLLECTION(self);
|
||||
[s appendFormat: @" :%s\n", object_get_class_name (self)];
|
||||
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,408 +0,0 @@
|
|||
/* Implementation for Objective-C LinkedList collection object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/LinkedList.h>
|
||||
#include <base/IndexedCollectionPrivate.h>
|
||||
#include <base/Coder.h>
|
||||
|
||||
@implementation LinkedList
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- init
|
||||
{
|
||||
_count = 0;
|
||||
_first_link = nil;
|
||||
_last_link = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithObjects: (id*)objs count: (unsigned)c
|
||||
{
|
||||
[self init];
|
||||
while (c--)
|
||||
[self prependObject: objs[c]];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: coder
|
||||
{
|
||||
id l;
|
||||
|
||||
[super encodeWithCoder: coder];
|
||||
[coder encodeValueOfCType: @encode (typeof (_count))
|
||||
at: &_count
|
||||
withName: @"LinkedList count"];
|
||||
FOR_COLLECTION (self, l)
|
||||
{
|
||||
[coder encodeObject: l
|
||||
withName: @"LinkedList element"];
|
||||
}
|
||||
END_FOR_COLLECTION (self);
|
||||
[coder encodeObjectReference: _first_link
|
||||
withName: @"LinkedList first link"];
|
||||
[coder encodeObjectReference: _last_link
|
||||
withName: @"LinkedList last link"];
|
||||
}
|
||||
|
||||
- initWithCoder: coder
|
||||
{
|
||||
int i;
|
||||
// id link;
|
||||
|
||||
self = [super initWithCoder: coder];
|
||||
[coder decodeValueOfCType: @encode (typeof (_count))
|
||||
at: &_count
|
||||
withName: NULL];
|
||||
/* We don't really care about storing the elements decoded, because
|
||||
we access them through their own link pointers. */
|
||||
for (i = 0; i < _count; i++)
|
||||
[coder decodeObjectAt: NULL
|
||||
withName: NULL];
|
||||
[coder decodeObjectAt: &_first_link
|
||||
withName: NULL];
|
||||
[coder decodeObjectAt: &_last_link
|
||||
withName: NULL];
|
||||
#if 0
|
||||
/* xxx Not necessary, since the links encode this?
|
||||
But should we rely on the links encoding this?
|
||||
BUT! Look out: the next link pointers may not be set until
|
||||
the last finishDecoding... method is run... */
|
||||
FOR_COLLECTION (self, link)
|
||||
{
|
||||
[link setLinkedList: self];
|
||||
}
|
||||
END_FOR_COLLECTION (self);
|
||||
#endif
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
LinkedList *copy = [super emptyCopy];
|
||||
copy->_first_link = nil;
|
||||
copy->_last_link = nil;
|
||||
copy->_count = 0;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) _empty
|
||||
{
|
||||
_count = 0;
|
||||
_first_link = nil;
|
||||
_last_link = nil;
|
||||
}
|
||||
|
||||
/* These next four methods are the only ones that change the values of
|
||||
the instance variables _count, _first_link, except for
|
||||
"-init". */
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
NSAssert([oldObject linkedList] == self, NSInternalInconsistencyException);
|
||||
if (_first_link == oldObject)
|
||||
{
|
||||
if (_count > 1)
|
||||
_first_link = [oldObject nextLink];
|
||||
else
|
||||
_first_link = nil;
|
||||
}
|
||||
else
|
||||
[[oldObject prevLink] setNextLink:[oldObject nextLink]];
|
||||
if (_last_link == oldObject)
|
||||
{
|
||||
if (_count > 1)
|
||||
_last_link = [oldObject prevLink];
|
||||
else
|
||||
_first_link = nil;
|
||||
}
|
||||
else
|
||||
[[oldObject nextLink] setPrevLink:[oldObject prevLink]];
|
||||
_count--;
|
||||
[oldObject setNextLink: NO_OBJECT];
|
||||
[oldObject setPrevLink: NO_OBJECT];
|
||||
[oldObject setLinkedList: NO_OBJECT];
|
||||
[oldObject release];
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject after: oldObject
|
||||
{
|
||||
/* Make sure we actually own the oldObject. */
|
||||
NSAssert([oldObject linkedList] == self, NSInternalInconsistencyException);
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setLinkedList: self];
|
||||
|
||||
/* Insert it. */
|
||||
if (_count == 0)
|
||||
{
|
||||
_first_link = newObject;
|
||||
_last_link = newObject;
|
||||
_count = 1;
|
||||
[newObject setNextLink: NO_OBJECT];
|
||||
[newObject setPrevLink: NO_OBJECT];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldObject == _last_link)
|
||||
_last_link = newObject;
|
||||
[newObject setNextLink: [oldObject nextLink]];
|
||||
[newObject setPrevLink: oldObject];
|
||||
[[oldObject nextLink] setPrevLink: newObject];
|
||||
[oldObject setNextLink: newObject];
|
||||
}
|
||||
_count++;
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject before: oldObject
|
||||
{
|
||||
/* Make sure we actually own the oldObject. */
|
||||
NSAssert([oldObject linkedList] == self, NSInternalInconsistencyException);
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setLinkedList: self];
|
||||
|
||||
/* Insert it. */
|
||||
if (_count == 0)
|
||||
{
|
||||
_first_link = newObject;
|
||||
_last_link = newObject;
|
||||
_count = 1;
|
||||
[newObject setNextLink: NO_OBJECT];
|
||||
[newObject setPrevLink: NO_OBJECT];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (oldObject == _first_link)
|
||||
_first_link = newObject;
|
||||
[newObject setPrevLink: [oldObject prevLink]];
|
||||
[newObject setNextLink: oldObject];
|
||||
[[oldObject prevLink] setNextLink: newObject];
|
||||
[oldObject setPrevLink: newObject];
|
||||
}
|
||||
_count++;
|
||||
}
|
||||
|
||||
- (void) replaceObject: oldObject with: newObject
|
||||
{
|
||||
/* Make sure we actually own the oldObject. */
|
||||
NSAssert([oldObject linkedList] == self, NSInternalInconsistencyException);
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setLinkedList: self];
|
||||
|
||||
/* Do the replacement. */
|
||||
if (oldObject == _first_link)
|
||||
_first_link = newObject;
|
||||
[newObject setNextLink:[oldObject nextLink]];
|
||||
[newObject setPrevLink:[oldObject prevLink]];
|
||||
[[oldObject prevLink] setNextLink:newObject];
|
||||
[[oldObject nextLink] setPrevLink:newObject];
|
||||
|
||||
/* Release ownership of the oldObject. */
|
||||
[oldObject setNextLink: NO_OBJECT];
|
||||
[oldObject setPrevLink: NO_OBJECT];
|
||||
[oldObject setLinkedList: NO_OBJECT];
|
||||
[oldObject release];
|
||||
}
|
||||
|
||||
/* End of methods that change the instance variables. */
|
||||
|
||||
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Insert it. */
|
||||
if (_count == 0)
|
||||
{
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setLinkedList: self];
|
||||
|
||||
/* Put it in as the only node. */
|
||||
_first_link = newObject;
|
||||
_last_link = newObject;
|
||||
_count = 1;
|
||||
[newObject setNextLink: NO_OBJECT];
|
||||
[newObject setPrevLink: NO_OBJECT];
|
||||
}
|
||||
else
|
||||
[self insertObject: newObject after: _last_link];
|
||||
}
|
||||
|
||||
- (void) prependObject: newObject
|
||||
{
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Insert it. */
|
||||
if (_count == 0)
|
||||
{
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setLinkedList: self];
|
||||
|
||||
/* Put it in as the only node. */
|
||||
_first_link = newObject;
|
||||
_last_link = newObject;
|
||||
_count = 1;
|
||||
[newObject setNextLink: NO_OBJECT];
|
||||
[newObject setPrevLink: NO_OBJECT];
|
||||
}
|
||||
else
|
||||
[self insertObject: newObject before: _first_link];
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, (_count+1));
|
||||
|
||||
/* Make sure no one else already owns the newObject. */
|
||||
NSAssert([newObject linkedList] == NO_OBJECT, NSInternalInconsistencyException);
|
||||
|
||||
/* Insert it. */
|
||||
if (_count == 0)
|
||||
{
|
||||
/* Claim ownership of the newObject. */
|
||||
[newObject retain];
|
||||
[newObject setLinkedList: self];
|
||||
|
||||
/* Put it in as the only node. */
|
||||
_first_link = newObject;
|
||||
_last_link = newObject;
|
||||
_count = 1;
|
||||
[newObject setNextLink: NO_OBJECT];
|
||||
[newObject setPrevLink: NO_OBJECT];
|
||||
}
|
||||
else if (index == _count)
|
||||
[self insertObject: newObject after: _last_link];
|
||||
else
|
||||
[self insertObject:newObject before: [self objectAtIndex: index]];
|
||||
}
|
||||
|
||||
- (void) removeObjectAtIndex: (unsigned)index
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
[self removeObject: [self objectAtIndex: index]];
|
||||
}
|
||||
|
||||
- objectAtIndex: (unsigned)index
|
||||
{
|
||||
id <LinkedListComprising> link;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(index, _count);
|
||||
|
||||
if (index < _count / 2)
|
||||
for (link = _first_link;
|
||||
index;
|
||||
link = [link nextLink], index--)
|
||||
;
|
||||
else
|
||||
for (link = _last_link, index = _count - index - 1;
|
||||
index;
|
||||
link = [link prevLink], index--)
|
||||
;
|
||||
return link;
|
||||
}
|
||||
|
||||
- firstObject
|
||||
{
|
||||
return _first_link;
|
||||
}
|
||||
|
||||
- lastObject
|
||||
{
|
||||
return _last_link;
|
||||
}
|
||||
|
||||
- successorOfObject: oldObject
|
||||
{
|
||||
/* Make sure we actually own the oldObject. */
|
||||
NSAssert([oldObject linkedList] == self, NSInternalInconsistencyException);
|
||||
|
||||
return [oldObject nextLink];
|
||||
}
|
||||
|
||||
- predecessorOfObject: oldObject
|
||||
{
|
||||
/* Make sure we actually own the oldObject. */
|
||||
NSAssert([oldObject linkedList] == self, NSInternalInconsistencyException);
|
||||
|
||||
return [oldObject prevLink];
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
return _first_link;
|
||||
}
|
||||
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
id ret;
|
||||
|
||||
if (!*enumState)
|
||||
return nil;
|
||||
ret = *enumState;
|
||||
*enumState = [(id)(*enumState) nextLink];
|
||||
/* *enumState points to the next object to be returned. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
- prevObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
/* *enumState points to the object returned last time. */
|
||||
if (!*enumState)
|
||||
return nil;
|
||||
if (*enumState == _first_link)
|
||||
/* enumState was just initialized from -newEnumState. */
|
||||
return *enumState = _last_link;
|
||||
return (id) *enumState = [(id)(*enumState) prevLink];
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/* Implementation for Objective-C LinkedListNode object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/LinkedListNode.h>
|
||||
#include <base/Coder.h>
|
||||
|
||||
@implementation LinkedListNode
|
||||
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_next = _prev = _linked_list = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
[aCoder encodeObjectReference:_next withName:@"Next LinkedList Node"];
|
||||
[aCoder encodeObjectReference:_prev withName:@"Prev LinkedList Node"];
|
||||
[aCoder encodeObjectReference:_linked_list withName:@"LinkedList"];
|
||||
}
|
||||
|
||||
- initWithCoder: aCoder
|
||||
{
|
||||
[super initWithCoder:aCoder];
|
||||
[aCoder decodeObjectAt:&_next withName:NULL];
|
||||
[aCoder decodeObjectAt:&_prev withName:NULL];
|
||||
[aCoder decodeObjectAt:&_linked_list withName:NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id <LinkedListComprising>) nextLink
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
- (id <LinkedListComprising>) prevLink
|
||||
{
|
||||
return _prev;
|
||||
}
|
||||
|
||||
- (void) setNextLink: (id <LinkedListComprising>)aLink
|
||||
{
|
||||
_next = aLink;
|
||||
}
|
||||
|
||||
- (void) setPrevLink: (id <LinkedListComprising>)aLink
|
||||
{
|
||||
_prev = aLink;
|
||||
}
|
||||
|
||||
- linkedList
|
||||
{
|
||||
return _linked_list;
|
||||
}
|
||||
|
||||
- (void) setLinkedList: anObject;
|
||||
{
|
||||
_linked_list = anObject;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,99 +0,0 @@
|
|||
/* Implementation for Objective-C Magnitude object
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Magnitude.h>
|
||||
|
||||
/* These methods accesses no instance variables. It is exactly the kind
|
||||
of thing that should be a "behavior" associated with a protocol.
|
||||
i.e. #3 on Steve Naroff's wish list. */
|
||||
|
||||
@implementation Magnitude
|
||||
|
||||
- (int) compare: anObject
|
||||
{
|
||||
return [super compare:anObject];
|
||||
}
|
||||
|
||||
- (BOOL) greaterThan: anObject
|
||||
{
|
||||
if ([self compare:anObject] > 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) greaterThanOrEqual: anObject
|
||||
{
|
||||
if ([self compare:anObject] >= 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) lessThan: anObject
|
||||
{
|
||||
if ([self compare:anObject] < 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) lessThanOrEqual: anObject
|
||||
{
|
||||
if ([self compare:anObject] <= 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) between: firstObject and: secondObject
|
||||
{
|
||||
if ([self compare:firstObject] >= 0
|
||||
&& [self compare:secondObject] <= 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- maximum: anObject
|
||||
{
|
||||
if ([self compare:anObject] >= 0)
|
||||
return self;
|
||||
else
|
||||
return anObject;
|
||||
}
|
||||
|
||||
- minimum: anObject
|
||||
{
|
||||
if ([self compare:anObject] <= 0)
|
||||
return self;
|
||||
else
|
||||
return anObject;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,138 +0,0 @@
|
|||
/* Implementation for Objective-C MappedCollector collection object
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/MappedCollector.h>
|
||||
#include <base/Dictionary.h>
|
||||
#include <base/CollectionPrivate.h>
|
||||
|
||||
@implementation MappedCollector
|
||||
|
||||
/* This is the designated initializer for this class */
|
||||
- initWithCollection: (id <KeyedCollecting>)aDomain
|
||||
map: (id <KeyedCollecting>)aMap
|
||||
{
|
||||
_map = aMap;
|
||||
_domain = aDomain;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Archiving must mimic the above designated initializer */
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
+ newWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Override our superclass' designated initializer */
|
||||
- initWithObjects: (id*)objects forKeys: (id*)keys count: (unsigned)c
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
MappedCollector *copy = [super emptyCopy];
|
||||
copy->_map = [_map emptyCopy];
|
||||
copy->_domain = [_domain emptyCopy];
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) empty
|
||||
{
|
||||
[_domain empty];
|
||||
}
|
||||
|
||||
- objectAtKey: aKey
|
||||
{
|
||||
return [_domain objectAtKey: [_map objectAtKey: aKey]];
|
||||
}
|
||||
|
||||
- keyOfObject: aContentObject
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) replaceObjectAtKey: aKey with: newObject
|
||||
{
|
||||
return [_domain replaceObjectAtKey: [_map objectAtKey: aKey]
|
||||
with: newObject];
|
||||
}
|
||||
|
||||
- (void) putObject: newObject atKey: aKey
|
||||
{
|
||||
return [_domain putObject: newObject
|
||||
atKey: [_map objectAtKey:aKey]];
|
||||
}
|
||||
|
||||
- (void) removeObjectAtKey: aKey
|
||||
{
|
||||
return [_domain removeObjectAtKey: [_map objectAtKey: aKey]];
|
||||
}
|
||||
|
||||
- (BOOL) containsKey: aKey
|
||||
{
|
||||
return [_domain containsKey: [_map objectAtKey:aKey]];
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
return [_domain newEnumState];
|
||||
}
|
||||
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
return [_domain freeEnumState: enumState];
|
||||
}
|
||||
|
||||
- nextObjectAndKey: (id*)keyPtr withEnumState: (void**)enumState
|
||||
{
|
||||
id mapContent;
|
||||
id domainKey;
|
||||
|
||||
/* xxx This needs debugging; see checks/test02.m */
|
||||
while ((mapContent = [_map nextObjectAndKey:keyPtr withEnumState:enumState])
|
||||
&&
|
||||
(![_domain containsKey: (domainKey = [_map objectAtKey:*keyPtr])]))
|
||||
;
|
||||
if (mapContent == NO_OBJECT)
|
||||
return NO_OBJECT;
|
||||
return [_domain objectAtKey: domainKey];
|
||||
}
|
||||
|
||||
- species
|
||||
{
|
||||
return [Dictionary class];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,750 +0,0 @@
|
|||
/* Implementation of object for broadcasting Notification objects
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: March 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/* The implementation for NotificationDispatcher. */
|
||||
|
||||
/* NeXT says you can only have one NotificationCenter per task;
|
||||
I don't think GNU needs this restriction with its corresponding
|
||||
NotificationDistributor class. */
|
||||
|
||||
#include <config.h>
|
||||
#include <base/NotificationDispatcher.h>
|
||||
#include <base/LinkedListNode.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/Invocation.h>
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
|
||||
/* NotificationRequest class - One of these objects is created for
|
||||
each -addObserver... request. It holds the requested invocation,
|
||||
name and object. Each object is placed
|
||||
(1) in one LinkedList, as keyed by the NAME/OBJECT parameters (accessible
|
||||
through one of the ivars: anonymous_nr_list, object_2_nr_list,
|
||||
name_2_nr_list), and
|
||||
(2) in the Array, as keyed by the OBSERVER (as accessible through
|
||||
the ivar observer_2_nr_array.
|
||||
|
||||
To post a notification in satisfaction of this request,
|
||||
send -postNotification:. */
|
||||
|
||||
@interface NotificationRequest : LinkedListNode
|
||||
{
|
||||
int _retain_count;
|
||||
id _name;
|
||||
id _object;
|
||||
}
|
||||
- initWithName: n object: o;
|
||||
- (NSString*) notificationName;
|
||||
- notificationObject;
|
||||
- (void) postNotification: n;
|
||||
@end
|
||||
|
||||
@implementation NotificationRequest
|
||||
|
||||
- initWithName: n object: o
|
||||
{
|
||||
[super init];
|
||||
_retain_count = 0;
|
||||
_name = [n retain];
|
||||
_object = o;
|
||||
/* Note that OBJECT is not retained. See the comment for
|
||||
-addObserver... in NotificationDispatcher.h. */
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Implement these retain/release methods here for efficiency, since
|
||||
NotificationRequest's get retained and released by all their
|
||||
holders. Doing this is a judgement call; I'm choosing speed over
|
||||
space. */
|
||||
|
||||
- retain
|
||||
{
|
||||
_retain_count++;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (oneway void) release
|
||||
{
|
||||
if (_retain_count-- == 0)
|
||||
[self dealloc];
|
||||
}
|
||||
|
||||
- (unsigned) retainCount
|
||||
{
|
||||
return _retain_count + 1;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_name release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:other
|
||||
{
|
||||
if ([self class] != [other class])
|
||||
return NO;
|
||||
if (_object != [other notificationObject])
|
||||
return NO;
|
||||
if (_name != [other notificationName] &&
|
||||
![_name isEqual: [other notificationName]])
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString*) notificationName
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
- notificationObject
|
||||
{
|
||||
return _object;
|
||||
}
|
||||
|
||||
- (void) postNotification: n
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NotificationInvocation : NotificationRequest
|
||||
{
|
||||
id _invocation;
|
||||
}
|
||||
- initWithInvocation: i name: n object: o;
|
||||
@end
|
||||
|
||||
@implementation NotificationInvocation
|
||||
|
||||
- initWithInvocation: i name: n object: o
|
||||
{
|
||||
[super initWithName: n object: o];
|
||||
_invocation = [i retain];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_invocation release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) postNotification: n
|
||||
{
|
||||
[_invocation invokeWithObject: n];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NotificationPerformer : NotificationRequest
|
||||
{
|
||||
id _target;
|
||||
SEL _selector;
|
||||
}
|
||||
- initWithTarget: t selector: (SEL)s name: n object: o;
|
||||
@end
|
||||
|
||||
@implementation NotificationPerformer
|
||||
|
||||
- initWithTarget: t selector: (SEL)s name: n object: o
|
||||
{
|
||||
[super initWithName: n object: o];
|
||||
/* Note that TARGET is not retained. See the comment for
|
||||
-addObserver... in NotificationDispatcher.h. */
|
||||
_target = t;
|
||||
_selector = s;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) postNotification: n
|
||||
{
|
||||
[_target performSelector: _selector withObject: n];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
@implementation NotificationDispatcher
|
||||
|
||||
/* The default instance, most often the only one created.
|
||||
It is accessed by the class methods at the end of this file.
|
||||
There is no need to mutex locking of this variable. */
|
||||
static NotificationDispatcher *default_notification_dispatcher = nil;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NotificationDispatcher class])
|
||||
default_notification_dispatcher = [self new];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Initializing. */
|
||||
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_anonymous_nr_list = [LinkedList new];
|
||||
|
||||
/* Use NSNonOwnedPointerOrNullMapKeyCallBacks so we won't retain
|
||||
the object. We will, however, retain the values, which are
|
||||
LinkedList's. */
|
||||
_object_2_nr_list =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
|
||||
/* Use NSObjectMapKeyCallBacks so we retain the NAME. We also retain
|
||||
the values, which are LinkedList's. */
|
||||
_name_2_nr_list =
|
||||
NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
|
||||
/* Use NSNonOwnedPointerOrNullMapKeyCallBacks so we won't retain
|
||||
the observer. We will, however, retain the values, which are Array's. */
|
||||
_observer_2_nr_array =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
|
||||
_lock = [NSRecursiveLock new];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[_anonymous_nr_list release];
|
||||
NSFreeMapTable( _object_2_nr_list);
|
||||
NSFreeMapTable (_name_2_nr_list);
|
||||
NSFreeMapTable (_observer_2_nr_array);
|
||||
[_lock release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
/* Adding new observers. */
|
||||
|
||||
/* This is the (private) designated method for adding observers. If we
|
||||
came from -addInvocation... then OBSERVER is actually an Invocation. */
|
||||
|
||||
- (void) _addObserver: observer
|
||||
notificationRequest: nr
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
/* If observer is nil, there is nothing to do; return. */
|
||||
if (!observer)
|
||||
return;
|
||||
|
||||
[_lock lock];
|
||||
|
||||
/* Record the notification request in an array keyed by OBSERVER. */
|
||||
{
|
||||
/* Find the array of all the requests by OBSERVER. */
|
||||
Array *nr_array = NSMapGet (_observer_2_nr_array, observer);
|
||||
if (!nr_array)
|
||||
{
|
||||
nr_array = [Array new];
|
||||
/* nr_array is retained; observer is not. */
|
||||
NSMapInsert (_observer_2_nr_array, observer, nr_array);
|
||||
/* Now that nr_array is retained by the map table, release it;
|
||||
this way the array will be completely released when the
|
||||
map table is done with it. */
|
||||
[nr_array release];
|
||||
}
|
||||
/* If the observer is already watching this request, do nothing. */
|
||||
if ([nr_array containsObject:nr])
|
||||
{
|
||||
[_lock unlock];
|
||||
return;
|
||||
}
|
||||
[nr_array appendObject: nr];
|
||||
}
|
||||
|
||||
/* Record the NotificationRequest in one of three MapTable->LinkedLists. */
|
||||
|
||||
/* Record the request in one, and only one, LinkedList. The LinkedList
|
||||
is stored in a hash table accessed by a key. Which key is used
|
||||
depends on what combination of NAME and OBJECT are non-nil. */
|
||||
if (!name)
|
||||
{
|
||||
if (!object)
|
||||
{
|
||||
/* This NotificationRequest will get posted notifications
|
||||
for all NAME and OBJECT combinations. */
|
||||
[_anonymous_nr_list appendObject: nr];
|
||||
}
|
||||
else
|
||||
{
|
||||
LinkedList *nr_list = NSMapGet (_object_2_nr_list, object);
|
||||
if (!nr_list)
|
||||
{
|
||||
nr_list = [LinkedList new];
|
||||
/* nr_list is retained; object is not retained. */
|
||||
NSMapInsert (_object_2_nr_list, object, nr_list);
|
||||
/* Now that nr_list is retained by the map table, release it;
|
||||
this way the list will be completely released when the
|
||||
map table is done with it. */
|
||||
[nr_list release];
|
||||
}
|
||||
[nr_list appendObject: nr];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LinkedList *nr_list = NSMapGet (_name_2_nr_list, name);
|
||||
if (!nr_list)
|
||||
{
|
||||
nr_list = [LinkedList new];
|
||||
/* nr_list is retained; object is not retained. */
|
||||
NSMapInsert (_name_2_nr_list, name, nr_list);
|
||||
/* Now that nr_list is retained by the map table, release it;
|
||||
this way the list will be completely released when the
|
||||
map table is done with it. */
|
||||
[nr_list release];
|
||||
}
|
||||
[nr_list appendObject: nr];
|
||||
}
|
||||
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
- (void) addInvocation: (id <Invoking>)invocation
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
id nr;
|
||||
|
||||
/* Create the NotificationRequest object that will hold this
|
||||
observation request. This will retain INVOCATION and NAME. */
|
||||
nr = [[NotificationInvocation alloc]
|
||||
initWithInvocation: invocation
|
||||
name: name
|
||||
object: object];
|
||||
|
||||
/* Record it in all the right places. */
|
||||
[self _addObserver: invocation
|
||||
notificationRequest: nr
|
||||
name: name
|
||||
object: object];
|
||||
|
||||
/* Since nr was retained when it was added to the Array and
|
||||
LinkedList above, we can release it now. */
|
||||
[nr release];
|
||||
}
|
||||
|
||||
|
||||
/* For those that want to specify a selector instead of an invocation
|
||||
as a way to contact the observer. */
|
||||
|
||||
- (void) addObserver: observer
|
||||
selector: (SEL)sel
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
id nr;
|
||||
|
||||
/* Create the NotificationRequest object that will hold this
|
||||
observation request. This will retain INVOCATION and NAME. */
|
||||
nr = [[NotificationPerformer alloc]
|
||||
initWithTarget: observer
|
||||
selector: sel
|
||||
name: name
|
||||
object: object];
|
||||
|
||||
/* Record it in all the right places. */
|
||||
[self _addObserver: observer
|
||||
notificationRequest: nr
|
||||
name: name
|
||||
object: object];
|
||||
|
||||
/* Since nr was retained when it was added to the Array and
|
||||
LinkedList above, we can release it now. */
|
||||
[nr release];
|
||||
}
|
||||
|
||||
|
||||
/* Removing objects. */
|
||||
|
||||
/* A private method.
|
||||
Remove the NR object from its one LinkedList; if this is the last
|
||||
element of that LinkedList, and the LinkedList is map-accessible,
|
||||
also release the LinkedList. */
|
||||
|
||||
- (void) _removeFromLinkedListNotificationRequest: nr
|
||||
{
|
||||
id nr_list = [nr linkedList];
|
||||
|
||||
/* See if, instead of removing the NR from its LinkedList, we can
|
||||
actually release the entire list. */
|
||||
if ([nr_list count] == 1
|
||||
&& nr_list != _anonymous_nr_list)
|
||||
{
|
||||
id nr_name;
|
||||
id nr_object;
|
||||
LinkedList *mapped_nr_list;
|
||||
|
||||
NSAssert([nr_list firstObject] == nr, NSInternalInconsistencyException);
|
||||
if ((nr_name = [nr notificationName]))
|
||||
{
|
||||
mapped_nr_list = NSMapGet (_name_2_nr_list, nr_name);
|
||||
NSAssert(mapped_nr_list == nr_list, NSInternalInconsistencyException);
|
||||
NSMapRemove (_name_2_nr_list, nr_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
nr_object = [nr notificationObject];
|
||||
NSAssert(nr_object, NSInternalInconsistencyException);
|
||||
mapped_nr_list = NSMapGet (_object_2_nr_list, nr_object);
|
||||
NSAssert(mapped_nr_list == nr_list, NSInternalInconsistencyException);
|
||||
NSMapRemove (_object_2_nr_list, nr_object);
|
||||
}
|
||||
}
|
||||
else
|
||||
[nr_list removeObject: nr];
|
||||
}
|
||||
|
||||
|
||||
/* Removing notification requests. */
|
||||
|
||||
/* Remove all notification requests that would be sent to INVOCATION. */
|
||||
|
||||
- (void) removeInvocation: invocation
|
||||
{
|
||||
[self removeObserver: invocation];
|
||||
}
|
||||
|
||||
/* Remove the notification requests matching NAME and OBJECT that
|
||||
would be sent to INVOCATION. As with adding an observation
|
||||
request, nil NAME or OBJECT act as wildcards. */
|
||||
|
||||
- (void) removeInvocation: invocation
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[self removeObserver: invocation
|
||||
name: name
|
||||
object: object];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Remove all records pertaining to OBSERVER. For instance, this
|
||||
should be called before the OBSERVER is -dealloc'ed. */
|
||||
|
||||
- (void) removeObserver: observer
|
||||
{
|
||||
Array *observer_nr_array;
|
||||
NotificationRequest *nr;
|
||||
|
||||
/* If OBSERVER is nil, do nothing; just return. NOTE: This *does not*
|
||||
remove all requests with a nil OBSERVER; it would be too easy to
|
||||
unintentionally remove other's requests that way. If you need to
|
||||
remove a request with a nil OBSERVER, use -removeObserver:name:object: */
|
||||
if (!observer)
|
||||
return;
|
||||
|
||||
[_lock lock];
|
||||
|
||||
/* Get the array of NotificationRequest's associated with OBSERVER. */
|
||||
observer_nr_array = NSMapGet (_observer_2_nr_array, observer);
|
||||
|
||||
if (!observer_nr_array)
|
||||
/* OBSERVER was never registered for any notification requests with us.
|
||||
Nothing to do. */
|
||||
return;
|
||||
|
||||
/* Remove each of these from it's LinkedList. */
|
||||
FOR_ARRAY (observer_nr_array, nr)
|
||||
{
|
||||
[self _removeFromLinkedListNotificationRequest: nr];
|
||||
}
|
||||
END_FOR_ARRAY (observer_nr_array);
|
||||
|
||||
/* Remove from the MapTable the list of NotificationRequest's
|
||||
associated with OBSERVER. This also releases the observer_nr_array,
|
||||
and its contents. */
|
||||
NSMapRemove (_observer_2_nr_array, observer);
|
||||
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
|
||||
/* Remove the notification requests for the given parameters. As with
|
||||
adding an observation request, nil NAME or OBJECT act as wildcards. */
|
||||
|
||||
- (void) removeObserver: observer
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
Array *observer_nr_array;
|
||||
|
||||
/* If both NAME and OBJECT are nil, this call is the same as
|
||||
-removeObserver:, so just call it. */
|
||||
if (!name && !object)
|
||||
[self removeObserver: observer];
|
||||
|
||||
/* We are now guaranteed that at least one of NAME and OBJECT is non-nil. */
|
||||
|
||||
[_lock lock];
|
||||
|
||||
/* Get the list of NotificationRequest's associated with OBSERVER. */
|
||||
observer_nr_array = NSMapGet (_observer_2_nr_array, observer);
|
||||
|
||||
if (!observer_nr_array)
|
||||
/* OBSERVER was never registered for any notification requests with us.
|
||||
Nothing to do. */
|
||||
return;
|
||||
|
||||
/* Find those NotificationRequest's from the array that
|
||||
match NAME and OBJECT, and remove them from the array and
|
||||
their linked list. */
|
||||
/* xxx If we thought the LinkedList from the map table keyed on NAME
|
||||
would be shorter, we could use that instead. */
|
||||
{
|
||||
NotificationRequest *nr;
|
||||
int count = [observer_nr_array count];
|
||||
int i;
|
||||
|
||||
for (i = count-1; i >= 0; i--)
|
||||
{
|
||||
nr = [observer_nr_array objectAtIndex: i];
|
||||
if ((!name || [name isEqual: [nr notificationName]])
|
||||
&& (!object || [object isEqual: [nr notificationObject]]))
|
||||
{
|
||||
/* We can remove from the array, even though we are "enumerating"
|
||||
over it, because we are enumerating from back-to-front,
|
||||
and the indices of yet-to-come objects don't change when
|
||||
high-indexed objects are removed. */
|
||||
[observer_nr_array removeObjectAtIndex: i];
|
||||
[self _removeFromLinkedListNotificationRequest: nr];
|
||||
}
|
||||
}
|
||||
/* xxx If there are some LinkedList's that are empty, I should
|
||||
remove them from the map table's. */
|
||||
}
|
||||
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
|
||||
/* Post NOTIFICATION to all the observers that match its NAME and OBJECT. */
|
||||
|
||||
- (void) postNotification: notification
|
||||
{
|
||||
id notification_name = [(NSNotification *)notification name];
|
||||
id notification_object = [notification object];
|
||||
id nr;
|
||||
LinkedList *nr_list;
|
||||
NSMutableArray* array;
|
||||
|
||||
/* Make sure the notification has a name. */
|
||||
if (!notification_name)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Tried to post a notification with no name."];
|
||||
|
||||
[_lock lock];
|
||||
|
||||
array = [[NSMutableArray arrayWithCapacity:10] retain];
|
||||
|
||||
/* Post the notification to all the observers that specified neither
|
||||
NAME or OBJECT. */
|
||||
if ([_anonymous_nr_list count])
|
||||
{
|
||||
FOR_COLLECTION (_anonymous_nr_list, nr)
|
||||
{
|
||||
[array addObject:nr];
|
||||
}
|
||||
END_FOR_COLLECTION (_anonymous_nr_list);
|
||||
while ([array count] > 0)
|
||||
{
|
||||
nr = [array objectAtIndex:0];
|
||||
|
||||
if ([nr linkedList] != NO_OBJECT) /* Has request been removed? */
|
||||
[nr postNotification:notification];
|
||||
[array removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
/* Post the notification to all the observers that specified OBJECT,
|
||||
but didn't specify NAME. */
|
||||
if (notification_object)
|
||||
{
|
||||
nr_list = NSMapGet (_object_2_nr_list, notification_object);
|
||||
if (nr_list)
|
||||
{
|
||||
FOR_COLLECTION (nr_list, nr)
|
||||
{
|
||||
[array addObject:nr];
|
||||
}
|
||||
END_FOR_COLLECTION (nr_list);
|
||||
while ([array count] > 0)
|
||||
{
|
||||
nr = [array objectAtIndex:0];
|
||||
|
||||
if ([nr linkedList] != NO_OBJECT) /* Has request been removed? */
|
||||
[nr postNotification:notification];
|
||||
[array removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Post the notification to all the observers of NAME; (and if the
|
||||
observer's OBJECT is non-nil, don't send unless the observer's OBJECT
|
||||
matches the notification's OBJECT). */
|
||||
nr_list = NSMapGet (_name_2_nr_list, notification_name);
|
||||
if (nr_list)
|
||||
{
|
||||
FOR_COLLECTION (nr_list, nr)
|
||||
{
|
||||
id nr_object = [nr notificationObject];
|
||||
if (!nr_object || nr_object == notification_object)
|
||||
[array addObject:nr];
|
||||
}
|
||||
END_FOR_COLLECTION (nr_list);
|
||||
while ([array count] > 0)
|
||||
{
|
||||
nr = [array objectAtIndex:0];
|
||||
|
||||
if ([nr linkedList] != NO_OBJECT) /* Has request been removed? */
|
||||
[nr postNotification:notification];
|
||||
[array removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
|
||||
[array release];
|
||||
|
||||
[_lock unlock];
|
||||
}
|
||||
|
||||
- (void) postNotificationName: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[self postNotification: [NSNotification notificationWithName: name
|
||||
object: object]];
|
||||
}
|
||||
|
||||
- (void) postNotificationName: (NSString*)name
|
||||
object: object
|
||||
userInfo: info
|
||||
{
|
||||
[self postNotification: [NSNotification notificationWithName: name
|
||||
object: object
|
||||
userInfo: info]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Class methods. */
|
||||
|
||||
+ defaultInstance
|
||||
{
|
||||
return default_notification_dispatcher;
|
||||
}
|
||||
|
||||
+ (void) addInvocation: (id <Invoking>)invocation
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[default_notification_dispatcher addInvocation: invocation
|
||||
name: name
|
||||
object: object];
|
||||
}
|
||||
|
||||
+ (void) addObserver: observer
|
||||
selector: (SEL)sel
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[default_notification_dispatcher addObserver: observer
|
||||
selector: sel
|
||||
name: name
|
||||
object: object];
|
||||
}
|
||||
|
||||
+ (void) removeInvocation: invocation
|
||||
{
|
||||
[default_notification_dispatcher removeInvocation: invocation];
|
||||
}
|
||||
|
||||
+ (void) removeInvocation: invocation
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[default_notification_dispatcher removeInvocation: invocation
|
||||
name: name
|
||||
object: object];
|
||||
}
|
||||
|
||||
+ (void) removeObserver: observer
|
||||
{
|
||||
[default_notification_dispatcher removeObserver: observer];
|
||||
}
|
||||
|
||||
+ (void) removeObserver: observer
|
||||
name: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[default_notification_dispatcher removeObserver: observer
|
||||
name: name
|
||||
object: object];
|
||||
}
|
||||
|
||||
+ (void) postNotification: notification
|
||||
{
|
||||
[default_notification_dispatcher postNotification: notification];
|
||||
}
|
||||
|
||||
+ (void) postNotificationName: (NSString*)name
|
||||
object: object
|
||||
{
|
||||
[default_notification_dispatcher postNotificationName: name
|
||||
object: object];
|
||||
}
|
||||
|
||||
+ (void) postNotificationName: (NSString*)name
|
||||
object: object
|
||||
userInfo: info
|
||||
{
|
||||
[default_notification_dispatcher postNotificationName: name
|
||||
object: object
|
||||
userInfo: info];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NotificationDispatcher (OpenStepCompat)
|
||||
|
||||
/* For OpenStep compatibility. */
|
||||
+ defaultCenter
|
||||
{
|
||||
return default_notification_dispatcher;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,265 +0,0 @@
|
|||
/* Implementation for Objective-C OrderedCollection object
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: Feb 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/OrderedCollection.h>
|
||||
#include <stdio.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/NSString.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
|
||||
@implementation OrderedCollection
|
||||
|
||||
|
||||
// ADDING;
|
||||
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject before: oldObject
|
||||
{
|
||||
int i = [self indexOfObject: oldObject];
|
||||
[self insertObject: newObject atIndex: i];
|
||||
}
|
||||
|
||||
- (void) insertObject: newObject after: oldObject
|
||||
{
|
||||
int i = [self indexOfObject: oldObject];
|
||||
[self insertObject: newObject atIndex: i+1];
|
||||
}
|
||||
|
||||
- (void) insertContentsOf: (id <ConstantCollecting>) aCollection
|
||||
atIndex: (unsigned)index
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
#if 0
|
||||
void doIt(elt e)
|
||||
{
|
||||
[self insertElement: e atIndex: index];
|
||||
}
|
||||
if (aCollection == self)
|
||||
[self safeWithElementsInReverseCall:doIt];
|
||||
else
|
||||
{
|
||||
if ([(id)aCollection respondsToSelector:
|
||||
@selector(withElemetnsInReverseCall:)])
|
||||
[(id)aCollection withElementsInReverseCall:doIt];
|
||||
else
|
||||
[aCollection withElementsCall:doIt];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) appendObject: newObject
|
||||
{
|
||||
[self insertObject: newObject atIndex: [self count]];
|
||||
}
|
||||
|
||||
- (void) prependObject: newObject
|
||||
{
|
||||
[self insertObject: newObject atIndex: 0];
|
||||
}
|
||||
|
||||
- (void) appendContentsOf: (id <ConstantCollecting>) aCollection
|
||||
{
|
||||
id o;
|
||||
|
||||
NSAssert(aCollection != self, NSInvalidArgumentException);
|
||||
/* xxx Could be more efficient. */
|
||||
FOR_COLLECTION(aCollection, o)
|
||||
{
|
||||
[self appendObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(aCollection);
|
||||
}
|
||||
|
||||
- (void) prependContentsOf: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
id o;
|
||||
|
||||
NSAssert(aCollection != self, NSInvalidArgumentException);
|
||||
if ([(id)aCollection conformsTo: @protocol(IndexedCollecting)])
|
||||
{
|
||||
FOR_INDEXED_COLLECTION_REVERSE(self, o)
|
||||
{
|
||||
[self prependObject: o];
|
||||
}
|
||||
END_FOR_INDEXED_COLLECTION_REVERSE(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
FOR_COLLECTION(self, o)
|
||||
{
|
||||
[self prependObject: o];
|
||||
}
|
||||
END_FOR_COLLECTION(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SWAPPING AND SORTING;
|
||||
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2
|
||||
{
|
||||
id tmp = [self objectAtIndex:index1];
|
||||
[self replaceObjectAtIndex: index1 with: [self objectAtIndex: index2]];
|
||||
[self replaceObjectAtIndex: index2 with: tmp];
|
||||
}
|
||||
|
||||
/* This could be hacked a bit to make it more efficient */
|
||||
- (void) quickSortContentsFromIndex: (unsigned)p
|
||||
toIndex: (unsigned)r
|
||||
{
|
||||
unsigned i ,j;
|
||||
id x;
|
||||
|
||||
if (p < r)
|
||||
{
|
||||
/* Partition */
|
||||
x = [self objectAtIndex:p];
|
||||
i = p - 1;
|
||||
j = r + 1;
|
||||
for (;;)
|
||||
{
|
||||
do
|
||||
j = j - 1;
|
||||
while ([[self objectAtIndex: j] compare: x] > 0);
|
||||
do
|
||||
i = i + 1;
|
||||
while ([[self objectAtIndex: i] compare: x] < 0);
|
||||
if (i < j)
|
||||
[self swapAtIndeces: i : j];
|
||||
else
|
||||
break;
|
||||
}
|
||||
/* Sort partitions */
|
||||
[self quickSortContentsFromIndex: p toIndex: j];
|
||||
[self quickSortContentsFromIndex: j+1 toIndex: r];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) sortContents
|
||||
{
|
||||
[self quickSortContentsFromIndex: 0 toIndex: [self count]-1];
|
||||
}
|
||||
|
||||
|
||||
// REPLACING;
|
||||
|
||||
- (void) replaceRange: (IndexRange)aRange
|
||||
withCollection: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
- (void) replaceRange: (IndexRange)aRange
|
||||
usingCollection: (id <ConstantCollecting>)aCollection
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
#if 0
|
||||
- replaceRange: (IndexRange)aRange
|
||||
with: (id <Collecting>)aCollection
|
||||
{
|
||||
CHECK_INDEX_RANGE_ERROR(aRange.location, [self count]);
|
||||
CHECK_INDEX_RANGE_ERROR(aRange.location+aRange.length-1, [self count]);
|
||||
[self removeRange:aRange];
|
||||
[self insertContentsOf:aCollection atIndex:aRange.location];
|
||||
return self;
|
||||
}
|
||||
|
||||
- replaceRange: (IndexRange)aRange
|
||||
using: (id <Collecting>)aCollection
|
||||
{
|
||||
int i;
|
||||
void *state = [aCollection newEnumState];
|
||||
elt e;
|
||||
|
||||
CHECK_INDEX_RANGE_ERROR(aRange.location, [self count]);
|
||||
CHECK_INDEX_RANGE_ERROR(aRange.location+aRange.length-1, [self count]);
|
||||
for (i = aRange.location;
|
||||
i < aRange.location + aRange.length
|
||||
&& [aCollection getNextElement:&e withEnumState:&state];
|
||||
i++)
|
||||
{
|
||||
[self replaceElementAtIndex:i with:e];
|
||||
}
|
||||
[aCollection freeEnumState:&state];
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// OVERRIDE SOME COLLECTION METHODS;
|
||||
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
[self appendObject: newObject];
|
||||
}
|
||||
|
||||
- (void) addContentsOf: (id <Collecting>)aCollection
|
||||
{
|
||||
[self appendContentsOf: aCollection];
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// OVERRIDE SOME KEYED COLLECTION METHODS;
|
||||
|
||||
/* Semantics: You can "put" an element only at index "count" or less */
|
||||
- (void) putObject: newObject atIndex: (unsigned)index
|
||||
{
|
||||
unsigned c = [self count];
|
||||
|
||||
if (index < c)
|
||||
[self replaceObjectAtIndex: index withObject: newObject];
|
||||
else if (index == c)
|
||||
[self appendObject: newObject];
|
||||
else
|
||||
[NSException
|
||||
raise: NSRangeException
|
||||
format: @"in %s, can't put an element at index beyond [self count]"];
|
||||
}
|
||||
|
||||
- putObject: newObject atKey: index
|
||||
{
|
||||
return [self putObject: newObject atIndex: [index unsignedIntValue]];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// OVERRIDE SOME INDEXED COLLECTION METHODS;
|
||||
|
||||
/* Should be more efficiently overriden by some subclasses. */
|
||||
- (void) replaceObjectAtIndex: (unsigned)index withObject: newObject
|
||||
{
|
||||
[self removeObjectAtIndex: index];
|
||||
[self insertObject: newObject atIndex: index];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,48 +0,0 @@
|
|||
/* Implementation for Objective-C Queue object
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Queue.h>
|
||||
#include <base/ArrayPrivate.h>
|
||||
|
||||
@implementation Queue
|
||||
|
||||
- (void) enqueueObject: newObject
|
||||
{
|
||||
[self prependObject: newObject];
|
||||
}
|
||||
|
||||
- dequeueObject
|
||||
{
|
||||
id ret = [[self lastObject] retain];
|
||||
[self removeLastObject];
|
||||
return [ret autorelease];
|
||||
}
|
||||
|
||||
/* Overriding */
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
[self enqueueObject: newObject];
|
||||
}
|
||||
|
||||
@end
|
250
Source/RBTree.m
250
Source/RBTree.m
|
@ -1,250 +0,0 @@
|
|||
/* Implementation for Objective-C Red-Black Tree collection object
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/RBTree.h>
|
||||
#include <base/IndexedCollectionPrivate.h>
|
||||
#include <base/RBTreeNode.h>
|
||||
|
||||
#define NODE_IS_RED(NODE) ([NODE isRed])
|
||||
#define NODE_IS_BLACK(NODE) (![NODE isRed])
|
||||
|
||||
/* sentinal */
|
||||
static id nilRBNode;
|
||||
|
||||
@implementation RBTree
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [RBTree class])
|
||||
{
|
||||
nilRBNode = [[RBTreeNode alloc] init];
|
||||
[nilRBNode setBlack];
|
||||
}
|
||||
}
|
||||
|
||||
- nilNode
|
||||
{
|
||||
return nilRBNode;
|
||||
}
|
||||
|
||||
- (void) sortAddObject: newObject
|
||||
{
|
||||
id y;
|
||||
|
||||
[super sortAddObject: newObject];
|
||||
[newObject setRed];
|
||||
while (newObject != _contents_root
|
||||
&& [[newObject parentNode] isRed])
|
||||
{
|
||||
if ([newObject parentNode] ==
|
||||
[[[newObject parentNode] parentNode] leftNode])
|
||||
{
|
||||
y = [[[newObject parentNode] parentNode] leftNode];
|
||||
if ([y isRed])
|
||||
{
|
||||
[[newObject parentNode] setBlack];
|
||||
[y setBlack];
|
||||
[[[newObject parentNode] parentNode] setRed];
|
||||
newObject = [[newObject parentNode] parentNode];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newObject == [[newObject parentNode] rightNode])
|
||||
{
|
||||
newObject = [newObject parentNode];
|
||||
[self leftRotateAroundNode:newObject];
|
||||
}
|
||||
[[newObject parentNode] setBlack];
|
||||
[[[newObject parentNode] parentNode] setRed];
|
||||
[self rightRotateAroundNode:
|
||||
[[newObject parentNode] parentNode]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y = [[[newObject parentNode] parentNode] rightNode];
|
||||
if ([y isRed])
|
||||
{
|
||||
[[newObject parentNode] setBlack];
|
||||
[y setBlack];
|
||||
[[[newObject parentNode] parentNode] setRed];
|
||||
newObject = [[newObject parentNode] parentNode];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newObject == [[newObject parentNode] leftNode])
|
||||
{
|
||||
newObject = [newObject parentNode];
|
||||
[self rightRotateAroundNode:newObject];
|
||||
}
|
||||
[[newObject parentNode] setBlack];
|
||||
[[[newObject parentNode] parentNode] setRed];
|
||||
[self leftRotateAroundNode:
|
||||
[[newObject parentNode] parentNode]];
|
||||
}
|
||||
}
|
||||
}
|
||||
[_contents_root setBlack];
|
||||
}
|
||||
|
||||
- (void) _RBTreeDeleteFixup: x
|
||||
{
|
||||
id w;
|
||||
|
||||
while (x != _contents_root && NODE_IS_BLACK(x))
|
||||
{
|
||||
if (NODE_IS_LEFTCHILD(x))
|
||||
{
|
||||
w = [[x parentNode] rightNode];
|
||||
if (NODE_IS_RED(w))
|
||||
{
|
||||
[w setBlack];
|
||||
[[x parentNode] setRed];
|
||||
[self leftRotateAroundNode:[x parentNode]];
|
||||
w = [[x parentNode] rightNode];
|
||||
}
|
||||
if (NODE_IS_BLACK([w leftNode]) && NODE_IS_BLACK([w rightNode]))
|
||||
{
|
||||
[w setRed];
|
||||
x = [x parentNode];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NODE_IS_BLACK([w rightNode]))
|
||||
{
|
||||
[[w leftNode] setBlack];
|
||||
[w setRed];
|
||||
[self rightRotateAroundNode:w];
|
||||
w = [[x parentNode] rightNode];
|
||||
}
|
||||
if (NODE_IS_BLACK([x parentNode]))
|
||||
[w setBlack];
|
||||
else
|
||||
[w setRed];
|
||||
[[x parentNode] setBlack];
|
||||
[[w rightNode] setBlack];
|
||||
[self leftRotateAroundNode:[x parentNode]];
|
||||
x = _contents_root;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
w = [[x parentNode] leftNode];
|
||||
if (NODE_IS_RED(w))
|
||||
{
|
||||
[w setBlack];
|
||||
[[x parentNode] setRed];
|
||||
[self rightRotateAroundNode:[x parentNode]];
|
||||
w = [[x parentNode] leftNode];
|
||||
}
|
||||
if (NODE_IS_BLACK([w rightNode]) && NODE_IS_BLACK([w leftNode]))
|
||||
{
|
||||
[w setRed];
|
||||
x = [x parentNode];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NODE_IS_BLACK([w leftNode]))
|
||||
{
|
||||
[[w rightNode] setBlack];
|
||||
[w setRed];
|
||||
[self leftRotateAroundNode:w];
|
||||
w = [[x parentNode] leftNode];
|
||||
}
|
||||
if (NODE_IS_BLACK([x parentNode]))
|
||||
[w setBlack];
|
||||
else
|
||||
[w setRed];
|
||||
[[x parentNode] setBlack];
|
||||
[[w leftNode] setBlack];
|
||||
[self rightRotateAroundNode:[x parentNode]];
|
||||
x = _contents_root;
|
||||
}
|
||||
}
|
||||
}
|
||||
[x setBlack];
|
||||
}
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
id x, y;
|
||||
|
||||
if ([oldObject leftNode] == [self nilNode]
|
||||
|| [oldObject rightNode] == [self nilNode])
|
||||
y = oldObject;
|
||||
else
|
||||
y = [self successorOfObject: oldObject];
|
||||
|
||||
if ([y leftNode] != [self nilNode])
|
||||
x = [y leftNode];
|
||||
else
|
||||
x = [y rightNode];
|
||||
|
||||
[x setParentNode:[y parentNode]];
|
||||
|
||||
if ([y parentNode] == [self nilNode])
|
||||
_contents_root = x;
|
||||
else
|
||||
{
|
||||
if (y == [[y parentNode] leftNode])
|
||||
[[y parentNode] setLeftNode:x];
|
||||
else
|
||||
[[y parentNode] setRightNode:x];
|
||||
}
|
||||
|
||||
if (y != oldObject)
|
||||
{
|
||||
/* put y in the place of oldObject */
|
||||
[y setParentNode:[oldObject parentNode]];
|
||||
[y setLeftNode:[oldObject leftNode]];
|
||||
[y setRightNode:[oldObject rightNode]];
|
||||
if (oldObject == [[oldObject parentNode] leftNode])
|
||||
[[oldObject parentNode] setLeftNode:y];
|
||||
else
|
||||
[[oldObject parentNode] setRightNode:oldObject];
|
||||
[[oldObject leftNode] setParentNode:y];
|
||||
[[oldObject rightNode] setParentNode:y];
|
||||
}
|
||||
|
||||
if (NODE_IS_BLACK(y))
|
||||
[self _RBTreeDeleteFixup:x];
|
||||
|
||||
_count--;
|
||||
|
||||
/* Release ownership of the object. */
|
||||
#if 0
|
||||
[oldObject setRightNode: [self nilNode]];
|
||||
[oldObject setLeftNode: [self nilNode]];
|
||||
[oldObject setParentNode: [self nilNode]];
|
||||
#else
|
||||
[oldObject setLeftNode: NO_OBJECT];
|
||||
[oldObject setRightNode: NO_OBJECT];
|
||||
[oldObject setParentNode: NO_OBJECT];
|
||||
#endif
|
||||
[oldObject setBinaryTree: NO_OBJECT];
|
||||
[oldObject release];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/* Implementation for Objective-C RBTreeNode objects
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/RBTreeNode.h>
|
||||
#include <base/NSString.h>
|
||||
|
||||
@implementation RBTreeNode
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [RBTreeNode class])
|
||||
[self setVersion:0]; /* beta release */
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_red = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
[aCoder encodeValueOfObjCType:@encode(BOOL) at:&_red withName:@"RBTreeNode isRed"];
|
||||
}
|
||||
|
||||
- initWithCoder: aCoder
|
||||
{
|
||||
[self initWithCoder:aCoder];
|
||||
[aCoder decodeValueOfObjCType:@encode(BOOL) at:&_red withName:NULL];
|
||||
return self;
|
||||
}
|
||||
|
||||
- write: (TypedStream*)aStream
|
||||
{
|
||||
[super write:aStream];
|
||||
objc_write_type(aStream, @encode(BOOL), &_red);
|
||||
return self;
|
||||
}
|
||||
|
||||
- read: (TypedStream*)aStream
|
||||
{
|
||||
[super read:aStream];
|
||||
objc_read_type(aStream, @encode(BOOL), &_red);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) isRed
|
||||
{
|
||||
return _red;
|
||||
}
|
||||
|
||||
- setRed
|
||||
{
|
||||
_red = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
- setBlack
|
||||
{
|
||||
_red = NO;
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,112 +0,0 @@
|
|||
/* Implementation additive congruential pseudo-random num generating
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/RNGAdditiveCongruential.h>
|
||||
#include <base/Coder.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Additive Congruential Method,
|
||||
from Robert Sedgewick, "Algorithms" */
|
||||
|
||||
/* The Chi^2 test results for this RNG is bad.
|
||||
xxx Find the bug. */
|
||||
|
||||
@implementation RNGAdditiveCongruential
|
||||
|
||||
- initWithTableSize: (int)s tapsAtOffsets: (int)t1 :(int)t2
|
||||
{
|
||||
[super init];
|
||||
table_size = s;
|
||||
tap1 = t1;
|
||||
tap2 = t2;
|
||||
OBJC_MALLOC(table, long, table_size);
|
||||
[self setRandomSeed:0];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
OBJC_FREE(table);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
[self initWithTableSize:55 tapsAtOffsets:31 :55];
|
||||
return self;
|
||||
}
|
||||
|
||||
#define BITS_PER_CHAR 8
|
||||
#define HIGH_BYTE(X) ((X) / (1 << (sizeof(X)-1) * BITS_PER_CHAR))
|
||||
|
||||
- (long) nextRandom
|
||||
{
|
||||
int i;
|
||||
long result = 0;
|
||||
|
||||
/* Grab only the high bytes---they are the most random */
|
||||
for (i = 0; i < sizeof(long); i++)
|
||||
{
|
||||
index = (index + 1) % table_size;
|
||||
table[index] = (table[(index + table_size - tap1) % table_size]
|
||||
+
|
||||
table[(index + table_size - tap2) % table_size]);
|
||||
result = (result << BITS_PER_CHAR) + HIGH_BYTE(table[index]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) setRandomSeed: (long)s
|
||||
{
|
||||
/* Fill the table with the linear congruential method,
|
||||
from Robert Sedgewick, "Algorithms" */
|
||||
/* b must be x21, with x even, one less number of digits than ULONG_MAX */
|
||||
unsigned long b = ((ULONG_MAX / 1000) * 200) + 21;
|
||||
unsigned char *byte_table = (unsigned char*) table;
|
||||
int byte_table_size = table_size * sizeof(*table);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < byte_table_size; i++)
|
||||
{
|
||||
s = s * b + 1;
|
||||
byte_table[i] = HIGH_BYTE(s);
|
||||
}
|
||||
|
||||
/* Reset index to beginning */
|
||||
index = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,443 +0,0 @@
|
|||
/* Implementation of Berkeley random()-compatible generation for Objective-C
|
||||
|
||||
Reworked by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1995 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is derived from the Berkeley source:
|
||||
* @(#)random.c 5.5 (Berkeley) 7/6/88
|
||||
* It was reworked for the GNU C Library by Roland McGrath.
|
||||
* It was reworked for the GNU Objective-C Library by Andrew Kachites McCallum
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/RNGBerkeley.h>
|
||||
#include <base/Coder.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//#include <sys/time.h>
|
||||
|
||||
/* Deal with bcopy: */
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
#include <string.h>
|
||||
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
|
||||
#if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
|
||||
#define index strchr
|
||||
#define rindex strrchr
|
||||
#define bcopy(s, d, n) memcpy ((d), (s), (n))
|
||||
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
|
||||
#define bzero(s, n) memset ((s), 0, (n))
|
||||
#else /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
#include <strings.h>
|
||||
/* memory.h and strings.h conflict on some systems. */
|
||||
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
|
||||
|
||||
/* An improved random number generation package. In addition to the standard
|
||||
rand()/srand() like interface, this package also has a special state info
|
||||
interface. The initstate() routine is called with a seed, an array of
|
||||
bytes, and a count of how many bytes are being passed in; this array is
|
||||
then initialized to contain information for random number generation with
|
||||
that much state information. Good sizes for the amount of state
|
||||
information are 32, 64, 128, and 256 bytes. The state can be switched by
|
||||
calling the setstate() function with the same array as was initiallized
|
||||
with initstate(). By default, the package runs with 128 bytes of state
|
||||
information and generates far better random numbers than a linear
|
||||
congruential generator. If the amount of state information is less than
|
||||
32 bytes, a simple linear congruential R.N.G. is used. Internally, the
|
||||
state information is treated as an array of longs; the zeroeth element of
|
||||
the array is the type of R.N.G. being used (small integer); the remainder
|
||||
of the array is the state information for the R.N.G. Thus, 32 bytes of
|
||||
state information will give 7 longs worth of state information, which will
|
||||
allow a degree seven polynomial. (Note: The zeroeth word of state
|
||||
information also has some other information stored in it; see setstate
|
||||
for details). The random number generation technique is a linear feedback
|
||||
shift register approach, employing trinomials (since there are fewer terms
|
||||
to sum up that way). In this approach, the least significant bit of all
|
||||
the numbers in the state table will act as a linear feedback shift register,
|
||||
and will have period 2^deg - 1 (where deg is the degree of the polynomial
|
||||
being used, assuming that the polynomial is irreducible and primitive).
|
||||
The higher order bits will have longer periods, since their values are
|
||||
also influenced by pseudo-random carries out of the lower bits. The
|
||||
total period of the generator is approximately deg*(2**deg - 1); thus
|
||||
doubling the amount of state information has a vast influence on the
|
||||
period of the generator. Note: The deg*(2**deg - 1) is an approximation
|
||||
only good for large deg, when the period of the shift register is the
|
||||
dominant factor. With deg equal to seven, the period is actually much
|
||||
longer than the 7*(2**7 - 1) predicted by this formula. */
|
||||
|
||||
|
||||
|
||||
/* For each of the currently supported random number generators, we have a
|
||||
break value on the amount of state information (you need at least thi
|
||||
bytes of state info to support this random number generator), a degree for
|
||||
the polynomial (actually a trinomial) that the R.N.G. is based on, and
|
||||
separation between the two lower order coefficients of the trinomial. */
|
||||
|
||||
|
||||
/* Linear congruential. */
|
||||
#define TYPE_0 0
|
||||
#define BREAK_0 8
|
||||
#define DEG_0 0
|
||||
#define SEP_0 0
|
||||
|
||||
/* x**7 + x**3 + 1. */
|
||||
#define TYPE_1 1
|
||||
#define BREAK_1 32
|
||||
#define DEG_1 7
|
||||
#define SEP_1 3
|
||||
|
||||
/* x**15 + x + 1. */
|
||||
#define TYPE_2 2
|
||||
#define BREAK_2 64
|
||||
#define DEG_2 15
|
||||
#define SEP_2 1
|
||||
|
||||
/* x**31 + x**3 + 1. */
|
||||
#define TYPE_3 3
|
||||
#define BREAK_3 128
|
||||
#define DEG_3 31
|
||||
#define SEP_3 3
|
||||
|
||||
/* x**63 + x + 1. */
|
||||
#define TYPE_4 4
|
||||
#define BREAK_4 256
|
||||
#define DEG_4 63
|
||||
#define SEP_4 1
|
||||
|
||||
/* Array versions of the above information to make code run faster.
|
||||
Relies on fact that TYPE_i == i. */
|
||||
|
||||
#define MAX_TYPES 5 /* Max number of types above. */
|
||||
|
||||
static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
|
||||
static int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
|
||||
|
||||
|
||||
|
||||
/* Initially, everything is set up as if from:
|
||||
initstate(1, randtbl, 128);
|
||||
Note that this initialization takes advantage of the fact that srandom
|
||||
advances the front and rear pointers 10*rand_deg times, and hence the
|
||||
rear pointer which starts at 0 will also end up at zero; thus the zeroeth
|
||||
element of the state information, which contains info about the current
|
||||
position of the rear pointer is just
|
||||
(MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */
|
||||
|
||||
#if 0 /* moved to RNGBerkeley.h -am */
|
||||
static long int randtbl[DEG_3 + 1] =
|
||||
{
|
||||
TYPE_3,
|
||||
-851904987, -43806228, -2029755270, 1390239686, -1912102820,
|
||||
-485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
|
||||
-1714531963, 1800685987, -2015299881, 654595283, -1149023258,
|
||||
-1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
|
||||
-607508183, -205999574, -1696891592, 1492211999, -1528267240,
|
||||
-952028296, -189082757, 362343714, 1424981831, 2039449641,
|
||||
};
|
||||
#endif /* moved to RNGBerkeley.h -am */
|
||||
|
||||
/* FPTR and RPTR are two pointers into the state info, a front and a rear
|
||||
pointer. These two pointers are always rand_sep places aparts, as they
|
||||
cycle through the state information. (Yes, this does mean we could get
|
||||
away with just one pointer, but the code for random is more efficient
|
||||
this way). The pointers are left positioned as they would be from the call:
|
||||
initstate(1, randtbl, 128);
|
||||
(The position of the rear pointer, rptr, is really 0 (as explained above
|
||||
in the initialization of randtbl) because the state table pointer is set
|
||||
to point to randtbl[1] (as explained below).) */
|
||||
|
||||
#if 0 /* moved to RNGBerkeley.h -am */
|
||||
static long int *fptr = &randtbl[SEP_3 + 1];
|
||||
static long int *rptr = &randtbl[1];
|
||||
#endif /* moved to RNGBerkeley.h -am */
|
||||
|
||||
|
||||
/* The following things are the pointer to the state information table,
|
||||
the type of the current generator, the degree of the current polynomial
|
||||
being used, and the separation between the two pointers.
|
||||
Note that for efficiency of random, we remember the first location of
|
||||
the state information, not the zeroeth. Hence it is valid to access
|
||||
state[-1], which is used to store the type of the R.N.G.
|
||||
Also, we remember the last location, since this is more efficient than
|
||||
indexing every time to find the address of the last element to see if
|
||||
the front and rear pointers have wrapped. */
|
||||
|
||||
#if 0 /* moved to RNGBerkeley.h -am */
|
||||
static long int *state = &randtbl[1];
|
||||
|
||||
static int rand_type = TYPE_3;
|
||||
static int rand_deg = DEG_3;
|
||||
static int rand_sep = SEP_3;
|
||||
|
||||
static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
|
||||
#endif /* moved to RNGBerkeley.h -am */
|
||||
|
||||
|
||||
@implementation RNGBerkeley
|
||||
|
||||
- init
|
||||
{
|
||||
static long int static_randtbl[DEG_3 + 1] =
|
||||
{
|
||||
TYPE_3,
|
||||
-851904987, -43806228, -2029755270, 1390239686, -1912102820,
|
||||
-485608943, 1969813258, -1590463333, -1944053249, 455935928, 508023712,
|
||||
-1714531963, 1800685987, -2015299881, 654595283, -1149023258,
|
||||
-1470005550, -1143256056, -1325577603, -1568001885, 1275120390,
|
||||
-607508183, -205999574, -1696891592, 1492211999, -1528267240,
|
||||
-952028296, -189082757, 362343714, 1424981831, 2039449641,
|
||||
};
|
||||
[super init];
|
||||
bcopy(static_randtbl, randtbl, sizeof(randtbl));
|
||||
fptr = &randtbl[SEP_3 + 1];
|
||||
rptr = &randtbl[1];
|
||||
state = &randtbl[1];
|
||||
rand_type = TYPE_3;
|
||||
rand_deg = DEG_3;
|
||||
rand_sep = SEP_3;
|
||||
end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Initialize the random number generator based on the given seed. If the
|
||||
type is the trivial no-state-information type, just remember the seed.
|
||||
Otherwise, initializes state[] based on the given "seed" via a linear
|
||||
congruential generator. Then, the pointers are set to known locations
|
||||
that are exactly rand_sep places apart. Lastly, it cycles the state
|
||||
information a given number of times to get rid of any initial dependencies
|
||||
introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
|
||||
for default usage relies on values produced by this routine. */
|
||||
- (void) _srandom: (unsigned int)x
|
||||
{
|
||||
state[0] = x;
|
||||
if (rand_type != TYPE_0)
|
||||
{
|
||||
register long int i;
|
||||
for (i = 1; i < rand_deg; ++i)
|
||||
state[i] = (1103515145 * state[i - 1]) + 12345;
|
||||
fptr = &state[rand_sep];
|
||||
rptr = &state[0];
|
||||
for (i = 0; i < 10 * rand_deg; ++i)
|
||||
[self nextRandom]; /* (void) __random(); */
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setRandomSeed: (long)aSeed
|
||||
{
|
||||
[self _srandom:aSeed];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the state information in the given array of N bytes for
|
||||
future random number generation. Based on the number of bytes we
|
||||
are given, and the break values for the different R.N.G.'s, we choose
|
||||
the best (largest) one we can and set things up for it. srandom is
|
||||
then called to initialize the state information. Note that on return
|
||||
from srandom, we set state[-1] to be the type multiplexed with the current
|
||||
value of the rear pointer; this is so successive calls to initstate won't
|
||||
lose this information and will be able to restart with setstate.
|
||||
Note: The first thing we do is save the current state, if any, just like
|
||||
setstate so that it doesn't matter when initstate is called.
|
||||
Returns a pointer to the old state. */
|
||||
- (void*) _initstateSeed: (unsigned int)seed
|
||||
state: (void*)arg_state
|
||||
size: (size_t)n
|
||||
{
|
||||
void* ostate = (void*) &state[-1];
|
||||
|
||||
if (rand_type == TYPE_0)
|
||||
state[-1] = rand_type;
|
||||
else
|
||||
state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
|
||||
if (n < BREAK_1)
|
||||
{
|
||||
if (n < BREAK_0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
rand_type = TYPE_0;
|
||||
rand_deg = DEG_0;
|
||||
rand_sep = SEP_0;
|
||||
}
|
||||
else if (n < BREAK_2)
|
||||
{
|
||||
rand_type = TYPE_1;
|
||||
rand_deg = DEG_1;
|
||||
rand_sep = SEP_1;
|
||||
}
|
||||
else if (n < BREAK_3)
|
||||
{
|
||||
rand_type = TYPE_2;
|
||||
rand_deg = DEG_2;
|
||||
rand_sep = SEP_2;
|
||||
}
|
||||
else if (n < BREAK_4)
|
||||
{
|
||||
rand_type = TYPE_3;
|
||||
rand_deg = DEG_3;
|
||||
rand_sep = SEP_3;
|
||||
}
|
||||
else
|
||||
{
|
||||
rand_type = TYPE_4;
|
||||
rand_deg = DEG_4;
|
||||
rand_sep = SEP_4;
|
||||
}
|
||||
|
||||
state = &((long int *) arg_state)[1]; /* First location. */
|
||||
/* Must set END_PTR before srandom. */
|
||||
end_ptr = &state[rand_deg];
|
||||
[self _srandom:seed]; /*__srandom(seed); */
|
||||
if (rand_type == TYPE_0)
|
||||
state[-1] = rand_type;
|
||||
else
|
||||
state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
|
||||
|
||||
return ostate;
|
||||
}
|
||||
|
||||
|
||||
/* Restore the state from the given state array.
|
||||
Note: It is important that we also remember the locations of the pointers
|
||||
in the current state information, and restore the locations of the pointers
|
||||
from the old state information. This is done by multiplexing the pointer
|
||||
location into the zeroeth word of the state information. Note that due
|
||||
to the order in which things are done, it is OK to call setstate with the
|
||||
same state as the current state
|
||||
Returns a pointer to the old state information. */
|
||||
- (void*) _setstate: (void*)arg_state
|
||||
{
|
||||
register long int *new_state = (long int *) arg_state;
|
||||
register int type = new_state[0] % MAX_TYPES;
|
||||
register int rear = new_state[0] / MAX_TYPES;
|
||||
void* ostate = (void*) &state[-1];
|
||||
|
||||
if (rand_type == TYPE_0)
|
||||
state[-1] = rand_type;
|
||||
else
|
||||
state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TYPE_0:
|
||||
case TYPE_1:
|
||||
case TYPE_2:
|
||||
case TYPE_3:
|
||||
case TYPE_4:
|
||||
rand_type = type;
|
||||
rand_deg = degrees[type];
|
||||
rand_sep = seps[type];
|
||||
break;
|
||||
default:
|
||||
/* State info munged. */
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = &new_state[1];
|
||||
if (rand_type != TYPE_0)
|
||||
{
|
||||
rptr = &state[rear];
|
||||
fptr = &state[(rear + rand_sep) % rand_deg];
|
||||
}
|
||||
/* Set end_ptr too. */
|
||||
end_ptr = &state[rand_deg];
|
||||
|
||||
return ostate;
|
||||
}
|
||||
|
||||
|
||||
/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
|
||||
congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
|
||||
same in all ther other cases due to all the global variables that have been
|
||||
set up. The basic operation is to add the number at the rear pointer into
|
||||
the one at the front pointer. Then both pointers are advanced to the next
|
||||
location cyclically in the table. The value returned is the sum generated,
|
||||
reduced to 31 bits by throwing away the "least random" low bit.
|
||||
Note: The code takes advantage of the fact that both the front and
|
||||
rear pointers can't wrap on the same call by not testing the rear
|
||||
pointer if the front one has wrapped. Returns a 31-bit random number. */
|
||||
|
||||
- (long) nextRandom
|
||||
{
|
||||
if (rand_type == TYPE_0)
|
||||
{
|
||||
state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
|
||||
return state[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
long int i;
|
||||
*fptr += *rptr;
|
||||
/* Chucking least random bit. */
|
||||
i = (*fptr >> 1) & LONG_MAX;
|
||||
++fptr;
|
||||
if (fptr >= end_ptr)
|
||||
{
|
||||
fptr = state;
|
||||
++rptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
++rptr;
|
||||
if (rptr >= end_ptr)
|
||||
rptr = state;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
306
Source/Random.m
306
Source/Random.m
|
@ -1,306 +0,0 @@
|
|||
/* Implementation Objective-C object providing randoms in uniform distribution
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
RNGBerkeley nextRandom returns only positive numbers
|
||||
RNGAdditiveCongruential nextRandom returns positive and negative numbers
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Random.h>
|
||||
#include <base/RNGBerkeley.h>
|
||||
#include <base/Time.h>
|
||||
#include <base/Coder.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef union {
|
||||
float f;
|
||||
unsigned long u;
|
||||
} float_and_long_u;
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
unsigned long u[2];
|
||||
} double_and_long_u;
|
||||
|
||||
static float_and_long_u singleMantissa;
|
||||
static double_and_long_u doubleMantissa;
|
||||
|
||||
static id defaultRNG = nil;
|
||||
@class RNGBerkeley;
|
||||
|
||||
@implementation Random
|
||||
|
||||
+ initialize
|
||||
{
|
||||
if (self == [Random class])
|
||||
{
|
||||
defaultRNG = [RNGBerkeley class];
|
||||
NSAssert(sizeof(double) == 2 * sizeof(long), NSInternalInconsistencyException);
|
||||
NSAssert(sizeof(float) == sizeof(long), NSInternalInconsistencyException);
|
||||
|
||||
/* Following taken from libg++ */
|
||||
|
||||
/*
|
||||
The following is a hack that I attribute to
|
||||
Andres Nowatzyk at CMU. The intent of the loop
|
||||
is to form the smallest number 0 <= x < 1.0,
|
||||
which is then used as a mask for two longwords.
|
||||
this gives us a fast way way to produce double
|
||||
precision numbers from longwords.
|
||||
|
||||
I know that this works for IEEE and VAX floating
|
||||
point representations.
|
||||
|
||||
A further complication is that gnu C will blow
|
||||
the following loop, unless compiled with -ffloat-store,
|
||||
because it uses extended representations for some of
|
||||
of the comparisons. Thus, we have the following hack.
|
||||
If we could specify #pragma optimize, we wouldn't need this.
|
||||
*/
|
||||
{
|
||||
double_and_long_u t;
|
||||
float_and_long_u s;
|
||||
|
||||
#if _IEEE == 1
|
||||
|
||||
t.d = 1.5;
|
||||
if ( t.u[1] == 0 ) { // sun word order?
|
||||
t.u[0] = 0x3fffffff;
|
||||
t.u[1] = 0xffffffff;
|
||||
}
|
||||
else {
|
||||
t.u[0] = 0xffffffff; // encore word order?
|
||||
t.u[1] = 0x3fffffff;
|
||||
}
|
||||
|
||||
s.u = 0x3fffffff;
|
||||
#else
|
||||
volatile double x = 1.0; /* volatile needed when fp hardware used,
|
||||
and has greater precision than memory
|
||||
doubles */
|
||||
double y = 0.5;
|
||||
volatile float xx = 1.0; /* volatile needed when fp hardware used,
|
||||
and has greater precision than memory
|
||||
floats */
|
||||
float yy = 0.5;
|
||||
do { /* find largest fp-number < 2.0 */
|
||||
t.d = x;
|
||||
x += y;
|
||||
y *= 0.5;
|
||||
} while (x != t.d && x < 2.0);
|
||||
|
||||
do { /*find largest fp-number < 2.0 */
|
||||
s.f = xx;
|
||||
xx += yy;
|
||||
yy *= 0.5;
|
||||
} while (xx != s.f && xx < 2.0);
|
||||
#endif
|
||||
// set doubleMantissa to 1 for each doubleMantissa bit;
|
||||
doubleMantissa.d = 1.0;
|
||||
doubleMantissa.u[0] ^= t.u[0];
|
||||
doubleMantissa.u[1] ^= t.u[1];
|
||||
|
||||
// set singleMantissa to 1 for each singleMantissa bit;
|
||||
singleMantissa.f = 1.0;
|
||||
singleMantissa.u ^= s.u;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ setDefaultRandomGeneratorClass: (id <RandomGenerating>)aRNG
|
||||
{
|
||||
defaultRNG = aRNG;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (id <RandomGenerating>) defaultRandomGeneratorClass
|
||||
{
|
||||
return defaultRNG;
|
||||
}
|
||||
|
||||
/* For testing randomness of a random generator,
|
||||
the closer to r the returned value is, the better the randomness. */
|
||||
|
||||
+ (float) chiSquareOfRandomGenerator: (id <RandomGenerating>)aRNG
|
||||
iterations: (int)n
|
||||
range: (long)r
|
||||
{
|
||||
long table[r];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < r; i++)
|
||||
table[i] = 0;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
j = ABS([aRNG nextRandom]) % r;
|
||||
table[j]++;
|
||||
}
|
||||
j = 0;
|
||||
for (i = 0; i < r; i++)
|
||||
j += table[i] * table[i];
|
||||
return ((((float)r * j) / n) - n);
|
||||
}
|
||||
|
||||
/* For testing randomness of a random generator,
|
||||
the closer to 1.0 the returned value is, the better the randomness. */
|
||||
|
||||
+ (float) chiSquareOfRandomGenerator: (id <RandomGenerating>)aRNG
|
||||
{
|
||||
return [self chiSquareOfRandomGenerator:aRNG
|
||||
iterations:1000
|
||||
range:100] / 100.0;
|
||||
}
|
||||
|
||||
- initWithRandomGenerator: (id <RandomGenerating>)aRNG
|
||||
{
|
||||
[super init];
|
||||
rng = aRNG;
|
||||
return self;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
/* Without the (id) we get:
|
||||
Random.m: In function `_i_Random__init':
|
||||
Random.m:172: warning: method `alloc' not implemented by protocol.
|
||||
This is a bug in gcc.
|
||||
*/
|
||||
return [self initWithRandomGenerator:
|
||||
[[(id)[[self class] defaultRandomGeneratorClass] alloc] init]];
|
||||
}
|
||||
|
||||
- setRandomSeedFromClock
|
||||
{
|
||||
[self setRandomSeed:[Time secondClockValue]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- setRandomSeed: (long)seed
|
||||
{
|
||||
[rng setRandomSeed:seed];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (long) randomInt
|
||||
{
|
||||
return [rng nextRandom];
|
||||
}
|
||||
|
||||
- (long) randomIntBetween: (long)lowBound and: (long)highBound
|
||||
{
|
||||
return ([rng nextRandom] % (highBound - lowBound + 1) + lowBound);
|
||||
}
|
||||
|
||||
/* return between 0 and numSides-1 */
|
||||
- (long) randomDie: (long)numSides
|
||||
{
|
||||
return ([rng nextRandom] % numSides);
|
||||
}
|
||||
|
||||
- (BOOL) randomCoin
|
||||
{
|
||||
return ([rng nextRandom] % 2);
|
||||
}
|
||||
|
||||
- (BOOL) randomCoinWithProbability: (double)p
|
||||
{
|
||||
return (p >= [self randomDoubleProbability]);
|
||||
}
|
||||
|
||||
/* Returns 0.0 <= r < 1.0. Is this what people want?
|
||||
I'd like it to return 1.0 also. */
|
||||
- (float) randomFloat
|
||||
{
|
||||
union {long i; float f;} result;
|
||||
result.f = 1.0;
|
||||
result.i |= ([rng nextRandom] & singleMantissa.u);
|
||||
result.f -= 1.0;
|
||||
NSAssert(result.f < 1.0 && result.f >= 0, NSInternalInconsistencyException);
|
||||
return result.f;
|
||||
}
|
||||
|
||||
- (float) randomFloatBetween: (float)lowBound and: (float)highBound
|
||||
{
|
||||
return ([self randomFloat] * (highBound - lowBound) + lowBound);
|
||||
}
|
||||
|
||||
- (float) randomFloatProbability
|
||||
{
|
||||
return [self randomFloat];
|
||||
}
|
||||
|
||||
/* Returns 0.0 <= r < 1.0. Is this what people want?
|
||||
I'd like it to return 1.0 also. */
|
||||
- (double) randomDouble
|
||||
{
|
||||
union {unsigned long u[2]; double d;} result;
|
||||
|
||||
result.d = 1.0;
|
||||
result.u[0] |= ([rng nextRandom] & doubleMantissa.u[0]);
|
||||
result.u[1] |= ([rng nextRandom] & doubleMantissa.u[1]);
|
||||
result.d -= 1.0;
|
||||
NSAssert(result.d < 1.0 && result.d >= 0, NSInternalInconsistencyException);
|
||||
return result.d;
|
||||
}
|
||||
|
||||
- (double) randomDoubleBetween: (double)lowBound and: (double)highBound
|
||||
{
|
||||
return [self randomDouble] * (highBound - lowBound);
|
||||
}
|
||||
|
||||
- (double) randomDoubleProbability
|
||||
{
|
||||
return [self randomDouble];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- write: (TypedStream*)aStream
|
||||
{
|
||||
[super write:aStream];
|
||||
// [rng read:aStream];
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- read: (TypedStream*)aStream
|
||||
{
|
||||
[super read:aStream];
|
||||
// [rng read:aStream];
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
229
Source/Set.m
229
Source/Set.m
|
@ -1,229 +0,0 @@
|
|||
/* Implementation for Objective-C Set collection object
|
||||
Copyright (C) 1993,1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Set.h>
|
||||
#include <base/CollectionPrivate.h>
|
||||
#include <base/Coder.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
|
||||
#define DEFAULT_SET_CAPACITY 32
|
||||
|
||||
@implementation Set
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
|
||||
/* Eventually we will want to have better capacity management,
|
||||
potentially keep default capacity as a class variable. */
|
||||
|
||||
+ (unsigned) defaultCapacity
|
||||
{
|
||||
return DEFAULT_SET_CAPACITY;
|
||||
}
|
||||
|
||||
// INITIALIZING AND FREEING;
|
||||
|
||||
/* This is the designated initializer of this class */
|
||||
- initWithCapacity: (unsigned)cap
|
||||
{
|
||||
_contents_hash = NSCreateHashTable(NSObjectHashCallBacks, cap);
|
||||
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 */
|
||||
|
||||
- _initCollectionWithCoder: aCoder
|
||||
{
|
||||
[super _initCollectionWithCoder:aCoder];
|
||||
_contents_hash = NSCreateHashTable(NSObjectHashCallBacks,
|
||||
DEFAULT_SET_CAPACITY);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Empty copy must empty an allocCopy'ed version of self */
|
||||
- emptyCopy
|
||||
{
|
||||
Set *copy = [super emptyCopy];
|
||||
copy->_contents_hash =
|
||||
NSCreateHashTable (NSObjectHashCallBacks, 0);
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (_contents_hash)
|
||||
{
|
||||
NSFreeHashTable (_contents_hash);
|
||||
_contents_hash = 0;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// SET OPERATIONS;
|
||||
|
||||
- (void) intersectWithCollection: (id <Collecting>)aCollection
|
||||
{
|
||||
[self removeContentsNotIn: aCollection];
|
||||
}
|
||||
|
||||
- (void) unionWithCollection: (id <Collecting>)aCollection
|
||||
{
|
||||
[self addContentsIfAbsentOf: aCollection];
|
||||
}
|
||||
|
||||
- (void) differenceWithCollection: (id <Collecting>)aCollection
|
||||
{
|
||||
[self removeContentsIn: aCollection];
|
||||
}
|
||||
|
||||
- shallowCopyIntersectWithCollection: (id <Collecting>)aCollection
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
#if 0
|
||||
id newColl = [self emptyCopyAs:[self species]];
|
||||
void doIt(elt e)
|
||||
{
|
||||
if ([aCollection includesElement:e])
|
||||
[newColl addElement:e];
|
||||
}
|
||||
[self withElementsCall:doIt];
|
||||
return newColl;
|
||||
#endif
|
||||
}
|
||||
|
||||
- shallowCopyUnionWithCollection: (id <Collecting>)aCollection
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
#if 0
|
||||
id newColl = [self shallowCopy];
|
||||
[newColl addContentsOf:aCollection];
|
||||
return newColl;
|
||||
#endif
|
||||
}
|
||||
|
||||
- shallowCopyDifferenceWithCollection: (id <Collecting>)aCollection
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
#if 0
|
||||
id newColl = [self emptyCopyAs:[self species]];
|
||||
void doIt(elt e)
|
||||
{
|
||||
if (![aCollection includesElement:e])
|
||||
[newColl addElement:e];
|
||||
}
|
||||
[self withElementsCall:doIt];
|
||||
return newColl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ADDING;
|
||||
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
NSHashInsert (_contents_hash, newObject);
|
||||
}
|
||||
|
||||
|
||||
// REMOVING AND REPLACING;
|
||||
|
||||
- (void) removeObject: oldObject
|
||||
{
|
||||
NSHashRemove (_contents_hash, oldObject);
|
||||
}
|
||||
|
||||
/* This must work without sending any messages to content objects */
|
||||
- (void) _collectionEmpty
|
||||
{
|
||||
NSResetHashTable (_contents_hash);
|
||||
}
|
||||
|
||||
- (void) uniqueContents
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// TESTING;
|
||||
|
||||
- (BOOL) containsObject: anObject
|
||||
{
|
||||
return (NSHashGet (_contents_hash, anObject) ? 1 : 0);
|
||||
}
|
||||
|
||||
- (unsigned) count
|
||||
{
|
||||
if (!_contents_hash)
|
||||
return 0;
|
||||
return NSCountHashTable (_contents_hash);
|
||||
}
|
||||
|
||||
- (unsigned) occurrencesOfObject: anObject
|
||||
{
|
||||
if ([self containsObject: anObject])
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
- member: anObject
|
||||
{
|
||||
return NSHashGet(_contents_hash, anObject);
|
||||
}
|
||||
|
||||
|
||||
// ENUMERATING;
|
||||
|
||||
- nextObjectWithEnumState: (void**)enumState
|
||||
{
|
||||
return NSNextHashEnumeratorItem ((*(NSHashEnumerator**)enumState));
|
||||
}
|
||||
|
||||
- (void*) newEnumState
|
||||
{
|
||||
void *es;
|
||||
|
||||
OBJC_MALLOC (es, NSMapEnumerator, 1);
|
||||
*((NSHashEnumerator*)es) = NSEnumerateHashTable (_contents_hash);
|
||||
return es;
|
||||
}
|
||||
|
||||
- (void) freeEnumState: (void**)enumState
|
||||
{
|
||||
OBJC_FREE (*enumState);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
/* Implementation for Objective-C SplayTree collection object
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/SplayTree.h>
|
||||
#include <base/IndexedCollectionPrivate.h>
|
||||
|
||||
@implementation SplayTree
|
||||
|
||||
/* Make this a function ? */
|
||||
- (void) _doSplayOperationOnNode: aNode
|
||||
{
|
||||
id parent = [aNode parentNode];
|
||||
id parentRightChild =
|
||||
((parent == [self nilNode]) ? [self nilNode] : [parent rightNode]);
|
||||
|
||||
if (aNode == _contents_root || aNode == [self nilNode])
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (aNode == parentRightChild)
|
||||
{
|
||||
if (parent == _contents_root)
|
||||
{
|
||||
[self leftRotateAroundNode:parent];
|
||||
}
|
||||
else if (NODE_IS_RIGHTCHILD(parent))
|
||||
{
|
||||
[self leftRotateAroundNode:[parent parentNode]];
|
||||
[self leftRotateAroundNode:parent];
|
||||
}
|
||||
else
|
||||
/* NODE_IS_LEFTCHILD(parent) */
|
||||
{
|
||||
[self leftRotateAroundNode:parent];
|
||||
[self rightRotateAroundNode:[aNode parentNode]];
|
||||
}
|
||||
}
|
||||
else
|
||||
/* aNode == parentLeftChild */
|
||||
{
|
||||
if (parent == _contents_root)
|
||||
{
|
||||
[self rightRotateAroundNode:parent];
|
||||
}
|
||||
else if (NODE_IS_LEFTCHILD(parent))
|
||||
{
|
||||
[self rightRotateAroundNode:[parent parentNode]];
|
||||
[self rightRotateAroundNode:parent];
|
||||
}
|
||||
else
|
||||
/* NODE_IS_RIGHTCHILD(parent) */
|
||||
{
|
||||
[self rightRotateAroundNode:parent];
|
||||
[self leftRotateAroundNode:[aNode parentNode]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) splayNode: aNode
|
||||
{
|
||||
while (aNode != _contents_root)
|
||||
[self _doSplayOperationOnNode:aNode];
|
||||
}
|
||||
|
||||
/* We could make this a little more efficient by doing the splay as
|
||||
we search down the tree for the correct insertion point. */
|
||||
- (void) sortAddObject: newObject
|
||||
{
|
||||
[super sortAddObject: newObject];
|
||||
[self splayNode: newObject];
|
||||
}
|
||||
|
||||
- (void) removeObject: anObject
|
||||
{
|
||||
id parent = [anObject parentNode];
|
||||
[super removeObject: anObject];
|
||||
if (parent && parent != [self nilNode])
|
||||
[self splayNode:parent];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,66 +0,0 @@
|
|||
/* Implementation for Objective-C Stack object
|
||||
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Stack.h>
|
||||
#include <base/ArrayPrivate.h>
|
||||
|
||||
@implementation Stack
|
||||
|
||||
- (void) pushObject: newObject
|
||||
{
|
||||
[self appendObject: newObject];
|
||||
}
|
||||
|
||||
/* Overriding */
|
||||
- (void) addObject: newObject
|
||||
{
|
||||
[self pushObject: newObject];
|
||||
}
|
||||
|
||||
- popObject
|
||||
{
|
||||
id ret;
|
||||
ret = [[self lastObject] retain];
|
||||
[self removeLastObject];
|
||||
return [ret autorelease];
|
||||
}
|
||||
|
||||
- topObject
|
||||
{
|
||||
return [self lastObject];
|
||||
}
|
||||
|
||||
/* xxx Yipes. What copying semantics do we want here? */
|
||||
- (void) duplicateTop
|
||||
{
|
||||
[self pushObject: [self topObject]];
|
||||
}
|
||||
|
||||
- (void) exchangeTop
|
||||
{
|
||||
if (_count > 1)
|
||||
[self swapAtIndeces:_count-1 :_count-2];
|
||||
}
|
||||
|
||||
@end
|
Loading…
Add table
Add a link
Reference in a new issue