mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 08:26:27 +00:00
Remove old source
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@12356 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
3cd3290404
commit
babf23255c
125 changed files with 7 additions and 28856 deletions
|
@ -1,3 +1,8 @@
|
|||
2002-01-31 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Old/*: Removed (now at
|
||||
ftp://ftp.gnustep.org/pub/gnustep/old/gnustep-obsolete.tar.gz).
|
||||
|
||||
2002-01-31 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSMapTable.m:
|
||||
|
|
|
@ -14,8 +14,7 @@ The GNUstep Base Library is a library of general-purpose, non-graphical
|
|||
Objective C objects. For example, it includes classes for strings,
|
||||
object collections, byte streams, typed coders, invocations,
|
||||
notifications, notification dispatchers, moments in time, network ports,
|
||||
remote object messaging support (distributed objects), event loops, and
|
||||
random number generators.
|
||||
remote object messaging support (distributed objects), and event loops.
|
||||
|
||||
It provides functionality that aims to implement the non-graphical
|
||||
portion of the OpenStep standard (the Foundation library).
|
||||
|
|
|
@ -7,8 +7,7 @@ The GNUstep Base Library is a library of general-purpose, non-graphical
|
|||
Objective C objects. For example, it includes classes for strings,
|
||||
object collections, byte streams, typed coders, invocations,
|
||||
notifications, notification dispatchers, moments in time, network ports,
|
||||
remote object messaging support (distributed objects), event loops, and
|
||||
random number generators.
|
||||
remote object messaging support (distributed objects), and event loops.
|
||||
|
||||
It provides functionality that aims to implement the non-graphical
|
||||
portion of the OpenStep standard (the Foundation library).
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/* Interface for GNU Objective-C Archiver object for use serializing
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __Archiver_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Archiver_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coder.h>
|
||||
|
||||
/* Eventually some functionality may be moved out of Coder and
|
||||
into these objects.
|
||||
|
||||
These class should be used as concrete classes, not the Coder class. */
|
||||
|
||||
|
||||
@interface Archiver : Encoder
|
||||
@end
|
||||
|
||||
@interface Unarchiver : Decoder
|
||||
@end
|
||||
|
||||
#endif /* __Archiver_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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
|
72
Old/Array.h
72
Old/Array.h
|
@ -1,72 +0,0 @@
|
|||
/* Interface for Objective-C Array 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.
|
||||
*/
|
||||
|
||||
#ifndef __Array_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Array_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/IndexedCollection.h>
|
||||
#include <base/OrderedCollecting.h>
|
||||
|
||||
@interface ConstantArray : ConstantIndexedCollection
|
||||
{
|
||||
@public
|
||||
id *_contents_array;
|
||||
unsigned int _count;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface Array : ConstantArray
|
||||
{
|
||||
@public
|
||||
unsigned int _capacity;
|
||||
int _grow_factor;
|
||||
}
|
||||
|
||||
+ (unsigned) defaultCapacity;
|
||||
+ (int) defaultGrowFactor;
|
||||
|
||||
- initWithCapacity: (unsigned) aCapacity;
|
||||
|
||||
- (void) setCapacity: (unsigned)newCapacity;
|
||||
- (int) growFactor;
|
||||
- (void) setGrowFactor: (int)aNum;
|
||||
|
||||
@end
|
||||
|
||||
/* Put this on category instead of class to avoid bogus complaint from gcc */
|
||||
@interface Array (Ordering) <OrderedCollecting>
|
||||
@end
|
||||
|
||||
#define FOR_ARRAY(ARRAY, ELEMENT_VAR) \
|
||||
{ \
|
||||
unsigned _FOR_ARRAY_i; \
|
||||
for (_FOR_ARRAY_i = 0; \
|
||||
_FOR_ARRAY_i < ((Array*)ARRAY)->_count; \
|
||||
_FOR_ARRAY_i++) \
|
||||
{ \
|
||||
ELEMENT_VAR = \
|
||||
(((Array*)ARRAY)->_contents_array[_FOR_ARRAY_i]);
|
||||
|
||||
#define END_FOR_ARRAY(ARRAY) }}
|
||||
|
||||
#endif /* __Array_h_GNUSTEP_BASE_INCLUDE */
|
263
Old/Array.m
263
Old/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
|
|
@ -1,87 +0,0 @@
|
|||
/* Array definitions for the use of subclass implementations only
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __ArrayPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __ArrayPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/IndexedCollectionPrivate.h>
|
||||
|
||||
#define DEFAULT_ARRAY_CAPACITY 2
|
||||
#define DEFAULT_ARRAY_GROW_FACTOR 2
|
||||
|
||||
|
||||
/* Routines that help with inserting and removing elements */
|
||||
|
||||
/* Assumes that _count has already been incremented to make room
|
||||
for the hole. The data at _contents_array[_count-1] is not part
|
||||
of the collection). */
|
||||
static inline void
|
||||
makeHoleAt(Array *self, unsigned index)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = (self->_count)-1; i > index; i--)
|
||||
self->_contents_array[i] = self->_contents_array[i-1];
|
||||
}
|
||||
|
||||
/* Assumes that _count has not yet been decremented. The data at
|
||||
_contents_array[_count-1] is part of the collection. */
|
||||
static inline void
|
||||
fillHoleAt(Array *self, unsigned index)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = index; i < (self->_count)-1; i++)
|
||||
self->_contents_array[i] = self->_contents_array[i+1];
|
||||
}
|
||||
|
||||
/* These are the only two routines that change the value of the instance
|
||||
variable _count, except for "-initWithType:capacity:" and "-empty" */
|
||||
|
||||
/* Should these be methods instead of functions? Doing so would make
|
||||
them slower. */
|
||||
|
||||
/* Do this before adding an element */
|
||||
static inline void
|
||||
incrementCount(Array *self)
|
||||
{
|
||||
(self->_count)++;
|
||||
if (self->_count == self->_capacity)
|
||||
{
|
||||
[self setCapacity:(self->_capacity) * ABS(self->_grow_factor)];
|
||||
}
|
||||
}
|
||||
|
||||
/* Do this after removing an element */
|
||||
static inline void
|
||||
decrementCount(Array *self)
|
||||
{
|
||||
(self->_count)--;
|
||||
if (self->_grow_factor > 0
|
||||
&& self->_count < (self->_capacity / self->_grow_factor))
|
||||
{
|
||||
[self setCapacity:(self->_capacity) / self->_grow_factor];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ArrayPrivate_h_GNUSTEP_BASE_INCLUDE */
|
50
Old/Bag.h
50
Old/Bag.h
|
@ -1,50 +0,0 @@
|
|||
/* Interface 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.
|
||||
*/
|
||||
|
||||
#ifndef __Bag_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Bag_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Collection.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@interface Bag : Collection
|
||||
{
|
||||
NSMapTable *_contents_map;
|
||||
unsigned int _count; // the number of elements;
|
||||
}
|
||||
|
||||
// INITIALIZING AND FREEING;
|
||||
- initWithCapacity: (unsigned)aCapacity;
|
||||
|
||||
// ADDING;
|
||||
- (void) addObject: newObject withOccurrences: (unsigned)count;
|
||||
|
||||
// REMOVING AND REPLACING;
|
||||
- (void) removeObject: oldObject occurrences: (unsigned)count;
|
||||
|
||||
// TESTING;
|
||||
- (unsigned) uniqueCount;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Bag_h_GNUSTEP_BASE_INCLUDE */
|
211
Old/Bag.m
211
Old/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,42 +0,0 @@
|
|||
/* Interface for GNU Objective-C binary stream object for use serializing
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 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.
|
||||
*/
|
||||
|
||||
#ifndef __BinaryCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __BinaryCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStream.h>
|
||||
|
||||
@interface BinaryCStream : CStream
|
||||
{
|
||||
unsigned char _sizeof_long;
|
||||
unsigned char _sizeof_int;
|
||||
unsigned char _sizeof_short;
|
||||
unsigned char _sizeof_char;
|
||||
}
|
||||
|
||||
+ setDebugging: (BOOL)f;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __BinaryCStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,646 +0,0 @@
|
|||
/* Implementation of GNU Objective-C binary stream object for use serializing
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 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/BinaryCStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSByteOrder.h>
|
||||
#include <math.h>
|
||||
#if HAVE_VALUES_H
|
||||
#include <values.h> // This gets BITSPERBYTE on Solaris
|
||||
#endif
|
||||
|
||||
#define PRE_SIZEOF_PREFIX_FORMAT_VERSION 0
|
||||
#define CURRENT_FORMAT_VERSION ((((GNUSTEP_BASE_MAJOR_VERSION * 100) + \
|
||||
GNUSTEP_BASE_MINOR_VERSION) * 100) + GNUSTEP_BASE_SUBMINOR_VERSION)
|
||||
#define DEFAULT_FORMAT_VERSION CURRENT_FORMAT_VERSION
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
/* The number of bytes used to encode the length of a _C_CHARPTR
|
||||
string that is encoded. */
|
||||
#define NUM_BYTES_STRING_LENGTH 4
|
||||
|
||||
/* The value by which we multiply a float or double in order to bring
|
||||
mantissa digits to the left-hand-side of the decimal point, so that
|
||||
we can extract them by assigning the float or double to an int. */
|
||||
#if !defined(BITSPERBYTE) && defined(NeXT)
|
||||
#include <mach/vm_param.h>
|
||||
#define BITSPERBYTE BYTE_SIZE
|
||||
#elif !defined(BITSPERBYTE)
|
||||
#define BITSPERBYTE 8 /* a safe guess? */
|
||||
#endif
|
||||
#define FLOAT_FACTOR ((double)(1 << ((sizeof(int)*BITSPERBYTE)-2)))
|
||||
|
||||
@implementation BinaryCStream
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [BinaryCStream class])
|
||||
/* Make sure that we don't overrun memory when reading _C_CHARPTR. */
|
||||
NSAssert (sizeof(unsigned) >= NUM_BYTES_STRING_LENGTH,
|
||||
@"_C_CHARPTR overruns memory");
|
||||
}
|
||||
|
||||
|
||||
/* For debugging */
|
||||
|
||||
static int debug_binary_coder = 0;
|
||||
|
||||
+ setDebugging: (BOOL)f
|
||||
{
|
||||
debug_binary_coder = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ debugStderrCoder
|
||||
{
|
||||
static id c = nil;
|
||||
|
||||
if (!c)
|
||||
c = [[TextCStream alloc]
|
||||
initForWritingToStream: [StdioStream standardError]];
|
||||
return c;
|
||||
}
|
||||
|
||||
/* This is the designated initializer for reading. */
|
||||
- _initForReadingFromPostSignatureStream: (id <Streaming>)s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[super _initForReadingFromPostSignatureStream: s
|
||||
withFormatVersion: version];
|
||||
if (version > PRE_SIZEOF_PREFIX_FORMAT_VERSION)
|
||||
{
|
||||
/* Read the C-type sizes to expect. */
|
||||
[s readByte: &_sizeof_long];
|
||||
[s readByte: &_sizeof_int];
|
||||
[s readByte: &_sizeof_short];
|
||||
[s readByte: &_sizeof_char];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This is a designated initializer for writing. */
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[super initForWritingToStream: s
|
||||
withFormatVersion: version];
|
||||
if (version > PRE_SIZEOF_PREFIX_FORMAT_VERSION)
|
||||
{
|
||||
[s writeByte: sizeof (long)];
|
||||
[s writeByte: sizeof (int)];
|
||||
[s writeByte: sizeof (short)];
|
||||
[s writeByte: sizeof (char)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (NSString*) name
|
||||
{
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
/* Make sure we're not being asked to encode an "ObjC" type. */
|
||||
NSAssert(*type != '@', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to encode an \"ObjC\" type");
|
||||
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType: type
|
||||
at: d
|
||||
withName: name];
|
||||
}
|
||||
|
||||
[stream writeByte: *type];
|
||||
|
||||
#define WRITE_SIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
_TYPE tmp; \
|
||||
char buffer[1+sizeof(_TYPE)]; \
|
||||
buffer[0] = sizeof (_TYPE); \
|
||||
if (*(_TYPE*)_PTR < 0) \
|
||||
{ \
|
||||
buffer[0] |= 0x80; \
|
||||
tmp = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
||||
memcpy (buffer+1, &tmp, sizeof(_TYPE)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tmp = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
memcpy (buffer+1, &tmp, sizeof(_TYPE)); \
|
||||
} \
|
||||
[stream writeBytes: buffer length: 1+sizeof(_TYPE)]; \
|
||||
}
|
||||
|
||||
#define WRITE_SIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
_TYPE tmp; \
|
||||
char buffer[sizeof(_TYPE)]; \
|
||||
if (*(_TYPE*)_PTR < 0) \
|
||||
{ \
|
||||
tmp = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
||||
memcpy (buffer, &tmp, sizeof(_TYPE)); \
|
||||
NSAssert(!(buffer[0] & 0x80), @"high bit set"); \
|
||||
buffer[0] |= 0x80; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tmp = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
memcpy (buffer, &tmp, sizeof(_TYPE)); \
|
||||
} \
|
||||
[stream writeBytes: buffer length: sizeof(_TYPE)]; \
|
||||
}
|
||||
|
||||
#define WRITE_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
WRITE_SIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
WRITE_SIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
#define READ_SIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
char sign, size; \
|
||||
[stream readByte: &size]; \
|
||||
sign = size & 0x80; \
|
||||
size &= ~0x80; \
|
||||
{ \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size");\
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
if (sign) \
|
||||
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_SIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
int size = _sizeof_ ## _TYPE; \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
int sign; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
/* xxx Remove this next requirement eventually */ \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size"); \
|
||||
sign = buffer[0] & 0x80; \
|
||||
buffer[0] &= ~0x80; \
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
if (sign) \
|
||||
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
||||
}
|
||||
|
||||
#define READ_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
READ_SIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
READ_SIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
/* Reading and writing unsigned scalar types. */
|
||||
|
||||
#define WRITE_UNSIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
_TYPE tmp; \
|
||||
char buffer[1+sizeof(_TYPE)]; \
|
||||
buffer[0] = sizeof (_TYPE); \
|
||||
tmp = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
memcpy (buffer+1, &tmp, sizeof(_TYPE)); \
|
||||
[stream writeBytes: buffer length: (1+sizeof(_TYPE))]; \
|
||||
}
|
||||
|
||||
#define WRITE_UNSIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
unsigned _TYPE tmp; \
|
||||
char buffer[sizeof(unsigned _TYPE)]; \
|
||||
tmp = _CONV_FUNC (*(unsigned _TYPE*)_PTR); \
|
||||
memcpy (buffer, &tmp, sizeof(unsigned _TYPE)); \
|
||||
[stream writeBytes: buffer length: (sizeof(unsigned _TYPE))]; \
|
||||
}
|
||||
|
||||
#define WRITE_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
WRITE_UNSIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
WRITE_UNSIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
char size; \
|
||||
[stream readByte: &size]; \
|
||||
{ \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size");\
|
||||
*(_TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(_TYPE*)buffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
int size = _sizeof_ ## _TYPE; \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
/* xxx Remove this next requirement eventually */ \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size"); \
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
READ_UNSIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
READ_UNSIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
unsigned length = strlen (*(char**)d);
|
||||
unsigned nlength;
|
||||
nlength = NSSwapHostIntToBig (length);
|
||||
[stream writeBytes: &nlength
|
||||
length: NUM_BYTES_STRING_LENGTH];
|
||||
[stream writeBytes: *(char**)d
|
||||
length: length];
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream writeByte: *(unsigned char*)d];
|
||||
break;
|
||||
|
||||
/* Reading and writing signed scalar types. */
|
||||
|
||||
case _C_SHT:
|
||||
WRITE_SIGNED_TYPE (d, short, NSSwapHostShortToBig);
|
||||
break;
|
||||
case _C_USHT:
|
||||
WRITE_UNSIGNED_TYPE (d, short, NSSwapHostShortToBig);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
WRITE_SIGNED_TYPE (d, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
case _C_UINT:
|
||||
WRITE_UNSIGNED_TYPE (d, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
WRITE_SIGNED_TYPE (d, long, NSSwapHostLongToBig);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
WRITE_UNSIGNED_TYPE (d, long, NSSwapHostLongToBig);
|
||||
break;
|
||||
|
||||
/* xxx The handling of floats and doubles could be improved.
|
||||
e.g. I should account for varying sizeof(int) vs sizeof(double). */
|
||||
|
||||
case _C_FLT:
|
||||
{
|
||||
float fvalue;
|
||||
double value;
|
||||
int exponent, mantissa;
|
||||
short exponent_encoded;
|
||||
|
||||
memcpy (&fvalue, d, sizeof (float));
|
||||
value = fvalue;
|
||||
/* Get the exponent */
|
||||
value = frexp (value, &exponent);
|
||||
exponent_encoded = exponent;
|
||||
NSParameterAssert (exponent_encoded == exponent);
|
||||
/* Get the mantissa. */
|
||||
value *= FLOAT_FACTOR;
|
||||
mantissa = value;
|
||||
NSAssert (value - mantissa == 0,
|
||||
@"mantissa and value should be the same");
|
||||
/* Encode the value as its two integer components. */
|
||||
WRITE_SIGNED_TYPE (&exponent_encoded, short, NSSwapHostShortToBig);
|
||||
WRITE_SIGNED_TYPE (&mantissa, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_DBL:
|
||||
{
|
||||
double value;
|
||||
int exponent, mantissa1, mantissa2;
|
||||
short exponent_encoded;
|
||||
|
||||
memcpy (&value, d, sizeof (double));
|
||||
/* Get the exponent */
|
||||
value = frexp (value, &exponent);
|
||||
exponent_encoded = exponent;
|
||||
NSParameterAssert (exponent_encoded == exponent);
|
||||
/* Get the first part of the mantissa. */
|
||||
value *= FLOAT_FACTOR;
|
||||
mantissa1 = value;
|
||||
value -= mantissa1;
|
||||
value *= FLOAT_FACTOR;
|
||||
mantissa2 = value;
|
||||
NSAssert (value - mantissa2 == 0,
|
||||
@"mantissa2 and value should be the same");
|
||||
/* Encode the value as its three integer components. */
|
||||
WRITE_SIGNED_TYPE (&exponent_encoded, short, NSSwapHostShortToBig);
|
||||
WRITE_SIGNED_TYPE (&mantissa1, int, NSSwapHostIntToBig);
|
||||
WRITE_SIGNED_TYPE (&mantissa2, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi (type+1); /* xxx why +1 ? */
|
||||
int offset;
|
||||
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
while (len-- > 0)
|
||||
{
|
||||
/* Change this so we don't re-write type info every time. */
|
||||
/* xxx We should be able to encode arrays "ObjC" types also! */
|
||||
[self encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"array component"];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
[self encodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
/* xxx We should be able to encode structs "ObjC" types also! */
|
||||
[self encodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:@"structure component"];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
[self encodeUnindent];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Unrecognized type %s", type];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
char encoded_type;
|
||||
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to decode an \"ObjC\" type");
|
||||
|
||||
[stream readByte: &encoded_type];
|
||||
if (encoded_type != *type
|
||||
&& !((encoded_type=='c' || encoded_type=='C')
|
||||
&& (*type=='c' || *type=='C')))
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Expected type \"%c\", got type \"%c\"",
|
||||
*type, encoded_type];
|
||||
|
||||
switch (encoded_type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
unsigned length;
|
||||
unsigned read_count;
|
||||
read_count = [stream readBytes: &length
|
||||
length: NUM_BYTES_STRING_LENGTH];
|
||||
NSAssert2 (read_count == NUM_BYTES_STRING_LENGTH,
|
||||
@"expected %d bytes of input, got %d",
|
||||
NUM_BYTES_STRING_LENGTH,read_count);
|
||||
length = NSSwapBigIntToHost (length);
|
||||
OBJC_MALLOC (*(char**)d, char, length+1);
|
||||
read_count = [stream readBytes: *(char**)d
|
||||
length: length];
|
||||
NSAssert2 (read_count == length,
|
||||
@"expected %d bytes of input, got %d",length,read_count);
|
||||
(*(char**)d)[length] = '\0';
|
||||
/* Autorelease the newly malloc'ed pointer? Grep for (*objc_free)
|
||||
to see the places the may have to be changed
|
||||
[NSData dataWithBytesNoCopy: *(void**)d length: length+1]; */
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream readByte: (unsigned char*)d];
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
READ_SIGNED_TYPE (d, short, NSSwapBigShortToHost);
|
||||
break;
|
||||
case _C_USHT:
|
||||
READ_UNSIGNED_TYPE (d, short, NSSwapBigShortToHost);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
READ_SIGNED_TYPE (d, int, NSSwapBigIntToHost);
|
||||
break;
|
||||
case _C_UINT:
|
||||
READ_UNSIGNED_TYPE (d, int, NSSwapBigIntToHost);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
READ_SIGNED_TYPE (d, long, NSSwapBigLongToHost);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
READ_UNSIGNED_TYPE (d, long, NSSwapBigLongToHost);
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
{
|
||||
short exponent;
|
||||
int mantissa;
|
||||
double value;
|
||||
float fvalue;
|
||||
|
||||
/* Decode the exponent and mantissa. */
|
||||
READ_SIGNED_TYPE (&exponent, short, NSSwapBigShortToHost);
|
||||
READ_SIGNED_TYPE (&mantissa, int, NSSwapBigIntToHost);
|
||||
/* Assemble them into a double */
|
||||
value = mantissa / FLOAT_FACTOR;
|
||||
value = ldexp (value, exponent);
|
||||
/* Put the double into the requested memory location as a float */
|
||||
fvalue = value;
|
||||
memcpy (d, &fvalue, sizeof (float));
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_DBL:
|
||||
{
|
||||
short exponent;
|
||||
int mantissa1, mantissa2;
|
||||
double value;
|
||||
|
||||
/* Decode the exponent and the two pieces of the mantissa. */
|
||||
READ_SIGNED_TYPE (&exponent, short, NSSwapBigShortToHost);
|
||||
READ_SIGNED_TYPE (&mantissa1, int, NSSwapBigIntToHost);
|
||||
READ_SIGNED_TYPE (&mantissa2, int, NSSwapBigIntToHost);
|
||||
/* Assemble them into a double */
|
||||
value = ((mantissa2 / FLOAT_FACTOR) + mantissa1) / FLOAT_FACTOR;
|
||||
value = ldexp (value, exponent);
|
||||
/* Put the double into the requested memory location. */
|
||||
memcpy (d, &value, sizeof (double));
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||
int len = atoi(type+1);
|
||||
int offset;
|
||||
[self decodeName:namePtr];
|
||||
[self decodeIndent];
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
[self decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
[self decodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space just like char* ? No. */
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
const char *save_type = type;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
[self decodeName:namePtr];
|
||||
[self decodeIndent]; /* xxx insert [self decodeName:] */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self decodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:namePtr];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
type = save_type;
|
||||
[self decodeUnindent];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Unrecognized Type %s", type];
|
||||
}
|
||||
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"decoding unnamed"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
|
||||
|
||||
/* Encoding and decoding names. */
|
||||
|
||||
- (void) encodeName: (NSString*) name
|
||||
{
|
||||
if (debug_binary_coder)
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeName:name];
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *)n
|
||||
{
|
||||
#if 1
|
||||
if (n)
|
||||
*n = nil;
|
||||
#else
|
||||
if (n)
|
||||
*n = [[[NSString alloc] init] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/* Interface for Objective-C BinaryTree 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Binary Tree.
|
||||
Base class for smarter binary trees.
|
||||
*/
|
||||
|
||||
#ifndef __BinaryTree_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __BinaryTree_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/IndexedCollection.h>
|
||||
|
||||
/* The <BinaryTreeComprising> protocol defines the interface to an object
|
||||
that may be an element in a BinaryTree.
|
||||
*/
|
||||
@protocol BinaryTreeComprising <NSObject>
|
||||
- leftNode;
|
||||
- rightNode;
|
||||
- parentNode;
|
||||
- (void) setLeftNode: (id <BinaryTreeComprising>)aNode;
|
||||
- (void) setRightNode: (id <BinaryTreeComprising>)aNode;
|
||||
- (void) setParentNode: (id <BinaryTreeComprising>)aNode;
|
||||
- binaryTree;
|
||||
- (void) setBinaryTree: anObject;
|
||||
@end
|
||||
|
||||
#define NODE_IS_RIGHTCHILD(NODE) (NODE == [[NODE parentNode] rightNode])
|
||||
#define NODE_IS_LEFTCHILD(NODE) (NODE == [[NODE parentNode] leftNode])
|
||||
|
||||
@interface BinaryTree : IndexedCollection
|
||||
{
|
||||
unsigned int _count;
|
||||
id _contents_root;
|
||||
}
|
||||
|
||||
- nilNode;
|
||||
- rootNode;
|
||||
|
||||
- leftmostNodeFromNode: aNode;
|
||||
- rightmostNodeFromNode: aNode;
|
||||
|
||||
- (unsigned) depthOfNode: aNode;
|
||||
- (unsigned) heightOfNode: aNode;
|
||||
|
||||
- (unsigned) nodeCountUnderNode: aNode;
|
||||
|
||||
- leftRotateAroundNode: aNode;
|
||||
- rightRotateAroundNode: aNode;
|
||||
|
||||
- binaryTreePrintForDebugger;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif /* __BinaryTree_h_GNUSTEP_BASE_INCLUDE */
|
607
Old/BinaryTree.m
607
Old/BinaryTree.m
|
@ -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,40 +0,0 @@
|
|||
/* Interface 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>
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __BinaryTreeNode_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __BinaryTreeNode_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/BinaryTree.h>
|
||||
#include <base/Coding.h>
|
||||
|
||||
@interface BinaryTreeNode : NSObject <BinaryTreeComprising>
|
||||
{
|
||||
id _left;
|
||||
id _right;
|
||||
id _parent;
|
||||
id _binary_tree;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif /* __BinaryTreeNode_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,62 +0,0 @@
|
|||
/* Interface for GNU Objective-C stream object for use in archiving
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 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.
|
||||
*/
|
||||
|
||||
#ifndef __CStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStreaming.h>
|
||||
|
||||
@interface CStream : Stream <CStreaming>
|
||||
{
|
||||
Stream *stream;
|
||||
int format_version;
|
||||
int indentation;
|
||||
}
|
||||
|
||||
/* These are the standard ways to create a new CStream from a Stream
|
||||
that is open for reading.
|
||||
It reads the CStream signature at the beginning of the file, and
|
||||
automatically creates the appropriate subclass of CStream with
|
||||
the correct format version. */
|
||||
+ cStreamReadingFromFile: (NSString*) filename;
|
||||
+ cStreamReadingFromStream: (id <Streaming>) stream;
|
||||
|
||||
/* These are standard ways to create a new CStream with a Stream
|
||||
that is open for writing. */
|
||||
- initForWritingToFile: (NSString*) filename;
|
||||
- initForWritingToStream: (id <Streaming>) stream;
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version;
|
||||
|
||||
+ cStreamWritingToStream: (id <Streaming>) stream;
|
||||
+ cStreamWritingToFile: (NSString*) filename;
|
||||
|
||||
/* This is the designated initializer for reading. Don't call it yourself. */
|
||||
- _initForReadingFromPostSignatureStream: (id <Streaming>)s
|
||||
withFormatVersion: (int)version;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __CStream_h_GNUSTEP_BASE_INCLUDE */
|
287
Old/CStream.m
287
Old/CStream.m
|
@ -1,287 +0,0 @@
|
|||
/* Implementation of GNU Objective-C class for streaming C types and indentatn
|
||||
Copyright (C) 1994, 1995, 1996, 1997 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/preface.h>
|
||||
#include <base/CStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/CoderPrivate.h> /* for SIGNATURE_FORMAT_STRING */
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
id CStreamSignatureMalformedException = @"CStreamSignatureMalformedException";
|
||||
id CStreamSignatureMismatchException = @"CStreamSignatureMismatchException";
|
||||
|
||||
@implementation CStream
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name;
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) decodeValueOfCType: (const char*) type
|
||||
at: (void*) d
|
||||
withName: (NSString* *) namePtr;
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
|
||||
/* Signature methods. */
|
||||
|
||||
- (void) writeSignature
|
||||
{
|
||||
/* Careful: the string should not contain newlines. */
|
||||
[stream writeFormat: SIGNATURE_FORMAT_STRING,
|
||||
STRINGIFY(GNUSTEP_BASE_PACKAGE_NAME),
|
||||
GNUSTEP_BASE_MAJOR_VERSION,
|
||||
GNUSTEP_BASE_MINOR_VERSION,
|
||||
GNUSTEP_BASE_SUBMINOR_VERSION,
|
||||
object_get_class_name(self),
|
||||
format_version];
|
||||
}
|
||||
|
||||
+ (void) readSignatureFromStream: s
|
||||
getClassname: (char *) name
|
||||
formatVersion: (int*) version
|
||||
{
|
||||
int got;
|
||||
char package_name[64];
|
||||
int major_version;
|
||||
int minor_version;
|
||||
int subminor_version;
|
||||
|
||||
got = [s readFormat: SIGNATURE_FORMAT_STRING,
|
||||
&(package_name[0]),
|
||||
&major_version,
|
||||
&minor_version,
|
||||
&subminor_version,
|
||||
name,
|
||||
version];
|
||||
if (got != 6)
|
||||
[NSException raise:CStreamSignatureMalformedException
|
||||
format: @"CStream found a malformed signature"];
|
||||
}
|
||||
|
||||
|
||||
/* Initialization methods */
|
||||
|
||||
/* This is the hidden designated initializer. Do not call it yourself. */
|
||||
- _initWithStream: (id <Streaming>) s
|
||||
formatVersion: (int)version
|
||||
{
|
||||
[super init];
|
||||
[s retain];
|
||||
stream = s;
|
||||
format_version = version;
|
||||
indentation = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This is the designated initializer for reading. */
|
||||
- _initForReadingFromPostSignatureStream: (id <Streaming>)s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[self _initWithStream: s
|
||||
formatVersion: version];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initForReadingFromStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
/* xxx Why this condition? -mccallum */
|
||||
if ([stream streamPosition] != 0)
|
||||
{
|
||||
char name[128]; /* max class name length. */
|
||||
int version;
|
||||
[[self class] readSignatureFromStream: stream
|
||||
getClassname: name
|
||||
formatVersion: &version];
|
||||
if (!strcmp(name, object_get_class_name(self))
|
||||
|| version != format_version)
|
||||
{
|
||||
[NSException raise: CStreamSignatureMismatchException
|
||||
format: @"CStream found a mismatched signature"];
|
||||
}
|
||||
[self _initForReadingFromPostSignatureStream: s
|
||||
withFormatVersion: version];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ cStreamReadingFromStream: (id <Streaming>) s
|
||||
{
|
||||
char name[128]; /* Maximum class name length. */
|
||||
int version;
|
||||
id new_cstream;
|
||||
|
||||
[self readSignatureFromStream: s
|
||||
getClassname: name
|
||||
formatVersion: &version];
|
||||
new_cstream = [[objc_lookup_class(name) alloc]
|
||||
_initForReadingFromPostSignatureStream: s
|
||||
withFormatVersion: version];
|
||||
return [new_cstream autorelease];
|
||||
}
|
||||
|
||||
+ cStreamReadingFromFile: (NSString*) filename
|
||||
{
|
||||
return [self cStreamReadingFromStream:
|
||||
[StdioStream streamWithFilename: filename fmode: "r"]];
|
||||
}
|
||||
|
||||
/* This is a designated initializer for writing. */
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[self _initWithStream: s
|
||||
formatVersion: version];
|
||||
[self writeSignature];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withFormatVersion: [[self class] defaultFormatVersion]];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) file
|
||||
{
|
||||
return [self initForWritingToStream:
|
||||
[StdioStream streamWithFilename: file fmode: "w"]];
|
||||
}
|
||||
|
||||
+ cStreamWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [[[self alloc] initForWritingToStream: s]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
+ cStreamWritingToFile: (NSString*) filename;
|
||||
{
|
||||
return [[[self alloc] initForWritingToFile: filename]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
|
||||
/* Encoding/decoding indentation */
|
||||
|
||||
- (void) encodeWithName: (NSString*) name
|
||||
valuesOfCTypes: (const char *) types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self encodeName: name];
|
||||
va_start (ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self encodeValueOfCType: types
|
||||
at: va_arg(ap, void*)
|
||||
withName: NULL];
|
||||
types = objc_skip_typespec (types);
|
||||
}
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
- (void) decodeWithName: (NSString* *)name
|
||||
valuesOfCTypes: (const char *)types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self decodeName: name];
|
||||
va_start (ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self decodeValueOfCType: types
|
||||
at: va_arg (ap, void*)
|
||||
withName: NULL];
|
||||
types = objc_skip_typespec (types);
|
||||
}
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
- (void) encodeIndent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) encodeUnindent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) decodeIndent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) decodeUnindent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*) n
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *) name
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
|
||||
/* Access to the underlying stream. */
|
||||
|
||||
- (id <Streaming>) stream
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
/* Deallocation. */
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[stream release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,59 +0,0 @@
|
|||
/* Protocol for GNU Objective C byte streams that can code C types and indentn
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: April 1995
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __CStreaming_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __CStreaming_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Streaming.h>
|
||||
|
||||
@protocol CStreaming <Streaming>
|
||||
|
||||
- (void) encodeValueOfCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name;
|
||||
- (void) decodeValueOfCType: (const char*) type
|
||||
at: (void*) d
|
||||
withName: (NSString* *) namePtr;
|
||||
|
||||
- (void) encodeWithName: (NSString*) name
|
||||
valuesOfCTypes: (const char *) types, ...;
|
||||
- (void) decodeWithName: (NSString* *)name
|
||||
valuesOfCTypes: (const char *)types, ...;
|
||||
|
||||
- (void) encodeName: (NSString*) name;
|
||||
- (void) decodeName: (NSString* *) name;
|
||||
|
||||
- (void) encodeIndent;
|
||||
- (void) decodeIndent;
|
||||
|
||||
- (void) encodeUnindent;
|
||||
- (void) decodeUnindent;
|
||||
|
||||
- (id <Streaming>) stream;
|
||||
|
||||
+ (int) defaultFormatVersion;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __CStreaming_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/* Interface for Objective-C CircularArray collection 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.
|
||||
*/
|
||||
|
||||
#ifndef __CircularArray_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CircularArray_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Array.h>
|
||||
|
||||
@interface CircularArray : Array
|
||||
{
|
||||
@public
|
||||
unsigned int _start_index;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __CircularArray_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,74 +0,0 @@
|
|||
/* CircularArray definitions for the use of subclass implementations
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __CircularArrayPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CircularArrayPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/ArrayPrivate.h>
|
||||
|
||||
#define CIRCULAR_TO_BASIC(INDEX) \
|
||||
((INDEX + self->_start_index) % self->_capacity)
|
||||
|
||||
#define BASIC_TO_CIRCULAR(INDEX) \
|
||||
((INDEX + self->_capacity - self->_start_index) % self->_capacity)
|
||||
|
||||
#define NEXT_CIRCULAR_INDEX(INDEX) \
|
||||
((INDEX + 1) % self->_capacity)
|
||||
|
||||
#define PREV_CIRCULAR_INDEX(INDEX) \
|
||||
((INDEX + self->_capacity - 1) % self->_capacity)
|
||||
|
||||
static inline void
|
||||
circularMakeHoleAt(CircularArray *self, unsigned basicIndex)
|
||||
{
|
||||
int i;
|
||||
if (self->_start_index && basicIndex > self->_start_index)
|
||||
{
|
||||
for (i = self->_start_index; i < basicIndex; i++)
|
||||
self->_contents_array[i-1] = self->_contents_array[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = CIRCULAR_TO_BASIC(self->_count-1); i >= basicIndex; i--)
|
||||
self->_contents_array[i+1] = self->_contents_array[i];
|
||||
}
|
||||
/* This is never called with _count == 0 */
|
||||
}
|
||||
|
||||
static inline void
|
||||
circularFillHoleAt(CircularArray *self, unsigned basicIndex)
|
||||
{
|
||||
int i;
|
||||
if (basicIndex > self->_start_index)
|
||||
{
|
||||
for (i = basicIndex; i > self->_start_index; i--)
|
||||
self->_contents_array[i] = self->_contents_array[i-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = basicIndex; i < CIRCULAR_TO_BASIC(self->_count-1); i++)
|
||||
self->_contents_array[i] = self->_contents_array[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __CircularArrayPrivate_h_GNUSTEP_BASE_INCLUDE */
|
141
Old/Coder.h
141
Old/Coder.h
|
@ -1,141 +0,0 @@
|
|||
/* Interface for GNU Objective-C coder object for use serializing
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __Coder_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Coder_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coding.h>
|
||||
#include <base/Streaming.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@class CStream;
|
||||
|
||||
|
||||
/* The root abstract class for archiving */
|
||||
|
||||
@interface Coder : NSObject
|
||||
{
|
||||
@public
|
||||
int format_version;
|
||||
CStream *cstream;
|
||||
NSMapTable *classname_2_classname; /* for changing class names on r/w */
|
||||
int interconnect_stack_height; /* number of nested root objects */
|
||||
}
|
||||
|
||||
+ setDebugging: (BOOL)f;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* An abstract class for writing an archive */
|
||||
|
||||
@interface Encoder : Coder
|
||||
{
|
||||
@public
|
||||
/* xxx in_progress_table should actually be an NSHashTable,
|
||||
but we are working around a bug right now. */
|
||||
NSMapTable *in_progress_table; /* objects begun writing, but !finished */
|
||||
NSMapTable *object_2_xref; /* objects already written */
|
||||
NSMapTable *object_2_fref; /* table of forward references */
|
||||
NSMapTable *const_ptr_2_xref; /* const pointers already written */
|
||||
unsigned fref_counter; /* Keep track of unused fref numbers */
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename;
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withCStreamClass: (Class) cStreamClass;
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class)scc
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion;
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s;
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withCStreamClass: (Class) cStreamClass;
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class) cStreamClass
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion;
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toFile: (NSString*) filename;
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toStream: (id <Streaming>)stream;
|
||||
|
||||
/* Defaults */
|
||||
+ (void) setDefaultStreamClass: sc;
|
||||
+ defaultStreamClass;
|
||||
+ (void) setDefaultCStreamClass: sc;
|
||||
+ defaultCStreamClass;
|
||||
+ (void) setDefaultFormatVersion: (int)fv;
|
||||
+ (int) defaultFormatVersion;
|
||||
|
||||
@end
|
||||
|
||||
@interface Encoder (Encoding) <Encoding>
|
||||
@end
|
||||
|
||||
|
||||
|
||||
/* An abstract class for reading an archive. */
|
||||
|
||||
@interface Decoder : Coder
|
||||
{
|
||||
NSZone *zone; /* zone in which to create objects */
|
||||
id xref_2_object; /* objects already read */
|
||||
id xref_2_object_root; /* objs read since last -startDecodoingI.. */
|
||||
NSMapTable *xref_2_const_ptr; /* const pointers already written */
|
||||
NSMapTable *fref_2_object; /* table of forward references */
|
||||
NSMapTable *address_2_fref; /* table of forward references */
|
||||
}
|
||||
|
||||
/* These are class methods (and not instance methods) because the
|
||||
header of the file or stream determines which subclass of Decoder
|
||||
is created. */
|
||||
|
||||
+ newReadingFromFile: (NSString*) filename;
|
||||
+ newReadingFromStream: (id <Streaming>)stream;
|
||||
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromFile: (NSString*) filename;
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromStream: (id <Streaming>)stream;
|
||||
|
||||
@end
|
||||
|
||||
@interface Decoder (Decoding) <Decoding>
|
||||
@end
|
||||
|
||||
|
||||
/* Extensions to NSObject for encoding and decoding. */
|
||||
|
||||
@interface NSObject (OptionalNewWithCoder)
|
||||
+ newWithCoder: (Coder*)aDecoder;
|
||||
@end
|
||||
|
||||
GS_EXPORT id CoderSignatureMalformedException;
|
||||
|
||||
#endif /* __Coder_h_GNUSTEP_BASE_INCLUDE */
|
310
Old/Coder.m
310
Old/Coder.m
|
@ -1,310 +0,0 @@
|
|||
/* Implementation of GNU Objective-C coder object for use serializing
|
||||
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/preface.h>
|
||||
#include <base/behavior.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/CoderPrivate.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/Coding.h>
|
||||
#include <base/Streaming.h>
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStreaming.h>
|
||||
#include <base/CStream.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <base/BinaryCStream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSGeometry.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSArchiver.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSCoder.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
|
||||
|
||||
/* Exception strings */
|
||||
id CoderSignatureMalformedException = @"CoderSignatureMalformedException";
|
||||
|
||||
#define DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
#define DOING_ROOT_OBJECT (interconnect_stack_height != 0)
|
||||
|
||||
static BOOL debug_coder = NO;
|
||||
|
||||
|
||||
@implementation Coder
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Coder class])
|
||||
behavior_class_add_class (self, [NSCoderNonCore class]);
|
||||
}
|
||||
|
||||
+ setDebugging: (BOOL)f
|
||||
{
|
||||
debug_coder = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/* Initialization. */
|
||||
|
||||
/* This is the designated initializer. But, don't call it yourself;
|
||||
override it and call [super...] in subclasses. */
|
||||
- _initWithCStream: (id <CStreaming>) cs
|
||||
formatVersion: (int) version
|
||||
{
|
||||
format_version = version;
|
||||
cstream = [cs retain];
|
||||
classname_2_classname = NULL;
|
||||
interconnect_stack_height = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
if ([self class] == [Coder class])
|
||||
{
|
||||
[self shouldNotImplement:_cmd];
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
return [super init];
|
||||
}
|
||||
|
||||
/* We must separate the idea of "closing" a coder and "deallocating"
|
||||
a coder because of delays in deallocation due to -autorelease. */
|
||||
- (void) close
|
||||
{
|
||||
[[cstream stream] close];
|
||||
}
|
||||
|
||||
- (BOOL) isClosed
|
||||
{
|
||||
return [[cstream stream] isClosed];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
/* xxx No. [self _finishDecodeRootObject]; */
|
||||
[cstream release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
/* Access to instance variables. */
|
||||
|
||||
- cStream
|
||||
{
|
||||
return cstream;
|
||||
}
|
||||
|
||||
- (int) formatVersion
|
||||
{
|
||||
return format_version;
|
||||
}
|
||||
|
||||
- (void) resetCoder
|
||||
{
|
||||
/* xxx Finish this */
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* To fool ourselves into thinking we can call all these
|
||||
Encoding and Decoding methods. */
|
||||
@interface Coder (Coding) <Encoding, Decoding>
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation Coder (NSCoderCompatibility)
|
||||
|
||||
|
||||
/* The core methods */
|
||||
|
||||
- (void) encodeValueOfObjCType: (const char*)type
|
||||
at: (const void*)address;
|
||||
{
|
||||
[self encodeValueOfObjCType: type at: address withName: NULL];
|
||||
}
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)address
|
||||
{
|
||||
[self decodeValueOfObjCType: type at: address withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeDataObject: (NSData*)data
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- (NSData*) decodeDataObject
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (unsigned int) versionForClassName: (NSString*)className
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Override some methods in NSCoderNonCore */
|
||||
|
||||
- (void) encodeObject: (id)anObject
|
||||
{
|
||||
[self encodeObject: anObject withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeBycopyObject: (id)anObject
|
||||
{
|
||||
[self encodeBycopyObject: anObject withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeByrefObject: (id)anObject
|
||||
{
|
||||
[self encodeByrefObject: anObject withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeConditionalObject: (id)anObject
|
||||
{
|
||||
/* NeXT's implementation handles *forward* references by running
|
||||
through the entire encoding process twice! GNU Coding can handle
|
||||
forward references with only one pass. Therefore, however, GNU
|
||||
Coding cannot return a *forward* reference from -decodeObject, so
|
||||
here, assuming this call to -encodeConditionalObject: is mirrored
|
||||
by a -decodeObject, we don't try to encode *forward*
|
||||
references.
|
||||
|
||||
Note that this means objects that use -encodeConditionalObject:
|
||||
that are encoded in the GNU style might decode a nil where
|
||||
NeXT-style encoded would not. I don't see this a huge problem;
|
||||
at least not as bad as NeXT coding mechanism that actually causes
|
||||
crashes in situations where GNU's does fine. Still, if we wanted
|
||||
to fix this, we might be able to build a kludgy fix based on
|
||||
detecting when this would happen, rewinding the stream to the
|
||||
"conditional" point, and encoding again. Yuck. */
|
||||
|
||||
if ([self _coderReferenceForObject: anObject])
|
||||
[self encodeObject: anObject];
|
||||
else
|
||||
[self encodeObject: nil];
|
||||
}
|
||||
|
||||
- (void) encodeRootObject: (id)rootObject
|
||||
{
|
||||
[self encodeRootObject: rootObject withName: NULL];
|
||||
}
|
||||
|
||||
- (id) decodeObject
|
||||
{
|
||||
/* This won't work for decoding GNU-style forward references because
|
||||
once the GNU decoder finds the object later in the decoding, it
|
||||
will back-patch by storing the id in &o... &o will point to some
|
||||
weird location on the stack! This is why we make the GNU
|
||||
implementation of -encodeConditionalObject: not encode forward
|
||||
references. */
|
||||
id o;
|
||||
[self decodeObjectAt: &o withName: NULL];
|
||||
return [o autorelease];
|
||||
}
|
||||
|
||||
- (unsigned int) systemVersion
|
||||
{
|
||||
return format_version; /* xxx Is this right? */
|
||||
}
|
||||
|
||||
@end /* of (NSCoderCompatibility) */
|
||||
|
||||
|
||||
@implementation Coder (NSArchiverCompatibility)
|
||||
|
||||
|
||||
/* Initializing an archiver */
|
||||
|
||||
- (id) initForWritingWithMutableData: (NSMutableData*)mdata
|
||||
{
|
||||
[(id)self initForWritingToStream: [MemoryStream streamWithData: mdata]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initForReadingWithData: (NSData*)data
|
||||
{
|
||||
id ret = [[self class] newReadingFromStream:
|
||||
[MemoryStream streamWithData:data]];
|
||||
[self release];
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Archiving Data */
|
||||
|
||||
+ (NSData*) archivedDataWithRootObject: (id)rootObject
|
||||
{
|
||||
id d = [[NSMutableData alloc] init];
|
||||
id a = [[NSArchiver alloc] initForWritingWithMutableData:d];
|
||||
[a encodeRootObject:rootObject];
|
||||
return [d autorelease];
|
||||
}
|
||||
|
||||
+ (BOOL) archiveRootObject: (id)rootObject toFile: (NSString*)path
|
||||
{
|
||||
/* xxx fix this return value */
|
||||
id d = [self archivedDataWithRootObject:rootObject];
|
||||
[d writeToFile:path atomically:NO];
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* Getting data from the archiver */
|
||||
|
||||
+ unarchiveObjectWithData: (NSData*) data
|
||||
{
|
||||
return [self decodeObjectWithName: NULL
|
||||
fromStream: [MemoryStream streamWithData:data]];
|
||||
}
|
||||
|
||||
+ unarchiveObjectWithFile: (NSString*) path
|
||||
{
|
||||
return [self decodeObjectWithName: NULL fromFile: path];
|
||||
}
|
||||
|
||||
- (NSMutableData*) archiverData
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,66 +0,0 @@
|
|||
/* Private interface for GNU Objective-C coder object for use serializing
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 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.
|
||||
*/
|
||||
|
||||
#ifndef __CoderPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CoderPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coder.h>
|
||||
#include <base/CStreaming.h>
|
||||
|
||||
enum {
|
||||
CODER_OBJECT_NIL = 0,
|
||||
CODER_OBJECT,
|
||||
CODER_OBJECT_ROOT,
|
||||
CODER_OBJECT_REPEATED,
|
||||
CODER_OBJECT_FORWARD_REFERENCE,
|
||||
CODER_OBJECT_CLASS,
|
||||
CODER_CLASS_NIL,
|
||||
CODER_CLASS,
|
||||
CODER_CLASS_REPEATED,
|
||||
CODER_CONST_PTR_NULL,
|
||||
CODER_CONST_PTR,
|
||||
CODER_CONST_PTR_REPEATED
|
||||
};
|
||||
|
||||
#define DOING_ROOT_OBJECT (interconnect_stack_height != 0)
|
||||
|
||||
@interface Coder (Private)
|
||||
- _initWithCStream: (id <CStreaming>) cs formatVersion: (int) version;
|
||||
- (unsigned) _coderReferenceForObject: anObject;
|
||||
@end
|
||||
|
||||
#define SIGNATURE_FORMAT_STRING \
|
||||
@"GNU Objective C (%s %d.%d.%d) [%s %d]\n"
|
||||
|
||||
#define WRITE_SIGNATURE_FORMAT_ARGS \
|
||||
STRINGIFY(GNUSTEP_BASE_PACKAGE_NAME), \
|
||||
GNUSTEP_BASE_MAJOR_VERSION, \
|
||||
GNUSTEP_BASE_MINOR_VERSION, \
|
||||
GNUSTEP_BASE_SUBMINOR_VERSION, \
|
||||
[self defaultDecoderClassname], \
|
||||
format_version
|
||||
|
||||
|
||||
#define NO_SEL_TYPES "none"
|
||||
|
||||
#endif /* __CoderPrivate_h_GNUSTEP_BASE_INCLUDE */
|
165
Old/Coding.h
165
Old/Coding.h
|
@ -1,165 +0,0 @@
|
|||
/* Protocol for GNU Objective-C objects that can write/read to a coder
|
||||
Copyright (C) 1993, 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.
|
||||
*/
|
||||
|
||||
#ifndef __Coding_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Coding_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
/* #include <base/String.h>
|
||||
xxx Think about trying to get <String> back in types,
|
||||
but now there is a circular dependancy in the include files. */
|
||||
|
||||
@protocol CommonCoding
|
||||
- (BOOL) isDecoding;
|
||||
- (void) close;
|
||||
- (BOOL) isClosed;
|
||||
+ (int) defaultFormatVersion;
|
||||
- cStream;
|
||||
@end
|
||||
|
||||
@protocol Encoding <CommonCoding>
|
||||
|
||||
- (void) encodeValueOfObjCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeWithName: (id /*<String>*/)name
|
||||
valuesOfObjCTypes: (const char *)types, ...;
|
||||
|
||||
- (void) encodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (const void *)d
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) encodeBycopyObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) encodeByrefObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeRootObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) encodeObjectReference: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) startEncodingInterconnectedObjects;
|
||||
- (void) finishEncodingInterconnectedObjects;
|
||||
|
||||
- (void) encodeAtomicString: (const char*)sp
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeClass: aClass;
|
||||
|
||||
/* For inserting a name into a TextCoder stream */
|
||||
- (void) encodeName: (id /*<String>*/) n;
|
||||
|
||||
/* For classes that want to keep track of recursion */
|
||||
- (void) encodeIndent;
|
||||
- (void) encodeUnindent;
|
||||
|
||||
- (void) encodeBytes: (const void *)b
|
||||
count: (unsigned)c
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
@end
|
||||
|
||||
@protocol Decoding <CommonCoding>
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (id /*<String>*/ *) namePtr;
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (id /*<String>*/ *) namePtr;
|
||||
|
||||
- (void) decodeWithName: (id /*<String>*/*)name
|
||||
valuesOfObjCTypes: (const char *) types, ...;
|
||||
|
||||
- (void) decodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (void *)d
|
||||
withName: (id /*<String>*/*)name;
|
||||
|
||||
- (void) decodeObjectAt: (id*)anObjPtr
|
||||
withName: (id /*<String>*/*)name;
|
||||
|
||||
- (void) startDecodingInterconnectedObjects;
|
||||
- (void) finishDecodingInterconnectedObjects;
|
||||
|
||||
- (const char *) decodeAtomicStringWithName: (id /*<String>*/*) name;
|
||||
|
||||
- decodeClass;
|
||||
|
||||
/* For inserting a name into a TextCoder stream */
|
||||
- (void) decodeName: (id /*<String>*/ *)n;
|
||||
|
||||
/* For classes that want to keep track of recursion */
|
||||
- (void) decodeIndent;
|
||||
- (void) decodeUnindent;
|
||||
|
||||
- (void) decodeBytes: (void *)b
|
||||
count: (unsigned)c
|
||||
withName: (id /*<String>*/ *) name;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSObject (SelfCoding)
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)anEncoder;
|
||||
- (id) initWithCoder: (id <Decoding>)aDecoder;
|
||||
+ (id) newWithCoder: (id <Decoding>)aDecoder;
|
||||
|
||||
/* NOTE:
|
||||
|
||||
If the class responds to +newWithCoder Coder will send it for
|
||||
decoding, otherwise Coder will allocate the object itself and send
|
||||
initWithCoder instead.
|
||||
|
||||
+newWithCoder is useful because many classes keep track of their
|
||||
instances and only allow one instance of each configuration. For
|
||||
example, see the designated initializers of SocketPort, Connection,
|
||||
and Proxy.
|
||||
|
||||
Using +new.. instead of -init.. prevents us from having to waste
|
||||
the effort of allocating space for an object to be decoded, then
|
||||
immediately deallocating that space because we're just returning a
|
||||
pre-existing object.
|
||||
|
||||
The newWithCoder and initWithCoder methods must return the decoded
|
||||
object.
|
||||
|
||||
This is not a Protocol, because objects are not required to
|
||||
implement newWithCoder or initWithCoder. They probably want to
|
||||
implement one of them, though.
|
||||
|
||||
-mccallum */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Coding_h_GNUSTEP_BASE_INCLUDE */
|
129
Old/Collecting.h
129
Old/Collecting.h
|
@ -1,129 +0,0 @@
|
|||
/* Protocol for Objective-C objects that hold collections of elements.
|
||||
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.
|
||||
*/
|
||||
|
||||
/* The <Collecting> protocol is root of the collection protocol heirarchy.
|
||||
|
||||
The <Collecting> protocol defines the most general interface to a
|
||||
collection of elements. Elements can be added, removed, and replaced.
|
||||
The contents can be tested, enumerated, and enumerated through various
|
||||
filters. Elements may be objects, or any C type included in the
|
||||
"elt" union given in elt.h, but all elements of a collection must be of
|
||||
the same C type.
|
||||
*/
|
||||
|
||||
#ifndef __Collecting_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Collecting_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coding.h>
|
||||
#include <base/Invoking.h>
|
||||
#include <base/Enumerating.h>
|
||||
|
||||
@protocol ConstantCollecting <NSObject>
|
||||
|
||||
// INITIALIZING;
|
||||
- init;
|
||||
- initWithObjects: (id*)objc count: (unsigned)c;
|
||||
- initWithObjects: firstObject, ...;
|
||||
- initWithObjects: firstObject rest: (va_list)ap;
|
||||
- initWithContentsOf: (id <ConstantCollecting>)aCollection;
|
||||
|
||||
// QUERYING COUNTS;
|
||||
- (BOOL) isEmpty;
|
||||
- (unsigned) count;
|
||||
- (BOOL) containsObject: anObject;
|
||||
- (unsigned) occurrencesOfObject: anObject;
|
||||
|
||||
// COMPARISON WITH OTHER COLLECTIONS;
|
||||
- (BOOL) isSubsetOf: (id <ConstantCollecting>)aCollection;
|
||||
- (BOOL) isDisjointFrom: (id <ConstantCollecting>)aCollection;
|
||||
- (BOOL) isEqual: anObject;
|
||||
- (int) compare: anObject;
|
||||
- (BOOL) contentsEqual: (id <ConstantCollecting>)aCollection;
|
||||
|
||||
// PROPERTIES OF CONTENTS;
|
||||
- (BOOL) trueForAllObjectsByInvoking: (id <Invoking>)anInvocation;
|
||||
- (BOOL) trueForAnyObjectsByInvoking: (id <Invoking>)anInvocation;
|
||||
- detectObjectByInvoking: (id <Invoking>)anInvocation;
|
||||
- maxObject;
|
||||
- minObject;
|
||||
|
||||
// ENUMERATING
|
||||
- (id <Enumerating>) objectEnumerator;
|
||||
- (void) withObjectsInvoke: (id <Invoking>)anInvocation;
|
||||
- (void) withObjectsInvoke: (id <Invoking>)anInvocation whileTrue:(BOOL *)flag;
|
||||
- (void) makeObjectsPerform: (SEL)aSel;
|
||||
- (void) makeObjectsPerform: (SEL)aSel withObject: argObject;
|
||||
|
||||
// FILTERED ENUMERATING;
|
||||
- (void) withObjectsTrueByInvoking: (id <Invoking>)testInvocation
|
||||
invoke: (id <Invoking>)anInvocation;
|
||||
- (void) withObjectsFalseByInvoking: (id <Invoking>)testInvocation
|
||||
invoke: (id <Invoking>)anInvocation;
|
||||
- (void) withObjectsTransformedByInvoking: (id <Invoking>)transInvocation
|
||||
invoke: (id <Invoking>)anInvocation;
|
||||
|
||||
// LOW-LEVEL ENUMERATING;
|
||||
- (void*) newEnumState;
|
||||
- nextObjectWithEnumState: (void**)enumState;
|
||||
- (void) freeEnumState: (void**)enumState;
|
||||
|
||||
// COPYING;
|
||||
- allocCopy;
|
||||
- emptyCopy;
|
||||
- emptyCopyAs: (Class)aCollectionClass;
|
||||
- shallowCopy;
|
||||
- shallowCopyAs: (Class)aCollectionClass;
|
||||
- copyAs: (Class)aCollectionClass;
|
||||
- species;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@protocol Collecting <ConstantCollecting>
|
||||
|
||||
// ADDING;
|
||||
- (void) addObject: newObject;
|
||||
- (void) addObjectIfAbsent: newObject;
|
||||
- (void) addContentsOf: (id <ConstantCollecting>)aCollection;
|
||||
- (void) addContentsIfAbsentOf: (id <ConstantCollecting>)aCollection;
|
||||
- (void) addWithObjects: (id*)objc count: (unsigned)c;
|
||||
- (void) addObjects: firstObject, ...;
|
||||
- (void) addObjects: firstObject rest: (va_list)ap;
|
||||
|
||||
// REMOVING;
|
||||
- (void) removeObject: oldObject;
|
||||
- (void) removeAllOccurrencesOfObject: oldObject;
|
||||
- (void) removeContentsIn: (id <ConstantCollecting>)aCollection;
|
||||
- (void) removeContentsNotIn: (id <ConstantCollecting>)aCollection;
|
||||
- (void) uniqueContents;
|
||||
- (void) empty;
|
||||
|
||||
// REPLACING;
|
||||
- (void) replaceObject: oldObject withObject: newObject;
|
||||
- (void) replaceAllOccurrencesOfObject: oldObject withObject: newObject;
|
||||
|
||||
@end
|
||||
|
||||
#define NO_OBJECT nil
|
||||
|
||||
#endif /* __Collecting_h_GNUSTEP_BASE_INCLUDE */
|
102
Old/Collection.h
102
Old/Collection.h
|
@ -1,102 +0,0 @@
|
|||
/* Interface 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.
|
||||
*/
|
||||
|
||||
/* This is the abstract superclass that satisfies the Collecting
|
||||
protocol, without using any instance variables.
|
||||
*/
|
||||
|
||||
#ifndef __Collection_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Collection_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <base/Collecting.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Coding.h>
|
||||
|
||||
@interface ConstantCollection : NSObject <ConstantCollecting>
|
||||
- printForDebugger; /* This method will disappear later. */
|
||||
@end
|
||||
|
||||
@interface Collection : ConstantCollection <Collecting>
|
||||
@end
|
||||
|
||||
@interface Enumerator : NSObject <Enumerating>
|
||||
{
|
||||
id collection;
|
||||
void *enum_state;
|
||||
}
|
||||
@end
|
||||
|
||||
#define FOR_COLLECTION(ACOLL, ELT) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while ((ELT = [ACOLL nextObjectWithEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_COLLECTION(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
#define FOR_COLLECTION_WHILE_TRUE(ACOLL, ELT, FLAG) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while (FLAG && (ELT = [ACOLL nextObjectWithEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_COLLECTION_WHILE_TRUE(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
/* The only subclassResponsibilities in Collection are:
|
||||
|
||||
addElement:
|
||||
removeElement:
|
||||
getNextElement:withEnumState:
|
||||
empty
|
||||
|
||||
But subclasses may need to override the following for correctness:
|
||||
|
||||
contentType
|
||||
comparisonFunction
|
||||
|
||||
but subclasses will want to override others as well in order to
|
||||
increase efficiency, especially:
|
||||
|
||||
count
|
||||
|
||||
and perhaps:
|
||||
|
||||
includesElement:
|
||||
occurrencesOfElement:
|
||||
uniqueContents
|
||||
withElementsCall:whileTrue:
|
||||
withElementsCall:
|
||||
isEmpty
|
||||
releaseObjects
|
||||
|
||||
*/
|
||||
|
||||
#endif /* __Collection_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
839
Old/Collection.m
839
Old/Collection.m
|
@ -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,50 +0,0 @@
|
|||
/* Collection definitions for the use of subclass implementations only
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __CollectionPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CollectionPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
@interface ConstantCollection (ArchivingHelpers)
|
||||
/* These methods should never be called except in order, and inside
|
||||
-encodeWithCoder: and -decodeWithCoder: */
|
||||
- (void) _encodeCollectionWithCoder: (id <Encoding>)aCoder;
|
||||
- _initCollectionWithCoder: (id <Decoding>)aCoder;
|
||||
- (void) _encodeContentsWithCoder: (id <Encoding>)aCoder;
|
||||
- (void) _decodeContentsWithCoder: (id <Decoding>)aCoder;
|
||||
@end
|
||||
|
||||
@interface ConstantCollection (DeallocationHelpers)
|
||||
|
||||
/* Empty the internals of a collection after the contents have
|
||||
already been released. */
|
||||
- (void) _collectionEmpty;
|
||||
|
||||
- (void) _collectionReleaseContents;
|
||||
|
||||
/* Deallocate the internals of a collection after the contents
|
||||
have already been released. */
|
||||
- (void) _collectionDealloc;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __CollectionPrivate_h_GNUSTEP_BASE_INCLUDE */
|
878
Old/Decoder.m
878
Old/Decoder.m
|
@ -1,878 +0,0 @@
|
|||
/* Abstract class for reading objects from a stream
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996, with core from Coder, created 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/preface.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/CoderPrivate.h>
|
||||
#include <base/CStream.h>
|
||||
#include <base/Stream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
extern BOOL sel_types_match(const char* t1, const char* t2);
|
||||
|
||||
static int debug_coder = 0;
|
||||
|
||||
@implementation Decoder
|
||||
|
||||
static id dummyObject;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
BOOL beenHere = NO;
|
||||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
beenHere = YES;
|
||||
dummyObject = [NSObject new];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Signature Handling. */
|
||||
|
||||
+ (void) readSignatureFromCStream: (id <CStreaming>) cs
|
||||
getClassname: (char *) name
|
||||
formatVersion: (int*) version
|
||||
{
|
||||
int got;
|
||||
char package_name[64];
|
||||
int major_version;
|
||||
int minor_version;
|
||||
int subminor_version;
|
||||
|
||||
/* SIGNATURE_FORMAT_STRING is defined in gnustep/base/CoderPrivate.h */
|
||||
got = [[cs stream] readFormat: SIGNATURE_FORMAT_STRING,
|
||||
&package_name,
|
||||
&major_version,
|
||||
&minor_version,
|
||||
&subminor_version,
|
||||
name, version];
|
||||
if (got != 6)
|
||||
[NSException raise: CoderSignatureMalformedException
|
||||
format: @"Decoder found a malformed signature"];
|
||||
}
|
||||
|
||||
/* This is the designated initializer. */
|
||||
+ newReadingFromStream: (id <Streaming>) stream
|
||||
{
|
||||
id cs = [CStream cStreamReadingFromStream: stream];
|
||||
char name[128]; /* Max classname length. */
|
||||
int version;
|
||||
Decoder *new_coder;
|
||||
|
||||
[self readSignatureFromCStream: cs
|
||||
getClassname: name
|
||||
formatVersion: &version];
|
||||
|
||||
new_coder = [[objc_lookup_class(name) alloc]
|
||||
_initWithCStream: cs
|
||||
formatVersion: version];
|
||||
new_coder->xref_2_object = NULL;
|
||||
new_coder->xref_2_object_root = NULL;
|
||||
new_coder->fref_2_object = NULL;
|
||||
new_coder->address_2_fref = NULL;
|
||||
new_coder->zone = NSDefaultMallocZone();
|
||||
return new_coder;
|
||||
}
|
||||
|
||||
+ newReadingFromFile: (NSString*) filename
|
||||
{
|
||||
return [self newReadingFromStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "r"]];
|
||||
}
|
||||
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromStream: (id <Streaming>)stream;
|
||||
{
|
||||
id c, o;
|
||||
c = [self newReadingFromStream:stream];
|
||||
[c decodeObjectAt: &o withName: name];
|
||||
[c release];
|
||||
return [o autorelease];
|
||||
}
|
||||
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromFile: (NSString*) filename;
|
||||
{
|
||||
return [self decodeObjectWithName: name
|
||||
fromStream:
|
||||
[StdioStream streamWithFilename:filename fmode: "r"]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Functions and methods for keeping cross-references
|
||||
so objects that were already read can be referred to again. */
|
||||
|
||||
/* These _coder... methods may be overriden by subclasses so that
|
||||
cross-references can be kept differently. */
|
||||
|
||||
- (unsigned) _coderCreateReferenceForObject: anObj
|
||||
{
|
||||
if (!xref_2_object)
|
||||
{
|
||||
xref_2_object = [NSMutableArray new];
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
[xref_2_object addObject: dummyObject];
|
||||
}
|
||||
if (debug_coder)
|
||||
fprintf (stderr, "Decoder registering object xref %u\n",
|
||||
[xref_2_object count] - 1);
|
||||
[xref_2_object addObject: anObj]; // xxx but this will retain anObj. NO.
|
||||
/* This return value should be the same as the index of anObj
|
||||
in xref_2_object. */
|
||||
return ([xref_2_object count] - 1);
|
||||
}
|
||||
|
||||
- (void) _coderSubstituteObject: anObj atReference: (unsigned)xref
|
||||
{
|
||||
[xref_2_object replaceObjectAtIndex: xref withObject: anObj];
|
||||
}
|
||||
|
||||
- _coderObjectAtReference: (unsigned)xref
|
||||
{
|
||||
NSParameterAssert (xref_2_object);
|
||||
return [xref_2_object objectAtIndex: xref];
|
||||
}
|
||||
|
||||
|
||||
/* The methods for the root object table. The *root* object table
|
||||
(XREF_2_OBJECT_ROOT) isn't really used for much right now, but it
|
||||
may be in the future. For now, most of the work is don't by
|
||||
XREF_2_OBJECT. */
|
||||
|
||||
- (void) _coderPushRootObjectTable
|
||||
{
|
||||
if (!xref_2_object_root)
|
||||
xref_2_object_root = [NSMutableArray new];
|
||||
}
|
||||
|
||||
- (void) _coderPopRootObjectTable
|
||||
{
|
||||
NSParameterAssert (xref_2_object_root);
|
||||
if (!interconnect_stack_height)
|
||||
{
|
||||
[xref_2_object_root release];
|
||||
xref_2_object_root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) _coderCreateReferenceForInterconnectedObject: anObj
|
||||
{
|
||||
if (!xref_2_object_root)
|
||||
{
|
||||
xref_2_object_root = [NSMutableArray new];
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
[xref_2_object_root addObject: dummyObject];
|
||||
}
|
||||
[xref_2_object_root addObject: anObj];
|
||||
/* This return value should be the same as the index of anObj
|
||||
in xref_2_object_root. */
|
||||
return ([xref_2_object_root count] - 1);
|
||||
}
|
||||
|
||||
- _coderTopRootObjectTable
|
||||
{
|
||||
NSParameterAssert (xref_2_object_root);
|
||||
return xref_2_object_root;
|
||||
}
|
||||
|
||||
|
||||
/* Using the next three methods, subclasses can change the way that
|
||||
const pointers (like SEL, Class, Atomic strings, etc) are
|
||||
archived. */
|
||||
|
||||
- (unsigned) _coderCreateReferenceForConstPtr: (const void*)ptr
|
||||
{
|
||||
unsigned xref;
|
||||
|
||||
if (!xref_2_const_ptr)
|
||||
{
|
||||
xref_2_const_ptr = NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks,
|
||||
0);
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
NSMapInsert (xref_2_const_ptr, (void*)0, (void*)1);
|
||||
}
|
||||
xref = NSCountMapTable (xref_2_const_ptr);
|
||||
NSMapInsert (xref_2_const_ptr, (void*)xref, ptr);
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (const void*) _coderConstPtrAtReference: (unsigned)xref;
|
||||
{
|
||||
NSParameterAssert (xref_2_const_ptr);
|
||||
return NSMapGet (xref_2_const_ptr, (void*)xref);
|
||||
}
|
||||
|
||||
|
||||
/* Here are the methods for forward object references. */
|
||||
|
||||
- (void) _coderPushForwardObjectTable
|
||||
{
|
||||
#if 0
|
||||
if (!fref_stack)
|
||||
fref_stack = o_list_of_void_p ();
|
||||
o_list_append_element (fref_stack, NSCreateMap (...));
|
||||
#endif
|
||||
if (!address_2_fref)
|
||||
address_2_fref = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
|
||||
}
|
||||
|
||||
- (void) _coderPopForwardObjectTable
|
||||
{
|
||||
NSParameterAssert (address_2_fref);
|
||||
if (!interconnect_stack_height)
|
||||
{
|
||||
NSFreeMapTable (address_2_fref);
|
||||
address_2_fref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _coderSatisfyForwardReference: (unsigned)fref withObject: anObj
|
||||
{
|
||||
NSParameterAssert (address_2_fref);
|
||||
if (!fref_2_object)
|
||||
/* xxx Or should this be NSObjectMapValueCallBacks, so we make
|
||||
sure the object doesn't get released before we can resolve
|
||||
references with it? */
|
||||
fref_2_object = NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
/* There should only be one object for each fref. */
|
||||
NSAssert (!NSMapGet (fref_2_object, (void*)fref),
|
||||
@"Should have only been one object for each fref");
|
||||
NSMapInsert (fref_2_object, (void*)fref, anObj);
|
||||
}
|
||||
|
||||
- (void) _coderAssociateForwardReference: (unsigned)fref
|
||||
withObjectAddress: (void*)addr
|
||||
{
|
||||
/* Register ADDR as associated with FREF; later we will put id
|
||||
associated with FREF at ADDR. */
|
||||
NSParameterAssert (address_2_fref);
|
||||
/* There should not be duplicate addresses */
|
||||
NSAssert (!NSMapGet (address_2_fref, addr), @"Duplicate addresses");
|
||||
NSMapInsert (address_2_fref, addr, (void*)fref);
|
||||
}
|
||||
|
||||
- (void) _coderResolveTopForwardReferences
|
||||
{
|
||||
/* Enumerate the forward references and put them at the proper addresses. */
|
||||
NSMapEnumerator me;
|
||||
void *fref;
|
||||
void *addr;
|
||||
|
||||
if (!address_2_fref)
|
||||
return;
|
||||
|
||||
/* Go through all the addresses that are needing to be filled
|
||||
in with forward references, and put the correct object there.
|
||||
If fref_2_object does not contain an object for fref, (i.e. there
|
||||
was no satisfier for the forward reference), put nil there. */
|
||||
me = NSEnumerateMapTable (address_2_fref);
|
||||
while (NSNextMapEnumeratorPair (&me, &addr, &fref))
|
||||
*(id*)addr = (id) NSMapGet (fref_2_object, fref);
|
||||
}
|
||||
|
||||
|
||||
/* This is the Coder's interface to the over-ridable
|
||||
"_coderCreateReferenceForObject" method. Do not override it. It
|
||||
handles the xref_2_object_root. */
|
||||
|
||||
- (unsigned) _coderInternalCreateReferenceForObject: anObj
|
||||
{
|
||||
unsigned xref = [self _coderCreateReferenceForObject: anObj];
|
||||
if (DOING_ROOT_OBJECT)
|
||||
[self _coderCreateReferenceForInterconnectedObject: anObj];
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (void) _coderInternalSubstituteObject: anObj atReference: (unsigned)xref
|
||||
{
|
||||
[self _coderSubstituteObject: anObj atReference: xref];
|
||||
/* xxx If we ever use the root object table, do something with it also. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Method for decoding things. */
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
[cstream decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
}
|
||||
|
||||
- (void) decodeBytes: (void *)b
|
||||
count: (unsigned)c
|
||||
withName: (NSString* *) name
|
||||
{
|
||||
int actual_count;
|
||||
/* xxx Is this what we want?
|
||||
It won't be cleanly readable in TextCStream's. */
|
||||
[cstream decodeName: name];
|
||||
actual_count = [[cstream stream] readBytes: b length: c];
|
||||
NSAssert2 (actual_count == c,
|
||||
@"expected to read %d bytes, read %d bytes",c,actual_count);
|
||||
}
|
||||
|
||||
- (unsigned char) decodeTag
|
||||
{
|
||||
if ([cstream respondsToSelector: @selector(decodeTag)])
|
||||
return [(id)cstream decodeTag];
|
||||
{
|
||||
unsigned char t;
|
||||
[self decodeValueOfCType:@encode(unsigned char)
|
||||
at:&t
|
||||
withName:NULL];
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
- decodeClass
|
||||
{
|
||||
unsigned char tag;
|
||||
char *class_name;
|
||||
int class_version;
|
||||
id ret = Nil;
|
||||
|
||||
[self decodeIndent];
|
||||
tag = [self decodeTag];
|
||||
switch (tag)
|
||||
{
|
||||
case CODER_CLASS_NIL:
|
||||
break;
|
||||
case CODER_CLASS_REPEATED:
|
||||
{
|
||||
unsigned xref;
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: NULL];
|
||||
ret = (id) [self _coderConstPtrAtReference: xref];
|
||||
if (!ret)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"repeated class cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
case CODER_CLASS:
|
||||
{
|
||||
[self decodeValueOfCType: @encode(char*)
|
||||
at: &class_name
|
||||
withName: NULL];
|
||||
[self decodeValueOfCType: @encode(int)
|
||||
at: &class_version
|
||||
withName: NULL];
|
||||
|
||||
/* xxx should do classname substitution,
|
||||
ala decodeClassName:intoClassName: here. */
|
||||
|
||||
ret = objc_lookup_class (class_name);
|
||||
/* Ensure that the [+initialize] method has been called for the
|
||||
class by calling one of it's methods */
|
||||
if (ret != Nil)
|
||||
ret = [ret class];
|
||||
if (ret == Nil)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Couldn't find class `%s'", class_name];
|
||||
if (class_get_version(ret) != class_version)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"Class version mismatch, executable %d != encoded %d",
|
||||
class_get_version(ret), class_version];
|
||||
|
||||
{
|
||||
unsigned xref;
|
||||
xref = [self _coderCreateReferenceForConstPtr: ret];
|
||||
if (debug_coder)
|
||||
fprintf(stderr,
|
||||
"Decoder decoding registered class xref %u\n", xref);
|
||||
}
|
||||
objc_free (class_name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"unrecognized class tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (const char *) decodeAtomicStringWithName: (NSString* *) name
|
||||
{
|
||||
char *s;
|
||||
/* xxx Add repeat-string-ptr checking here */
|
||||
[self notImplemented:_cmd];
|
||||
[self decodeValueOfCType:@encode(char*) at:&s withName:name];
|
||||
return s;
|
||||
}
|
||||
|
||||
- (SEL) decodeSelectorWithName: (NSString* *) name
|
||||
{
|
||||
char tag;
|
||||
SEL ret = NULL;
|
||||
|
||||
[self decodeName:name];
|
||||
[self decodeIndent];
|
||||
tag = [self decodeTag];
|
||||
switch (tag)
|
||||
{
|
||||
case CODER_CONST_PTR_NULL:
|
||||
break;
|
||||
case CODER_CONST_PTR_REPEATED:
|
||||
{
|
||||
unsigned xref;
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: NULL];
|
||||
ret = (SEL) [self _coderConstPtrAtReference: xref];
|
||||
if (!ret)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"repeated selector cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
case CODER_CONST_PTR:
|
||||
{
|
||||
char *sel_name;
|
||||
char *sel_types;
|
||||
|
||||
[self decodeValueOfCType:@encode(char *)
|
||||
at:&sel_name
|
||||
withName:NULL];
|
||||
[self decodeValueOfCType:@encode(char *)
|
||||
at:&sel_types
|
||||
withName:NULL];
|
||||
#if NeXT_runtime
|
||||
ret = sel_getUid(sel_name);
|
||||
#else
|
||||
if (!strcmp(sel_types, NO_SEL_TYPES))
|
||||
ret = sel_get_any_uid(sel_name);
|
||||
else
|
||||
ret = sel_get_typed_uid(sel_name, sel_types);
|
||||
#endif
|
||||
if (!ret)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Could not find selector (%s) with types [%s]",
|
||||
sel_name, sel_types];
|
||||
#if ! NeXT_runtime
|
||||
if (strcmp(sel_types, NO_SEL_TYPES)
|
||||
&& !(sel_types_match(sel_types, ret->sel_types)))
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"ObjC runtime didn't provide SEL with matching type"];
|
||||
#endif
|
||||
{
|
||||
unsigned xref;
|
||||
xref = [self _coderCreateReferenceForConstPtr: ret];
|
||||
if (debug_coder)
|
||||
fprintf(stderr,
|
||||
"Decoder decoding registered sel xref %u\n", xref);
|
||||
}
|
||||
objc_free(sel_name);
|
||||
objc_free(sel_types);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"unrecognized selector tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
- (void) startDecodingInterconnectedObjects
|
||||
{
|
||||
interconnect_stack_height++;
|
||||
[self _coderPushRootObjectTable];
|
||||
[self _coderPushForwardObjectTable];
|
||||
}
|
||||
|
||||
- (void) finishDecodingInterconnectedObjects
|
||||
{
|
||||
NSParameterAssert (interconnect_stack_height);
|
||||
|
||||
/* xxx This might not be the right thing to do; perhaps we should do
|
||||
this finishing up work at the end of each nested call, not just
|
||||
at the end of all nested calls.
|
||||
However, then we might miss some forward references that we could
|
||||
have resolved otherwise. */
|
||||
if (--interconnect_stack_height)
|
||||
return;
|
||||
|
||||
/* xxx fix the use of _coderPopForwardObjectTable and
|
||||
_coderPopRootObjectTable. */
|
||||
|
||||
#if 0 /* Actually, we do this below in -decodeObjectAt:withName: */
|
||||
/* Send "-awakeAfterUsingCoder:" to all the objects that were read */
|
||||
{
|
||||
SEL awake_sel = sel_get_any_uid("awakeAfterUsingCoder:");
|
||||
if (awake_sel)
|
||||
{
|
||||
int i;
|
||||
id table = [self _coderTopRootObjectTable];
|
||||
|
||||
/* Loop through all objects that we decoded by this Decoder */
|
||||
for (i = [table count]-1; i >= 0; i--)
|
||||
{
|
||||
id o = [table objectAtIndex: i];
|
||||
if (__objc_responds_to(o, awake_sel))
|
||||
{
|
||||
replacement_obj =
|
||||
(*objc_msg_lookup(e.id_u,awake_sel))(o, awake_sel, self);
|
||||
/* xxx Make the replacement in the decoder's object tables. */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* resolve object forward references */
|
||||
[self _coderResolveTopForwardReferences];
|
||||
[self _coderPopForwardObjectTable];
|
||||
|
||||
[self _coderPopRootObjectTable];
|
||||
}
|
||||
|
||||
- (void) _decodeRootObjectAt: (id*)ret withName: (NSString* *) name
|
||||
{
|
||||
[self startDecodingInterconnectedObjects];
|
||||
[self decodeObjectAt:ret withName:name];
|
||||
[self finishDecodingInterconnectedObjects];
|
||||
}
|
||||
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CLASS:
|
||||
{
|
||||
[self decodeName:namePtr];
|
||||
*(id*)d = [self decodeClass];
|
||||
break;
|
||||
}
|
||||
case _C_ATOM:
|
||||
*(const char**)d = [self decodeAtomicStringWithName:namePtr];
|
||||
break;
|
||||
case _C_SEL:
|
||||
*(SEL*)d = [self decodeSelectorWithName:namePtr];
|
||||
break;
|
||||
case _C_ID:
|
||||
[self decodeObjectAt:d withName:namePtr];
|
||||
break;
|
||||
default:
|
||||
[self decodeValueOfCType:type at:d withName:namePtr];
|
||||
}
|
||||
/* xxx We need to catch unions and make a sensible error message */
|
||||
}
|
||||
|
||||
- (BOOL) _createReferenceBeforeInit
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* This is the designated (and one-and-only) object decoder */
|
||||
- (void) decodeObjectAt: (id*) anObjPtr withName: (NSString* *) name
|
||||
{
|
||||
unsigned char tag;
|
||||
unsigned fref = 0;
|
||||
id dummy_object;
|
||||
|
||||
/* Sometimes the user wants to decode an object, but doesn't care to
|
||||
have a pointer to it, (LinkedList elements, for example). In
|
||||
this case, the user can pass in NULL for anObjPtr, and all will
|
||||
be safe. */
|
||||
if (!anObjPtr)
|
||||
anObjPtr = &dummy_object;
|
||||
|
||||
[self decodeName:name];
|
||||
[self decodeIndent];
|
||||
tag = [self decodeTag];
|
||||
switch (tag)
|
||||
{
|
||||
case CODER_OBJECT_NIL:
|
||||
*anObjPtr = nil;
|
||||
break;
|
||||
case CODER_OBJECT_CLASS:
|
||||
*anObjPtr = [self decodeClass];
|
||||
break;
|
||||
case CODER_OBJECT_FORWARD_REFERENCE:
|
||||
{
|
||||
if (!DOING_ROOT_OBJECT)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"can't decode forward reference when not decoding "
|
||||
@"a root object"];
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: NULL];
|
||||
/* The user doesn't need the object pointer anyway, don't record
|
||||
it in the table. */
|
||||
if (anObjPtr == &dummy_object)
|
||||
break;
|
||||
[self _coderAssociateForwardReference: fref
|
||||
withObjectAddress: anObjPtr];
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT:
|
||||
{
|
||||
Class object_class;
|
||||
SEL new_sel = sel_get_any_uid ("newWithCoder:");
|
||||
Method* new_method;
|
||||
BOOL create_ref_before_init = [self _createReferenceBeforeInit];
|
||||
/* Initialize this to <0 so we can tell below if it's been set */
|
||||
int xref = -1;
|
||||
|
||||
[self decodeIndent];
|
||||
object_class = [self decodeClass];
|
||||
/* xxx Should change the runtime.
|
||||
class_get_class_method should take the class as its first
|
||||
argument, not the metaclass! */
|
||||
new_method = class_get_class_method(class_get_meta_class(object_class),
|
||||
new_sel);
|
||||
if (new_method && !create_ref_before_init)
|
||||
*anObjPtr = (*(new_method->method_imp))(object_class, new_sel, self);
|
||||
else
|
||||
{
|
||||
SEL init_sel = sel_get_any_uid ("initWithCoder:");
|
||||
Method *init_method =
|
||||
class_get_instance_method (object_class, init_sel);
|
||||
/* xxx Or should I send +alloc? */
|
||||
*anObjPtr = (id) NSAllocateObject (object_class, 0, zone);
|
||||
if (create_ref_before_init)
|
||||
xref = [self _coderInternalCreateReferenceForObject: *anObjPtr];
|
||||
if (init_method)
|
||||
*anObjPtr =
|
||||
(*(init_method->method_imp))(*anObjPtr, init_sel, self);
|
||||
/* xxx else what, error? */
|
||||
}
|
||||
|
||||
/* Send -awakeAfterUsingCoder: */
|
||||
/* xxx Unknown whether -awakeAfterUsingCoder: should be sent here, or
|
||||
when Decoder is deallocated, or after a root object is finished
|
||||
decoding. */
|
||||
/* NOTE: Use of this with the NeXT archiving methods is
|
||||
tricky, because if [*anObj initWithCoder:] creates any
|
||||
objects that references *anObj, and if [*anObj
|
||||
awakeAfterUsingCoder:] replaces itself, then the
|
||||
subobject's references will not be to the replacement.
|
||||
There is no way to magically fix this circular dependancy;
|
||||
users must be aware. We should just make sure we require
|
||||
the same cautions as NeXT's implementation. Note that, with
|
||||
the GNU archiving methods, this problem doesn't occur because
|
||||
we don't register the object until after it has been fully
|
||||
initialized and awakened. */
|
||||
{
|
||||
SEL awake_sel = sel_get_any_uid ("awakeAfterUsingCoder:");
|
||||
IMP awake_imp = objc_msg_lookup (*anObjPtr, awake_sel);
|
||||
id replacement;
|
||||
|
||||
if (awake_imp)
|
||||
{
|
||||
replacement = (*awake_imp) (*anObjPtr, awake_sel, self);
|
||||
if (replacement != *anObjPtr)
|
||||
{
|
||||
if (xref > 0)
|
||||
[self _coderInternalSubstituteObject: replacement
|
||||
atReference: xref];
|
||||
*anObjPtr = replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self decodeUnindent];
|
||||
|
||||
/* If this was a CODER_OBJECT_FORWARD_SATISFIER, then remember it. */
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: NULL];
|
||||
if (fref)
|
||||
{
|
||||
NSAssert (!create_ref_before_init,
|
||||
@"You are trying to decode an object with the non-GNU\n"
|
||||
@"OpenStep-style forward references, but the object's\n"
|
||||
@"decoding mechanism wants to use GNU features.");
|
||||
[self _coderSatisfyForwardReference: fref withObject: *anObjPtr];
|
||||
}
|
||||
|
||||
/* Would get error here with Connection-wide object references
|
||||
because addProxy gets called in +newRemote:connection: */
|
||||
if (!create_ref_before_init)
|
||||
{
|
||||
unsigned xref =
|
||||
[self _coderInternalCreateReferenceForObject: *anObjPtr];
|
||||
if (debug_coder)
|
||||
fprintf(stderr,
|
||||
"Decoder decoding registered class xref %u\n", xref);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT_ROOT:
|
||||
{
|
||||
[self _decodeRootObjectAt: anObjPtr withName: name];
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT_REPEATED:
|
||||
{
|
||||
unsigned xref;
|
||||
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: NULL];
|
||||
*anObjPtr = [[self _coderObjectAtReference: xref] retain];
|
||||
if (!*anObjPtr)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"repeated object cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"unrecognized object tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
}
|
||||
|
||||
|
||||
- (void) decodeWithName: (NSString* *)name
|
||||
valuesOfObjCTypes: (const char *)types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self decodeName:name];
|
||||
va_start(ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self decodeValueOfObjCType:types
|
||||
at:va_arg(ap, void*)
|
||||
withName:NULL];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
- (void) decodeValueOfObjCTypes: (const char *)types
|
||||
at: (void *)d
|
||||
withName: (NSString* *)name
|
||||
{
|
||||
[self decodeName:name];
|
||||
while (*types)
|
||||
{
|
||||
[self decodeValueOfObjCType:types
|
||||
at:d
|
||||
withName:NULL];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (void *)d
|
||||
withName: (NSString* *) name
|
||||
{
|
||||
int i;
|
||||
int offset = objc_sizeof_type(type);
|
||||
char *where = d;
|
||||
|
||||
[self decodeName:name];
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
[self decodeValueOfObjCType:type
|
||||
at:where
|
||||
withName:NULL];
|
||||
where += offset;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeIndent
|
||||
{
|
||||
[cstream decodeIndent];
|
||||
}
|
||||
|
||||
- (void) decodeUnindent
|
||||
{
|
||||
[cstream decodeUnindent];
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *)n
|
||||
{
|
||||
[cstream decodeName: n];
|
||||
}
|
||||
|
||||
|
||||
+ (NSString*) classNameDecodedForArchiveClassName: (NSString*) inArchiveName
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void) decodeClassName: (NSString*) inArchiveName
|
||||
asClassName:(NSString *)trueName
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
|
||||
/* Managing Zones */
|
||||
|
||||
- (NSZone*) objectZone
|
||||
{
|
||||
return zone;
|
||||
}
|
||||
|
||||
- (void) setObjectZone: (NSZone*)z
|
||||
{
|
||||
zone = z;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (xref_2_object) [xref_2_object release];
|
||||
if (xref_2_object_root) [xref_2_object_root release];
|
||||
if (xref_2_const_ptr) NSFreeMapTable (xref_2_const_ptr);
|
||||
if (fref_2_object) NSFreeMapTable (fref_2_object);
|
||||
if (address_2_fref) NSFreeMapTable (address_2_fref);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,74 +0,0 @@
|
|||
/* Interface for Objective-C "collection of delegates" 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.
|
||||
*/
|
||||
|
||||
/* Using this object, a delegator can have an arbitrary number of
|
||||
delegates. Send a message to this object and the message will get
|
||||
forwarded to the delegates on the list. */
|
||||
|
||||
#ifndef __DelegatePool_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __DelegatePool_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Array.h>
|
||||
|
||||
/* Available sending behaviors */
|
||||
enum DelegatePoolSendBehavior {SEND_TO_ALL = 0,
|
||||
SEND_TO_FIRST_RESPONDER,
|
||||
SEND_UNTIL_YES,
|
||||
SEND_UNTIL_NO};
|
||||
|
||||
@interface DelegatePool
|
||||
{
|
||||
struct objc_class *isa;
|
||||
@public
|
||||
unsigned char _send_behavior;
|
||||
Array *_list;
|
||||
BOOL _last_message_had_receivers;
|
||||
}
|
||||
|
||||
// CREATING AND FREEING;
|
||||
+ alloc;
|
||||
+ new;
|
||||
- init;
|
||||
- (void) dealloc;
|
||||
|
||||
// MANIPULATING COLLECTION OF DELEGATES;
|
||||
- (void) delegatePoolAddObject: anObject;
|
||||
- (void) delegatePoolAddObjectIfAbsent: anObject;
|
||||
- (void) delegatePoolRemoveObject: anObject;
|
||||
- (BOOL) delegatePoolIncludesObject: anObject;
|
||||
- delegatePoolCollection;
|
||||
- (unsigned char) delegatePoolSendBehavior;
|
||||
- (void) delegatePoolSetSendBehavior: (unsigned char)b;
|
||||
|
||||
// FOR PASSING ALL OTHER MESSAGES TO DELEGATES;
|
||||
// RETURNS 0 IF NO OBJECTS RESPOND;
|
||||
- forward:(SEL)aSel :(arglist_t)argFrame;
|
||||
|
||||
// FOR FINDING OUT IF ANY OBJECTS IN THE POOL RESPONDED TO THE LAST MSG;
|
||||
/* This method is bad because it won't be thread-safe---it may
|
||||
go away in the future. */
|
||||
- (BOOL) delegatePoolLastMessageHadReceivers;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __DelegatePool_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,40 +0,0 @@
|
|||
/* Interface 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>
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __Dictionary_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Dictionary_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/KeyedCollection.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@interface Dictionary : KeyedCollection
|
||||
{
|
||||
NSMapTable *_contents_hash;
|
||||
}
|
||||
|
||||
- initWithCapacity: (unsigned)aCapacity;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Dictionary_h_GNUSTEP_BASE_INCLUDE */
|
||||
|
209
Old/Dictionary.m
209
Old/Dictionary.m
|
@ -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
|
883
Old/Encoder.m
883
Old/Encoder.m
|
@ -1,883 +0,0 @@
|
|||
/* Abstract class for writing objects to a stream
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996, with core from Coder, created 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/preface.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/CoderPrivate.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/BinaryCStream.h>
|
||||
#include <Foundation/NSArchiver.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
static int default_format_version;
|
||||
static id default_stream_class;
|
||||
static id default_cstream_class;
|
||||
#define DEFAULT_DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
static int debug_coder = 0;
|
||||
|
||||
|
||||
/* xxx For experimentation. The function in objc-api.h doesn't always
|
||||
work for objects; it sometimes returns YES for an instance. */
|
||||
/* But, metaclasses return YES too? */
|
||||
static BOOL
|
||||
my_object_is_class(id object)
|
||||
{
|
||||
if (object != nil
|
||||
#if NeXT_runtime
|
||||
&& CLS_ISMETA(((Class)object)->isa)
|
||||
&& ((Class)object)->isa != ((Class)object)->isa)
|
||||
#else
|
||||
&& CLS_ISMETA(((Class)object)->class_pointer)
|
||||
&& ((Class)object)->class_pointer != ((Class)object)->class_pointer)
|
||||
#endif
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@implementation Encoder
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Encoder class])
|
||||
{
|
||||
/* This code has not yet been ported to machines for which
|
||||
a pointer is not the same size as an int. */
|
||||
NSAssert(sizeof(void*) == sizeof(unsigned),
|
||||
@"Pointer and int are different sizes");
|
||||
|
||||
/* Initialize some defaults. */
|
||||
default_stream_class = [MemoryStream class];
|
||||
default_cstream_class = [BinaryCStream class];
|
||||
default_format_version = DEFAULT_DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Default format version, Stream and CStream class handling. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return default_format_version;
|
||||
}
|
||||
|
||||
+ (void) setDefaultFormatVersion: (int)f
|
||||
{
|
||||
default_format_version = f;
|
||||
}
|
||||
|
||||
+ (void) setDefaultCStreamClass: sc
|
||||
{
|
||||
default_cstream_class = sc;
|
||||
}
|
||||
|
||||
+ defaultCStreamClass
|
||||
{
|
||||
return default_cstream_class;
|
||||
}
|
||||
|
||||
+ (void) setDefaultStreamClass: sc
|
||||
{
|
||||
default_stream_class = sc;
|
||||
}
|
||||
|
||||
+ defaultStreamClass
|
||||
{
|
||||
return default_stream_class;
|
||||
}
|
||||
|
||||
/* xxx This method interface may change in the future. */
|
||||
- (const char *) defaultDecoderClassname
|
||||
{
|
||||
return "Unarchiver";
|
||||
}
|
||||
|
||||
|
||||
/* Signature Handling. */
|
||||
|
||||
- (void) writeSignature
|
||||
{
|
||||
/* Careful: the string should not contain newlines. */
|
||||
[[cstream stream] writeFormat: SIGNATURE_FORMAT_STRING,
|
||||
WRITE_SIGNATURE_FORMAT_ARGS];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This is the designated initializer for this class. */
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class) cStreamClass
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion
|
||||
{
|
||||
[super _initWithCStream: [[cStreamClass alloc]
|
||||
initForWritingToStream: s
|
||||
withFormatVersion: cStreamFormatVersion]
|
||||
formatVersion: version];
|
||||
[cstream release];
|
||||
in_progress_table = NULL;
|
||||
object_2_xref = NULL;
|
||||
object_2_fref = NULL;
|
||||
const_ptr_2_xref = NULL;
|
||||
fref_counter = 0;
|
||||
[self writeSignature];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* ..Writing... methods */
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withCStreamClass: (Class) cStreamClass
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withFormatVersion: DEFAULT_DEFAULT_FORMAT_VERSION
|
||||
cStreamClass: cStreamClass
|
||||
cStreamFormatVersion: [cStreamClass defaultFormatVersion]];
|
||||
}
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withCStreamClass: [[self class] defaultCStreamClass]];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class) cStreamClass
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion
|
||||
{
|
||||
return [self initForWritingToStream: [StdioStream
|
||||
streamWithFilename: filename
|
||||
fmode: "w"]
|
||||
withFormatVersion: version
|
||||
cStreamClass: cStreamClass
|
||||
cStreamFormatVersion: cStreamFormatVersion];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withCStreamClass: (Class) cStreamClass
|
||||
{
|
||||
return [self initForWritingToStream: [StdioStream
|
||||
streamWithFilename: filename
|
||||
fmode: "w"]
|
||||
withCStreamClass: cStreamClass];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
{
|
||||
return [self initForWritingToStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
+ newWritingToStream: (id <Streaming>)s
|
||||
{
|
||||
return [[self alloc] initForWritingToStream: s];
|
||||
}
|
||||
|
||||
+ newWritingToFile: (NSString*)filename
|
||||
{
|
||||
return [self newWritingToStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toStream: (id <Streaming>)stream
|
||||
{
|
||||
id c = [[self alloc] initForWritingToStream: stream];
|
||||
[c encodeRootObject: anObject withName: name];
|
||||
[c close];
|
||||
[c release];
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toFile: (NSString*) filename
|
||||
{
|
||||
return [self encodeRootObject: anObject
|
||||
withName: name
|
||||
toStream: [StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
|
||||
/* Functions and methods for keeping cross-references
|
||||
so objects aren't written/read twice. */
|
||||
|
||||
/* These _coder... methods may be overriden by subclasses so that
|
||||
cross-references can be kept differently.
|
||||
over again.
|
||||
*/
|
||||
- (unsigned) _coderCreateReferenceForObject: anObj
|
||||
{
|
||||
unsigned xref;
|
||||
if (!object_2_xref)
|
||||
{
|
||||
object_2_xref =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
}
|
||||
xref = NSCountMapTable (object_2_xref) + 1;
|
||||
NSMapInsert (object_2_xref, anObj, (void*)xref);
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (unsigned) _coderReferenceForObject: anObject
|
||||
{
|
||||
if (object_2_xref)
|
||||
return (unsigned) NSMapGet (object_2_xref, anObject);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Methods for handling constant pointers */
|
||||
/* By overriding the next three methods, subclasses can change the way
|
||||
that const pointers (like SEL, Class, Atomic strings, etc) are
|
||||
archived. */
|
||||
|
||||
- (unsigned) _coderCreateReferenceForConstPtr: (const void*)ptr
|
||||
{
|
||||
unsigned xref;
|
||||
if (!const_ptr_2_xref)
|
||||
const_ptr_2_xref =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
|
||||
xref = NSCountMapTable (const_ptr_2_xref) + 1;
|
||||
NSAssert (! NSMapGet (const_ptr_2_xref, (void*)xref), @"xref already in Map");
|
||||
NSMapInsert (const_ptr_2_xref, ptr, (void*)xref);
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (unsigned) _coderReferenceForConstPtr: (const void*)ptr
|
||||
{
|
||||
if (const_ptr_2_xref)
|
||||
return (unsigned) NSMapGet (const_ptr_2_xref, ptr);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Methods for forward references */
|
||||
|
||||
- (unsigned) _coderCreateForwardReferenceForObject: anObject
|
||||
{
|
||||
unsigned fref;
|
||||
if (!object_2_fref)
|
||||
object_2_fref =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
fref = ++fref_counter;
|
||||
NSAssert ( ! NSMapGet (object_2_fref, anObject), @"anObject already in Map");
|
||||
NSMapInsert (object_2_fref, anObject, (void*)fref);
|
||||
return fref;
|
||||
}
|
||||
|
||||
- (unsigned) _coderForwardReferenceForObject: anObject
|
||||
{
|
||||
/* This method must return 0 if it's not there. */
|
||||
if (!object_2_fref)
|
||||
return 0;
|
||||
return (unsigned) NSMapGet (object_2_fref, anObject);
|
||||
}
|
||||
|
||||
- (void) _coderRemoveForwardReferenceForObject: anObject
|
||||
{
|
||||
NSMapRemove (object_2_fref, anObject);
|
||||
}
|
||||
|
||||
|
||||
/* This is the Coder's interface to the over-ridable
|
||||
"_coderPutObject:atReference" method. Do not override it. It
|
||||
handles the root_object_table. */
|
||||
|
||||
- (void) _coderInternalCreateReferenceForObject: anObj
|
||||
{
|
||||
[self _coderCreateReferenceForObject: anObj];
|
||||
}
|
||||
|
||||
|
||||
/* Handling the in_progress_table. These are called before and after
|
||||
the actual object (not a forward or backward reference) is encoded.
|
||||
|
||||
One of these objects should also call
|
||||
-_coderInternalCreateReferenceForObject:. GNU archiving calls it
|
||||
in the first, in order to force forward references to objects that
|
||||
are in progress; this allows for -initWithCoder: methods that
|
||||
deallocate self, and return another object. OpenStep-style coding
|
||||
calls it in the second, meaning that we never create forward
|
||||
references to objects that are in progress; we encode a backward
|
||||
reference to the in progress object, and assume that it will not
|
||||
change location. */
|
||||
|
||||
- (void) _objectWillBeInProgress: anObj
|
||||
{
|
||||
if (!in_progress_table)
|
||||
in_progress_table =
|
||||
/* This is "NonOwnedPointer", and not "Object", because
|
||||
with "Object" we would get an infinite loop with distributed
|
||||
objects when we try to put a Proxy in in the table, and
|
||||
send the proxy the -hash method. */
|
||||
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
NSMapInsert (in_progress_table, anObj, (void*)1);
|
||||
}
|
||||
|
||||
- (void) _objectNoLongerInProgress: anObj
|
||||
{
|
||||
NSMapRemove (in_progress_table, anObj);
|
||||
/* Register that we have encoded it so that future encoding can
|
||||
do backward references properly. */
|
||||
[self _coderInternalCreateReferenceForObject: anObj];
|
||||
}
|
||||
|
||||
|
||||
/* Method for encoding things. */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[cstream encodeValueOfCType:type
|
||||
at:d
|
||||
withName:name];
|
||||
}
|
||||
|
||||
- (void) encodeBytes: (const void *)b
|
||||
count: (unsigned)c
|
||||
withName: (NSString*)name
|
||||
{
|
||||
/* xxx Is this what we want?
|
||||
It won't be cleanly readable in TextCStream's. */
|
||||
[cstream encodeName: name];
|
||||
[[cstream stream] writeBytes: b length: c];
|
||||
}
|
||||
|
||||
|
||||
- (void) encodeTag: (unsigned char)t
|
||||
{
|
||||
if ([cstream respondsToSelector: @selector(encodeTag:)])
|
||||
[(id)cstream encodeTag:t];
|
||||
else
|
||||
[self encodeValueOfCType:@encode(unsigned char)
|
||||
at:&t
|
||||
withName:@"Coder tag"];
|
||||
}
|
||||
|
||||
- (void) encodeClass: aClass
|
||||
{
|
||||
[self encodeIndent];
|
||||
if (aClass == Nil)
|
||||
{
|
||||
[self encodeTag: CODER_CLASS_NIL];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* xxx Perhaps I should do classname substitution here. */
|
||||
const char *class_name = class_get_class_name (aClass);
|
||||
unsigned xref;
|
||||
|
||||
/* Do classname substitution, ala encodeClassName:intoClassName */
|
||||
if (classname_2_classname)
|
||||
{
|
||||
char *subst_class_name = NSMapGet (classname_2_classname,
|
||||
class_name);
|
||||
if (subst_class_name)
|
||||
{
|
||||
class_name = subst_class_name;
|
||||
aClass = objc_lookup_class (class_name);
|
||||
}
|
||||
}
|
||||
|
||||
xref = [self _coderReferenceForConstPtr: aClass];
|
||||
if (xref)
|
||||
{
|
||||
/* It's already been encoded, so just encode the x-reference */
|
||||
[self encodeTag: CODER_CLASS_REPEATED];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: @"Class cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It hasn't been encoded before; encode it. */
|
||||
int class_version = class_get_version (aClass);
|
||||
|
||||
NSAssert (class_name, @"Class doesn't have a name");
|
||||
NSAssert (*class_name, @"Class name is empty");
|
||||
|
||||
[self encodeTag: CODER_CLASS];
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &class_name
|
||||
withName: @"Class name"];
|
||||
[self encodeValueOfCType: @encode(int)
|
||||
at: &class_version
|
||||
withName: @"Class version"];
|
||||
[self _coderCreateReferenceForConstPtr: aClass];
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
return;
|
||||
}
|
||||
|
||||
- (void) encodeAtomicString: (const char*) sp
|
||||
withName: (NSString*) name
|
||||
{
|
||||
/* xxx Add repeat-string-ptr checking here. */
|
||||
[self notImplemented:_cmd];
|
||||
[self encodeValueOfCType:@encode(char*) at:&sp withName:name];
|
||||
}
|
||||
|
||||
- (void) encodeSelector: (SEL)sel withName: (NSString*) name
|
||||
{
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
if (sel == 0)
|
||||
{
|
||||
[self encodeTag: CODER_CONST_PTR_NULL];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned xref = [self _coderReferenceForConstPtr: sel];
|
||||
if (xref)
|
||||
{
|
||||
/* It's already been encoded, so just encode the x-reference */
|
||||
[self encodeTag: CODER_CONST_PTR_REPEATED];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: @"SEL cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *sel_name;
|
||||
const char *sel_types;
|
||||
|
||||
[self encodeTag: CODER_CONST_PTR];
|
||||
|
||||
/* Get the selector name and type. */
|
||||
sel_name = sel_get_name(sel);
|
||||
#if NeXT_runtime
|
||||
sel_types = NO_SEL_TYPES;
|
||||
#else
|
||||
sel_types = sel_get_type(sel);
|
||||
#endif
|
||||
#if 1 /* xxx Yipes,... careful... */
|
||||
/* xxx Think about something like this. */
|
||||
if (!sel_types)
|
||||
sel_types =
|
||||
sel_get_type (sel_get_any_typed_uid (sel_get_name (sel)));
|
||||
#endif
|
||||
if (!sel_name || !*sel_name)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"ObjC runtime didn't provide SEL name"];
|
||||
if (!sel_types || !*sel_types)
|
||||
sel_types = NO_SEL_TYPES;
|
||||
|
||||
[self _coderCreateReferenceForConstPtr: sel];
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &sel_name
|
||||
withName: @"SEL name"];
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &sel_types
|
||||
withName: @"SEL types"];
|
||||
if (debug_coder)
|
||||
fprintf(stderr, "Coder encoding registered sel xref %u\n", xref);
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
return;
|
||||
}
|
||||
|
||||
- (void) encodeValueOfObjCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name
|
||||
{
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CLASS:
|
||||
[self encodeName: name];
|
||||
[self encodeClass: *(id*)d];
|
||||
break;
|
||||
case _C_ATOM:
|
||||
[self encodeAtomicString: *(char**)d withName: name];
|
||||
break;
|
||||
case _C_SEL:
|
||||
{
|
||||
[self encodeSelector: *(SEL*)d withName: name];
|
||||
break;
|
||||
}
|
||||
case _C_ID:
|
||||
[self encodeObject: *(id*)d withName: name];
|
||||
break;
|
||||
default:
|
||||
[self encodeValueOfCType:type at:d withName:name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Methods for handling interconnected objects */
|
||||
|
||||
- (void) startEncodingInterconnectedObjects
|
||||
{
|
||||
interconnect_stack_height++;
|
||||
}
|
||||
|
||||
- (void) finishEncodingInterconnectedObjects
|
||||
{
|
||||
/* xxx Perhaps we should look at the forward references and
|
||||
encode here any forward-referenced objects that haven't been
|
||||
encoded yet. No---the current behavior implements NeXT's
|
||||
-encodeConditionalObject: */
|
||||
NSParameterAssert (interconnect_stack_height);
|
||||
interconnect_stack_height--;
|
||||
}
|
||||
|
||||
/* NOTE: Unlike NeXT's, this *can* be called recursively */
|
||||
- (void) encodeRootObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self encodeName: @"Root Object"];
|
||||
[self encodeIndent];
|
||||
[self encodeTag: CODER_OBJECT_ROOT];
|
||||
[self startEncodingInterconnectedObjects];
|
||||
[self encodeObject: anObj withName: name];
|
||||
[self finishEncodingInterconnectedObjects];
|
||||
[self encodeUnindent];
|
||||
}
|
||||
|
||||
|
||||
/* These next three methods are the designated coder methods called when
|
||||
we've determined that the object has not already been
|
||||
encoded---we're not simply going to encode a cross-reference number
|
||||
to the object, we're actually going to encode an object (either a
|
||||
proxy to the object or the object itself).
|
||||
|
||||
NSPortCoder overrides _doEncodeObject: in order to implement
|
||||
the encoding of proxies. */
|
||||
|
||||
- (void) _doEncodeBycopyObject: anObj
|
||||
{
|
||||
id encoded_object, encoded_class;
|
||||
|
||||
/* Give the user the opportunity to substitute the class and object */
|
||||
/* xxx Is this the right place for this substitution? */
|
||||
if ([[self class] isKindOf: [NSCoder class]]
|
||||
&& ! [[self class] isKindOf: [NSArchiver class]])
|
||||
/* Make sure we don't do this for the Coder class, because
|
||||
by default Coder should behave like NSArchiver. */
|
||||
{
|
||||
encoded_object = [anObj replacementObjectForCoder: (NSCoder*)self];
|
||||
encoded_class = [encoded_object classForCoder];
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded_object = [anObj replacementObjectForArchiver: (NSArchiver*)self];
|
||||
encoded_class = [encoded_object classForArchiver];
|
||||
}
|
||||
[self encodeClass: encoded_class];
|
||||
/* xxx We should make sure it responds to this selector! */
|
||||
[encoded_object encodeWithCoder: (id)self];
|
||||
}
|
||||
|
||||
/* This method overridden by NSPortCoder */
|
||||
- (void) _doEncodeObject: anObj
|
||||
{
|
||||
[self _doEncodeBycopyObject:anObj];
|
||||
}
|
||||
|
||||
/* This method overridden by NSPortCoder */
|
||||
- (void) _doEncodeByrefObject: anObj
|
||||
{
|
||||
[self _doEncodeObject: anObj];
|
||||
}
|
||||
|
||||
|
||||
/* This is the designated object encoder */
|
||||
- (void) _encodeObject: anObj
|
||||
withName: (NSString*) name
|
||||
isBycopy: (BOOL) bycopy_flag
|
||||
isByref: (BOOL) byref_flag
|
||||
isForwardReference: (BOOL) forward_ref_flag
|
||||
{
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
if (!anObj)
|
||||
{
|
||||
[self encodeTag:CODER_OBJECT_NIL];
|
||||
}
|
||||
else if (my_object_is_class(anObj))
|
||||
{
|
||||
[self encodeTag: CODER_OBJECT_CLASS];
|
||||
[self encodeClass:anObj];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned xref = [self _coderReferenceForObject: anObj];
|
||||
if (xref)
|
||||
{
|
||||
/* It's already been encoded, so just encode the x-reference */
|
||||
[self encodeTag: CODER_OBJECT_REPEATED];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: @"Object cross-reference number"];
|
||||
}
|
||||
else if (forward_ref_flag
|
||||
|| (in_progress_table
|
||||
&& NSMapGet (in_progress_table, anObj)))
|
||||
{
|
||||
unsigned fref;
|
||||
|
||||
/* We are going to encode a forward reference, either because
|
||||
(1) our caller asked for it, or (2) we are in the middle
|
||||
of encoding this object, and haven't finished encoding it yet. */
|
||||
/* Find out if it already has a forward reference number. */
|
||||
fref = [self _coderForwardReferenceForObject: anObj];
|
||||
if (!fref)
|
||||
/* It doesn't, so create one. */
|
||||
fref = [self _coderCreateForwardReferenceForObject: anObj];
|
||||
[self encodeTag: CODER_OBJECT_FORWARD_REFERENCE];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No backward or forward references, we are going to encode
|
||||
the object. */
|
||||
unsigned fref;
|
||||
|
||||
/* Register the object as being in progress of encoding. In
|
||||
OpenStep-style archiving, this method also calls
|
||||
-_coderInternalCreateReferenceForObject:. */
|
||||
[self _objectWillBeInProgress: anObj];
|
||||
|
||||
/* Encode the object. */
|
||||
[self encodeTag: CODER_OBJECT];
|
||||
[self encodeIndent];
|
||||
if (bycopy_flag)
|
||||
[self _doEncodeBycopyObject:anObj];
|
||||
else if (byref_flag)
|
||||
[self _doEncodeByrefObject:anObj];
|
||||
else
|
||||
[self _doEncodeObject:anObj];
|
||||
[self encodeUnindent];
|
||||
|
||||
/* Find out if this object satisfies any forward references,
|
||||
and encode either the forward reference number, or a
|
||||
zero. NOTE: This test is here, and not before the
|
||||
_doEncode.., because the encoding of this object may,
|
||||
itself, generate a "forward reference" to this object,
|
||||
(ala the in_progress_table). That is, we cannot know
|
||||
whether this object satisfies a forward reference until
|
||||
after it has been encoded. */
|
||||
fref = [self _coderForwardReferenceForObject: anObj];
|
||||
if (fref)
|
||||
{
|
||||
/* It does satisfy a forward reference; write the forward
|
||||
reference number, so the decoder can know. */
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
/* Remove it from the forward reference table, since we'll never
|
||||
have another forward reference for this object. */
|
||||
[self _coderRemoveForwardReferenceForObject: anObj];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It does not satisfy any forward references. Let the
|
||||
decoder know this by encoding NULL. Note: in future
|
||||
encoding we may have backward references to this
|
||||
object, but we will never need forward references to
|
||||
this object. */
|
||||
unsigned null_fref = 0;
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &null_fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
}
|
||||
|
||||
/* We're done encoding the object, it's no longer in progress.
|
||||
In GNU-style archiving, this method also calls
|
||||
-_coderInternalCreateReferenceForObject:. */
|
||||
[self _objectNoLongerInProgress: anObj];
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
}
|
||||
|
||||
- (void) encodeObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:NO
|
||||
isByref:NO
|
||||
isForwardReference:NO];
|
||||
}
|
||||
|
||||
|
||||
- (void) encodeBycopyObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:YES
|
||||
isByref:NO
|
||||
isForwardReference:NO];
|
||||
}
|
||||
|
||||
- (void) encodeByrefObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:NO
|
||||
isByref:YES
|
||||
isForwardReference:NO];
|
||||
}
|
||||
|
||||
- (void) encodeObjectReference: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:NO
|
||||
isByref:NO
|
||||
isForwardReference:YES];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void) encodeWithName: (NSString*)name
|
||||
valuesOfObjCTypes: (const char *)types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self encodeName:name];
|
||||
va_start(ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self encodeValueOfObjCType:types
|
||||
at:va_arg(ap, void*)
|
||||
withName:@"Encoded Types Component"];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
- (void) encodeValueOfObjCTypes: (const char *)types
|
||||
at: (const void *)d
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self encodeName:name];
|
||||
while (*types)
|
||||
{
|
||||
[self encodeValueOfObjCType:types
|
||||
at:d
|
||||
withName:@"Encoded Types Component"];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) encodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (const void *)d
|
||||
withName: (NSString*)name
|
||||
{
|
||||
int i;
|
||||
int offset = objc_sizeof_type(type);
|
||||
const char *where = d;
|
||||
|
||||
[self encodeName:name];
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
[self encodeValueOfObjCType:type
|
||||
at:where
|
||||
withName:@"Encoded Array Component"];
|
||||
where += offset;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) encodeIndent
|
||||
{
|
||||
[cstream encodeIndent];
|
||||
}
|
||||
|
||||
- (void) encodeUnindent
|
||||
{
|
||||
[cstream encodeUnindent];
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*)n
|
||||
{
|
||||
[cstream encodeName: n];
|
||||
}
|
||||
|
||||
|
||||
/* Substituting Classes */
|
||||
|
||||
- (NSString*) classNameEncodedForTrueClassName: (NSString*) trueName
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
|
||||
#if 0
|
||||
if (classname_2_classname)
|
||||
return NSMapGet (classname_2_classname, [trueName cString]);
|
||||
return trueName;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) encodeClassName: (NSString*) trueName
|
||||
intoClassName: (NSString*) inArchiveName
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
|
||||
#if 0
|
||||
/* The table should hold char*'s, not id's. */
|
||||
if (!classname_2_classname)
|
||||
classname_2_classname =
|
||||
NSCreateMapTable (NSObjectsMapKeyCallBacks,
|
||||
NSObjectsMapValueCallBacks, 0);
|
||||
NSMapInsert (classname_2_classname, trueName, inArchiveName);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (in_progress_table) NSFreeMapTable (in_progress_table);
|
||||
if (object_2_xref) NSFreeMapTable (object_2_xref);
|
||||
if (object_2_fref) NSFreeMapTable (object_2_fref);
|
||||
if (const_ptr_2_xref) NSFreeMapTable (const_ptr_2_xref);
|
||||
if (classname_2_classname) NSFreeMapTable (classname_2_classname);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,36 +0,0 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 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.
|
||||
*/
|
||||
|
||||
#ifndef __Enumerating_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __Enumerating_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
@protocol Enumerating <NSObject>
|
||||
|
||||
- initWithCollection: aCollection;
|
||||
- nextObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Enumerating_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* Interface for Objective-C GapArray collection object
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Kresten Krab Thorup <krab@iesd.auc.dk>
|
||||
Dept. of Mathematics and Computer Science, Aalborg U., Denmark
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __GapArray_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __GapArray_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Array.h>
|
||||
|
||||
@interface GapArray : Array
|
||||
{
|
||||
@public
|
||||
unsigned _gap_start; /* start of gap */
|
||||
unsigned _gap_size; /* size of gap */
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __GapArray_h_GNUSTEP_BASE_INCLUDE */
|
144
Old/GapArray.m
144
Old/GapArray.m
|
@ -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
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/* GapArray definitions for the use of subclass implementations
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
Copyright (C) 1993,1994 Kresten Krab Thorup <krab@iesd.auc.dk>
|
||||
Dept. of Mathematics and Computer Science, Aalborg U., Denmark
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __GapArrayPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __GapArrayPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/ArrayPrivate.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define GAP_TO_BASIC(INDEX) \
|
||||
({ unsigned int __idx = (INDEX); \
|
||||
__idx >= self->_gap_start \
|
||||
? __idx+self->_gap_size : __idx; })
|
||||
|
||||
#define BASIC_TO_GAP(INDEX) \
|
||||
({ unsigned int __idx = (INDEX); \
|
||||
__idx < self->_gap_start \
|
||||
? __idx : __idx-self->_gap_size; })
|
||||
|
||||
static inline void
|
||||
gapMoveGapTo (GapArray* self, unsigned index)
|
||||
{
|
||||
int i;
|
||||
assert (index <= self->_capacity);
|
||||
if (index < self->_gap_start)
|
||||
{
|
||||
#ifndef STABLE_MEMCPY
|
||||
int b = index + self->_gap_size;
|
||||
for (i = self->_gap_start + self->_gap_size - 1; i >= b; i--)
|
||||
self->_contents_array[i] = self->_contents_array[i - self->_gap_size];
|
||||
#else
|
||||
memcpy (self->_contents_array + index + self->_gap_size,
|
||||
self->_contents_array + index,
|
||||
self->_gap_start - index)
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef STABLE_MEMCPY
|
||||
for(i = self->_gap_start; i != index; i++)
|
||||
self->_contents_array[i] = self->_contents_array[i + self->_gap_size];
|
||||
#else
|
||||
memcpy (self->_contents_array + self->_gap_start,
|
||||
self->_contents_array + self->_gap_start + self->_gap_size,
|
||||
index - self->_gap_start);
|
||||
#endif
|
||||
}
|
||||
self->_gap_start = index;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gapMakeHoleAt(GapArray *self, unsigned index)
|
||||
{
|
||||
gapMoveGapTo (self, index);
|
||||
self->_gap_start += 1;
|
||||
self->_gap_size -= 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gapFillHoleAt(GapArray *self, unsigned index)
|
||||
{
|
||||
gapMoveGapTo (self, index);
|
||||
self->_gap_size += 1;
|
||||
}
|
||||
|
||||
#endif /* __GapArrayPrivate_h_GNUSTEP_BASE_INCLUDE */
|
36
Old/Heap.h
36
Old/Heap.h
|
@ -1,36 +0,0 @@
|
|||
/* Interface for Objective-C Heap 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.
|
||||
*/
|
||||
|
||||
#ifndef __Heap_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Heap_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Array.h>
|
||||
|
||||
@interface Heap : Array
|
||||
|
||||
- (void) heapifyFromIndex: (unsigned)index;
|
||||
- (void) heapify;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Heap_h_GNUSTEP_BASE_INCLUDE */
|
102
Old/Heap.m
102
Old/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,132 +0,0 @@
|
|||
/* Protocol for Objective-C objects that hold elements accessible by index
|
||||
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.
|
||||
*/
|
||||
|
||||
/* The <IndexedCollecting> protocol inherits from the
|
||||
<KeyedCollecting> protocol.
|
||||
|
||||
The <IndexedCollecting> protocol defines the interface to a
|
||||
collection of elements that are accessible by a key that is an index,
|
||||
where the indeces in a collection are a contiguous series of unsigned
|
||||
integers beginning at 0. This is the root of the protocol heirarchy
|
||||
for all collections that hold their elements in some order. Elements
|
||||
may be accessed, inserted, replaced and removed by their index.
|
||||
*/
|
||||
|
||||
#ifndef __IndexedCollecting_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __IndexedCollecting_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Collecting.h>
|
||||
#include <Foundation/NSRange.h>
|
||||
|
||||
#define IndexRange NSRange
|
||||
|
||||
#define IndexRangeInside(RANGE1,RANGE2) \
|
||||
({IndexRange __a=(RANGE1), __b=(RANGE2); \
|
||||
__a.start<=__b.start && __a.end>=__b.end;})
|
||||
|
||||
|
||||
@protocol ConstantIndexedCollecting <ConstantCollecting>
|
||||
|
||||
// GETTING MEMBERS BY INDEX;
|
||||
- objectAtIndex: (unsigned)index;
|
||||
- firstObject;
|
||||
- lastObject;
|
||||
|
||||
// GETTING MEMBERS BY NEIGHBOR;
|
||||
- successorOfObject: anObject;
|
||||
- predecessorOfObject: anObject;
|
||||
|
||||
// GETTING INDICES BY MEMBER;
|
||||
- (unsigned) indexOfObject: anObject;
|
||||
- (unsigned) indexOfObject: anObject inRange: (IndexRange)aRange;
|
||||
|
||||
// TESTING;
|
||||
- (BOOL) contentsEqualInOrder: (id <ConstantIndexedCollecting>)aColl;
|
||||
- (int) compareInOrderContentsOf: (id <Collecting>)aCollection;
|
||||
- (unsigned) indexOfFirstDifference: (id <ConstantIndexedCollecting>)aColl;
|
||||
- (unsigned) indexOfFirstIn: (id <ConstantCollecting>)aColl;
|
||||
- (unsigned) indexOfFirstNotIn: (id <ConstantCollecting>)aColl;
|
||||
|
||||
// ENUMERATING;
|
||||
- (id <Enumerating>) reverseObjectEnumerator;
|
||||
- (void) withObjectsInRange: (IndexRange)aRange
|
||||
invoke: (id <Invoking>)anInvocation;
|
||||
- (void) withObjectsInReverseInvoke: (id <Invoking>)anInvocation;
|
||||
- (void) withObjectsInReverseInvoke: (id <Invoking>)anInvocation
|
||||
whileTrue:(BOOL *)flag;
|
||||
- (void) makeObjectsPerformInReverse: (SEL)aSel;
|
||||
- (void) makeObjectsPerformInReverse: (SEL)aSel withObject: argObject;
|
||||
|
||||
// LOW-LEVEL ENUMERATING;
|
||||
- prevObjectWithEnumState: (void**)enumState;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@protocol IndexedCollecting <ConstantIndexedCollecting, Collecting>
|
||||
|
||||
// REPLACING;
|
||||
- (void) replaceObjectAtIndex: (unsigned)index with: newObject;
|
||||
|
||||
// REMOVING;
|
||||
- (void) removeObjectAtIndex: (unsigned)index;
|
||||
- (void) removeFirstObject;
|
||||
- (void) removeLastObject;
|
||||
- (void) removeRange: (IndexRange)aRange;
|
||||
|
||||
// SORTING;
|
||||
- (void) sortContents;
|
||||
- (void) sortAddObject: newObject;
|
||||
|
||||
@end
|
||||
|
||||
#define NO_INDEX NSNotFound
|
||||
|
||||
/* xxx Fix this comment: */
|
||||
|
||||
/* Most methods in the KeyedCollecting protocol that mention a key are
|
||||
duplicated in the IndexedCollecting protocol, with their names
|
||||
modified to reflect that the "key" now must be an unsigned integer,
|
||||
(an "index"). The programmer should be able to use either of the
|
||||
corresponding method names to the same effect.
|
||||
|
||||
The new methods are provided in the IndexedCollecting protocol for:
|
||||
1) Better type checking for when an unsigned int is required.
|
||||
2) More intuitive method names.
|
||||
|
||||
IndexedCollecting KeyedCollecting
|
||||
----------------------------------------------------------------------
|
||||
insertObject:atIndex insertObject:atKey:
|
||||
replaceObjectAtIndex:with: replaceObjectAtKey:with:
|
||||
removeObjectAtIndex: removeObjectAtKey:
|
||||
objectAtIndex: objectAtKey:
|
||||
includesIndex: includesKey:
|
||||
|
||||
insertElement:atIndex insertElement:atKey:
|
||||
replaceElementAtIndex:with: replaceElementAtKey:with:
|
||||
removeElementAtIndex: removeElementAtKey:
|
||||
elementAtIndex: elementAtKey:
|
||||
|
||||
*/
|
||||
|
||||
#endif /* __IndexedCollecting_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,110 +0,0 @@
|
|||
/* Interface for Objective-C Sequential 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.
|
||||
*/
|
||||
|
||||
#ifndef __IndexedCollection_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __IndexedCollection_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/KeyedCollection.h>
|
||||
#include <base/IndexedCollecting.h>
|
||||
|
||||
@interface ConstantIndexedCollection : ConstantCollection
|
||||
@end
|
||||
|
||||
@interface IndexedCollection : ConstantIndexedCollection
|
||||
@end
|
||||
|
||||
@interface ReverseEnumerator : Enumerator
|
||||
@end
|
||||
|
||||
/* Put this on category instead of class to avoid bogus complaint from gcc */
|
||||
@interface ConstantIndexedCollection (Protocol) <ConstantIndexedCollecting>
|
||||
@end
|
||||
@interface IndexedCollection (Protocol) <IndexedCollecting>
|
||||
@end
|
||||
|
||||
#define FOR_INDEXED_COLLECTION(ACOLL, ELT) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while ((ELT = [ACOLL nextObjectWithEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_INDEXED_COLLECTION(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
#define FOR_INDEXED_COLLECTION_REVERSE(ACOLL, ELT) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while ((ELT = [ACOLL prevObjectWithEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_INDEXED_COLLECTION_REVERSE(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
#define FOR_INDEXED_COLLECTION_WHILE_TRUE(ACOLL, ELT, FLAG) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while (FLAG && (ELT = [ACOLL nextObjectWithEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_INDEXED_COLLECTION_WHILE_TRUE(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
|
||||
/* The only subclassResponsibilities in IndexedCollection are:
|
||||
|
||||
insertElement:atIndex:
|
||||
removeElementAtIndex:
|
||||
elementAtIndex:
|
||||
|
||||
but subclass will want to override others as well in order to
|
||||
increase efficiency. The following are especially important if
|
||||
the subclass's implementation of "elementAtIndex:" is not efficient:
|
||||
|
||||
replaceElementAtIndex:with:
|
||||
swapAtIndeces::
|
||||
shallowCopyReplaceFrom:to:with:
|
||||
sortAddElement:byCalling:
|
||||
removeElement:
|
||||
firstElement
|
||||
lastElement
|
||||
shallowCopyFrom:to:
|
||||
withElementsCall:whileTrue:
|
||||
withElementsInReverseCall:whileTrue:
|
||||
|
||||
and perhaps:
|
||||
|
||||
appendElement:
|
||||
prependElement:
|
||||
indexOfElement:
|
||||
withElementsInReverseCall:
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __IndexedCollection_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,40 +0,0 @@
|
|||
/* IndexedCollection definitions for the use of subclass implementations only
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __IndexedCollectionPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __IndexedCollectionPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/CollectionPrivate.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
/* To be used inside a method for making sure that index
|
||||
is not above range.
|
||||
*/
|
||||
#define CHECK_INDEX_RANGE_ERROR(INDEX, OVER) \
|
||||
if (INDEX >= OVER) \
|
||||
[NSException raise: NSRangeException \
|
||||
format: @"in %s, index %d is out of range", \
|
||||
sel_get_name (_cmd), INDEX]
|
||||
|
||||
#endif /* __IndexedCollectionPrivate_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,38 +0,0 @@
|
|||
/* Protocol for GNU Objective-C objects that understand an invalidation msg
|
||||
Copyright (C) 1993,1994 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.
|
||||
*/
|
||||
|
||||
#ifndef __InvalidationListening_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __InvalidationListening_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
/* This protocol is just temporary. It will disappear when GNU writes
|
||||
a more general notification system.
|
||||
It is not recommended that you use it in your code. */
|
||||
|
||||
@protocol InvalidationListening
|
||||
|
||||
- senderIsInvalid: sender;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __InvalidationListening_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,98 +0,0 @@
|
|||
#ifndef __Invocation_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Invocation_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
/*
|
||||
Use these for notifications!
|
||||
Don't forget to make these archivable / transportable.
|
||||
WARNING: All the (char*) type arguments and return values may
|
||||
extraneous stuff after the first type.
|
||||
*/
|
||||
|
||||
#include <base/Collection.h>
|
||||
#include <base/Invoking.h>
|
||||
|
||||
@interface Invocation : NSObject <Invoking>
|
||||
{
|
||||
char *return_type; /* may actually contain full argframe type */
|
||||
unsigned return_size;
|
||||
void *return_value;
|
||||
}
|
||||
- initWithReturnType: (const char *)encoding;
|
||||
- (const char *) returnType;
|
||||
- (unsigned) returnSize;
|
||||
- (void) getReturnValue: (void*) addr;
|
||||
@end
|
||||
|
||||
@interface ArgframeInvocation : Invocation
|
||||
{
|
||||
arglist_t argframe;
|
||||
BOOL args_retained;
|
||||
/* Use return_type to hold full argframe type. */
|
||||
}
|
||||
- initWithArgframe: (arglist_t)frame type: (const char *)e;
|
||||
- initWithType: (const char *)e;
|
||||
|
||||
- (void) retainArguments;
|
||||
- (BOOL) argumentsRetained;
|
||||
|
||||
- (const char *) argumentTypeAtIndex: (unsigned)i;
|
||||
- (unsigned) argumentSizeAtIndex: (unsigned)i;
|
||||
- (void) getArgument: (void*)addr atIndex: (unsigned)i;
|
||||
- (void) setArgumentAtIndex: (unsigned)i
|
||||
toValueAt: (const void*)addr;
|
||||
@end
|
||||
|
||||
@interface MethodInvocation : ArgframeInvocation
|
||||
{
|
||||
id *target_pointer;
|
||||
SEL *sel_pointer;
|
||||
}
|
||||
|
||||
- initWithArgframe: (arglist_t)frame selector: (SEL)s;
|
||||
- initWithSelector: (SEL)s;
|
||||
- initWithTarget: target selector: (SEL)s, ...;
|
||||
- (void) invokeWithTarget: t;
|
||||
- (SEL) selector;
|
||||
- (void) setSelector: (SEL)s;
|
||||
- target;
|
||||
- (void) setTarget: t;
|
||||
@end
|
||||
|
||||
/* Same as MethodInvocation, except that when sent
|
||||
[ -invokeWithObject: anObj], anObj does not become the target
|
||||
for the invocation's selector, it becomes the first object
|
||||
argument of the selector. */
|
||||
@interface ObjectMethodInvocation : MethodInvocation
|
||||
{
|
||||
id *arg_object_pointer;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface VoidFunctionInvocation : Invocation
|
||||
{
|
||||
void (*function)();
|
||||
}
|
||||
- initWithVoidFunction: (void(*)())f;
|
||||
@end
|
||||
|
||||
|
||||
@interface ObjectFunctionInvocation : Invocation
|
||||
{
|
||||
id (*function)(id);
|
||||
}
|
||||
- initWithObjectFunction: (id(*)(id))f;
|
||||
@end
|
||||
|
||||
|
||||
#if 0
|
||||
@interface FunctionInvocation : ArgframeInvocation
|
||||
{
|
||||
void (*function)();
|
||||
}
|
||||
- initWithFunction: (void(*)())f
|
||||
argframe: (arglist_t)frame type: (const char *)e;
|
||||
- initWithFunction: (void(*)())f;
|
||||
@end
|
||||
#endif
|
||||
|
||||
#endif /* __Invocation_h_GNUSTEP_BASE_INCLUDE */
|
861
Old/Invocation.m
861
Old/Invocation.m
|
@ -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,42 +0,0 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 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.
|
||||
*/
|
||||
|
||||
#ifndef __Invoking_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __Invoking_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol Invoking <NSObject>
|
||||
|
||||
- (void) invoke;
|
||||
- (void) invokeWithObject: anObject;
|
||||
|
||||
- objectReturnValue;
|
||||
- (int) intReturnValue;
|
||||
|
||||
- (BOOL) returnValueIsTrue;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Invoking_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/* Protocol for Objective-C objects holding (keyElement,contentElement) pairs.
|
||||
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.
|
||||
*/
|
||||
|
||||
/* The <KeyedCollecting> protocol inherits from the <Collecting> protocol.
|
||||
|
||||
The <KeyedCollecting> protocol defines the interface to a
|
||||
collection of elements that are accessible by a key, where the key is
|
||||
some unique element. Pairs of (key element, content element) may be
|
||||
added, removed and replaced. The keys and contents may be tested,
|
||||
enumerated and copied.
|
||||
*/
|
||||
|
||||
#ifndef __KeyedCollecting_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __KeyedCollecting_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Collecting.h>
|
||||
|
||||
@protocol ConstantKeyedCollecting <ConstantCollecting>
|
||||
|
||||
// INITIALIZING;
|
||||
- initWithObjects: (id*)objects forKeys: (id*)keys count: (unsigned)c;
|
||||
|
||||
// GETTING ELEMENTS AND KEYS;
|
||||
- objectAtKey: aKey;
|
||||
- keyOfObject: aContentObject;
|
||||
|
||||
// TESTING;
|
||||
- (BOOL) containsKey: aKey;
|
||||
|
||||
// ENUMERATIONS;
|
||||
- (id <Enumerating>) keyEnumerator;
|
||||
- withKeyObjectsInvoke: (id <Invoking>)anInvocation;
|
||||
- withKeyObjectsInvoke: (id <Invoking>)anInvocation
|
||||
whileTrue: (BOOL *)flag;
|
||||
|
||||
// LOW-LEVEL ENUMERATING;
|
||||
- nextObjectAndKey: (id*)keyPtr withEnumState: (void**)enumState;
|
||||
|
||||
// COPYING;
|
||||
- shallowCopyValuesAs: (Class)aCollectingClass;
|
||||
- shallowCopyKeysAs: (Class)aCollectingClass;
|
||||
- copyValuesAs: (Class)aCollectingClass;
|
||||
- copyKeysAs: (Class)aCollectingClass;
|
||||
|
||||
@end
|
||||
|
||||
@protocol KeyedCollecting <ConstantKeyedCollecting, Collecting>
|
||||
|
||||
// ADDING;
|
||||
- (void) putObject: newContentObject atKey: aKey;
|
||||
|
||||
// REPLACING AND SWAPPING;
|
||||
- (void) replaceObjectAtKey: aKey with: newContentObject;
|
||||
- (void) swapObjectsAtKeys: key1 : key2;
|
||||
|
||||
// REMOVING;
|
||||
- (void) removeObjectAtKey: aKey;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __KeyedCollecting_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,79 +0,0 @@
|
|||
/* Interface for Objective-C KeyedCollection 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.
|
||||
*/
|
||||
|
||||
#ifndef __KeyedCollection_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __KeyedCollection_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Collection.h>
|
||||
#include <base/KeyedCollecting.h>
|
||||
|
||||
@interface ConstantKeyedCollection : Collection
|
||||
@end
|
||||
|
||||
@interface KeyedCollection : ConstantKeyedCollection
|
||||
@end
|
||||
|
||||
/* Put this on category instead of class to avoid bogus complaint from gcc */
|
||||
@interface ConstantKeyedCollection (Protocol) <ConstantKeyedCollecting>
|
||||
@end
|
||||
@interface KeyedCollection (Protocol) <KeyedCollecting>
|
||||
@end
|
||||
|
||||
@interface KeyEnumerator : Enumerator
|
||||
@end
|
||||
|
||||
#define FOR_KEYED_COLLECTION(ACOLL, ELT, KEY) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while ((ELT = [ACOLL nextObjectAndKey: &(KEY) withEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_KEYED_COLLECTION(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
#define FOR_KEYED_COLLECTION_WHILE_TRUE(ACOLL, ELT, KEY, FLAG) \
|
||||
{ \
|
||||
void *_es = [ACOLL newEnumState]; \
|
||||
while (FLAG && (ELT = [ACOLL nextObjectAndKey: &(KEY) \
|
||||
withEnumState: &_es])) \
|
||||
{
|
||||
|
||||
#define END_FOR_KEYED_COLLECTION_WHILE_TRUE(ACOLL) \
|
||||
} \
|
||||
[ACOLL freeEnumState: &_es]; \
|
||||
}
|
||||
|
||||
|
||||
/* The only subclassResponsibilities in IndexedCollection are:
|
||||
|
||||
keyDescription
|
||||
insertElement:atKey:
|
||||
removeElementAtKey:
|
||||
elementAtKey:
|
||||
includesKey:
|
||||
getNextKey:content:withEnumState:
|
||||
*/
|
||||
|
||||
#endif /* __KeyedCollection_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,50 +0,0 @@
|
|||
/* Interface for Objective-C LinkedList 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.
|
||||
*/
|
||||
|
||||
#ifndef __LinkedList_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __LinkedList_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/OrderedCollection.h>
|
||||
|
||||
/* The <LinkedListComprising> protocol defines the interface to an object
|
||||
that may be an element in a LinkedList.
|
||||
*/
|
||||
@protocol LinkedListComprising
|
||||
- nextLink;
|
||||
- prevLink;
|
||||
- (void) setNextLink: (id <LinkedListComprising>)aLink;
|
||||
- (void) setPrevLink: (id <LinkedListComprising>)aLink;
|
||||
- linkedList;
|
||||
- (void) setLinkedList: aLinkedList;
|
||||
@end
|
||||
|
||||
@interface LinkedList : OrderedCollection
|
||||
{
|
||||
id _first_link;
|
||||
id _last_link;
|
||||
unsigned int _count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __LinkedList_h_GNUSTEP_BASE_INCLUDE */
|
408
Old/LinkedList.m
408
Old/LinkedList.m
|
@ -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,38 +0,0 @@
|
|||
/* Interface 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.
|
||||
*/
|
||||
|
||||
#ifndef __LinkedListNode_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __LinkedListNode_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/LinkedList.h>
|
||||
#include <base/Coding.h>
|
||||
|
||||
@interface LinkedListNode : NSObject <LinkedListComprising>
|
||||
{
|
||||
id <LinkedListComprising> _next;
|
||||
id <LinkedListComprising> _prev;
|
||||
id _linked_list;
|
||||
}
|
||||
@end
|
||||
|
||||
#endif /* __LinkedListNode_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,34 +0,0 @@
|
|||
/* Protocol for GNU Objective-C mutex locks
|
||||
Copyright (C) 1993,1994 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.
|
||||
*/
|
||||
|
||||
#ifndef __Locking_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Locking_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <objc/Protocol.h>
|
||||
|
||||
@protocol Locking
|
||||
- (void) lock;
|
||||
- (void) unlock;
|
||||
@end
|
||||
|
||||
#endif /* __Locking_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,39 +0,0 @@
|
|||
/* Interface for Mach-port based object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: 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.
|
||||
*/
|
||||
|
||||
#ifndef __MachPort_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __MachPort_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#if __mach__
|
||||
|
||||
#include <base/Port.h>
|
||||
|
||||
@interface MachInPort : InPort
|
||||
@end
|
||||
|
||||
@interface MachOutPort : OutPort
|
||||
@end
|
||||
|
||||
#endif /* __mach__ */
|
||||
|
||||
#endif /* __MachPort_h_GNUSTEP_BASE_INCLUDE */
|
196
Old/MachPort.m
196
Old/MachPort.m
|
@ -1,196 +0,0 @@
|
|||
/* Implementation of Machport-based port object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: September 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.
|
||||
*/
|
||||
|
||||
/* This old code really needs work; it does not currently compile. */
|
||||
|
||||
#if __mach__
|
||||
|
||||
#include <config.h>
|
||||
#include <base/MachPort.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <base/Set.h>
|
||||
|
||||
#include <mach/cthreads.h>
|
||||
#include <mach/notify.h>
|
||||
|
||||
static Dictionary *portDictionary;
|
||||
static NSLock *portDictionaryGate;
|
||||
|
||||
@implementation MachPort
|
||||
|
||||
+ initialize
|
||||
{
|
||||
portDictionaryGate = [NSLock new];
|
||||
NSAssert(sizeof(int) == sizeof(port_t), NSInternalInconsistencyException);
|
||||
portDictionary = [[Dictionary alloc]
|
||||
initWithType:@encode(id)
|
||||
keyType:@encode(int)];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This not tested */
|
||||
static int
|
||||
listen_for_invalidation (any_t arg)
|
||||
{
|
||||
kern_return_t r;
|
||||
notification_t m;
|
||||
m.notify_header.msg_size = sizeof(notification_t);
|
||||
m.notify_header.msg_local_port = task_notify();
|
||||
for (;;)
|
||||
{
|
||||
r = msg_receive((msg_header_t*)&m, MSG_OPTION_NONE, 0);
|
||||
switch (r)
|
||||
{
|
||||
case RCV_SUCCESS:
|
||||
fprintf(stderr, "notification id %d\n", (int)m.notify_header.msg_id);
|
||||
break;
|
||||
case RCV_TIMED_OUT:
|
||||
fprintf(stderr, "notification msg_receive timed out\n");
|
||||
exit(-1);
|
||||
default:
|
||||
mach_error("notification", r);
|
||||
exit(-1);
|
||||
}
|
||||
switch (m.notify_header.msg_id)
|
||||
{
|
||||
case NOTIFY_PORT_DELETED:
|
||||
[[MachPort newFromMachPort:m.notify_port] invalidate];
|
||||
break;
|
||||
case NOTIFY_MSG_ACCEPTED:
|
||||
break;
|
||||
case NOTIFY_PORT_DESTROYED:
|
||||
[[MachPort newFromMachPort:m.notify_port] invalidate];
|
||||
break;
|
||||
default:
|
||||
mach_error("notification", r);
|
||||
exit(-1);
|
||||
}
|
||||
/* Where do we free the object? */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This not tested */
|
||||
+ listenForPortInvalidation
|
||||
{
|
||||
MachPort *listenPort = [MachPort new];
|
||||
task_set_special_port(task_self(), TASK_NOTIFY_PORT, [listenPort mach_port]);
|
||||
cthread_detach(cthread_fork((any_t)listen_for_invalidation, (any_t)0));
|
||||
return self;
|
||||
}
|
||||
|
||||
/* designated initializer */
|
||||
+ newFromMachPort: (port_t)p dealloc: (BOOL)f
|
||||
{
|
||||
MachPort *aPort;
|
||||
[portDictionaryGate lock];
|
||||
if ((aPort = [portDictionary elementAtKey:(int)p]))
|
||||
{
|
||||
[portDictionaryGate unlock];
|
||||
[aPort addReference];
|
||||
return aPort;
|
||||
}
|
||||
aPort = [[self alloc] init];
|
||||
aPort->mach_port = p;
|
||||
aPort->deallocate = f;
|
||||
[portDictionary addElement:aPort atKey:(int)p];
|
||||
[portDictionaryGate unlock];
|
||||
return aPort;
|
||||
}
|
||||
|
||||
+ newFromMachPort: (port_t)p
|
||||
{
|
||||
return [self newFromMachPort:p dealloc:NO];
|
||||
}
|
||||
|
||||
+ new
|
||||
{
|
||||
kern_return_t error;
|
||||
port_t p;
|
||||
|
||||
if ((error=port_allocate(task_self(), &p)) != KERN_SUCCESS) {
|
||||
mach_error("port_allocate failed", error);
|
||||
exit(1);
|
||||
}
|
||||
return [self newFromMachPort:p];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[aCoder encodeValueOfCType: @encode(BOOL)
|
||||
at: &deallocate
|
||||
withName: @""];
|
||||
[aCoder encodeMachPort: mach_port];
|
||||
}
|
||||
|
||||
+ newWithCoder: aCoder
|
||||
{
|
||||
BOOL f;
|
||||
port_t mp;
|
||||
MachPort *p;
|
||||
|
||||
[aCoder decodeValueOfCType: @encode(BOOL)
|
||||
at: &f
|
||||
withName: NULL];
|
||||
[aCoder decodeMachPort: &mp];
|
||||
|
||||
p = [MachPort newFromMachPort:mp dealloc:f];
|
||||
return p;
|
||||
}
|
||||
|
||||
- (unsigned) hash
|
||||
{
|
||||
/* What should this be? */
|
||||
return (unsigned)self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (refcount-1 == 0)
|
||||
{
|
||||
[portDictionaryGate lock];
|
||||
[portDictionaryGate removeElementAtKey:(int)machPort];
|
||||
[portDictionaryGate unlock];
|
||||
if (deallocate)
|
||||
{
|
||||
kern_return_t error;
|
||||
error = port_deallocate(task_self(), machPort);
|
||||
if (error != KERN_SUCCESS) {
|
||||
mach_error("port_deallocate failed", error);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
[super dealloc];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (mach_port_t) machPort
|
||||
{
|
||||
return mach_port;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __mach__ */
|
|
@ -1,33 +0,0 @@
|
|||
/* Interface for Objective-C Magnitude 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.
|
||||
*/
|
||||
|
||||
#ifndef __Magnitude_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Magnitude_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Ordering.h>
|
||||
|
||||
@interface Magnitude : NSObject <Ordering>
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Magnitude_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,40 +0,0 @@
|
|||
/* Interface for Objective-C MappedCollector 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.
|
||||
*/
|
||||
|
||||
#ifndef __MappedCollector_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __MappedCollector_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/KeyedCollection.h>
|
||||
|
||||
@interface MappedCollector : KeyedCollection
|
||||
{
|
||||
id <KeyedCollecting> _map;
|
||||
id <KeyedCollecting> _domain;
|
||||
}
|
||||
|
||||
- initWithCollection: (id <KeyedCollecting>)aDomain
|
||||
map: (id <KeyedCollecting>)aMap;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __MappedCollector_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,90 +0,0 @@
|
|||
/* Interface for GNU Objective C memory stream
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Date: September 1997
|
||||
|
||||
Modifications to use NSData and NSMutable data objects to hold data.
|
||||
*/
|
||||
|
||||
#ifndef __MemoryStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __MemoryStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/Streaming.h>
|
||||
|
||||
/* This protocol is preliminary and may change.
|
||||
This also may get pulled out into a separate .h file. */
|
||||
|
||||
@protocol MemoryStreaming <Streaming>
|
||||
|
||||
- initWithCapacity: (unsigned)capacity;
|
||||
|
||||
- (void) setStreamBufferCapacity: (unsigned)s;
|
||||
|
||||
- (char*) streamBuffer;
|
||||
- (unsigned) streamBufferCapacity;
|
||||
- (unsigned) streamEofPosition;
|
||||
|
||||
@end
|
||||
|
||||
@interface MemoryStream : Stream <MemoryStreaming>
|
||||
{
|
||||
id data;
|
||||
int prefix;
|
||||
int position;
|
||||
int eof_position;
|
||||
BOOL isMutable;
|
||||
}
|
||||
|
||||
+ (MemoryStream*)streamWithData: (id)anObject;
|
||||
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
prefix: (unsigned)prefix;
|
||||
- initWithData: (id)anObject;
|
||||
|
||||
#if 0
|
||||
- initWithSize: (unsigned)s; /* For backwards compatibility, depricated */
|
||||
#endif
|
||||
|
||||
- (id) data;
|
||||
- (id) mutableData;
|
||||
- (unsigned) streamBufferPrefix;
|
||||
- (unsigned) streamBufferLength; /* prefix + eofPosition */
|
||||
|
||||
/* xxx This interface will change */
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* reset for this position */
|
||||
position: (unsigned)i; /* current position for reading/writing */
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
freeWhenDone: (BOOL)f
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* reset for this position */
|
||||
position: (unsigned)i; /* current position for reading/writing */
|
||||
@end
|
||||
|
||||
#endif /* __MemoryStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,435 +0,0 @@
|
|||
/* Implementation of GNU Objective C memory stream
|
||||
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/preface.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/Coder.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Deal with memchr: */
|
||||
#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 */
|
||||
|
||||
#define DEFAULT_MEMORY_STREAM_SIZE 64
|
||||
|
||||
extern int
|
||||
o_vscanf (void *stream,
|
||||
int (*inchar_func)(void*),
|
||||
void (*unchar_func)(void*,int),
|
||||
const char *format, va_list argptr);
|
||||
|
||||
static BOOL debug_memory_stream = NO;
|
||||
|
||||
/* A pretty stupid implementation based on realloc(), but it works for now. */
|
||||
|
||||
@implementation MemoryStream
|
||||
|
||||
+ (MemoryStream*)streamWithData: (id)anObject
|
||||
{
|
||||
return [[[MemoryStream alloc] initWithData:anObject] autorelease];
|
||||
}
|
||||
|
||||
- (id) data
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/* xxx This interface will change */
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
freeWhenDone: (BOOL)f
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* never read/write before this position */
|
||||
position: (unsigned)i /* current position for reading/writing */
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
if (b)
|
||||
if (f)
|
||||
data = [[NSMutableData alloc] initWithBytesNoCopy: b length: s];
|
||||
else
|
||||
data = [[NSMutableData alloc] initWithBytes: b length: s];
|
||||
else
|
||||
{
|
||||
data = [[NSMutableData alloc] initWithCapacity: s];
|
||||
if (data)
|
||||
[data setLength: s];
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
prefix = p;
|
||||
position = i;
|
||||
eof_position = l;
|
||||
isMutable = YES;
|
||||
if ([data length] < prefix + MAX(position, eof_position))
|
||||
[data setLength: prefix + MAX(position, eof_position)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self release];
|
||||
self = nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* never read/write before this position */
|
||||
position: (unsigned)i /* current position for reading/writing */
|
||||
{
|
||||
return [self _initOnMallocBuffer: b
|
||||
freeWhenDone: YES
|
||||
size: s
|
||||
eofPosition: l
|
||||
prefix: p
|
||||
position: i];
|
||||
}
|
||||
|
||||
/* xxx This method will disappear. */
|
||||
#if 0
|
||||
- initWithSize: (unsigned)s
|
||||
prefix: (unsigned)p
|
||||
position: (unsigned)i
|
||||
{
|
||||
return [self _initOnMallocBuffer: 0
|
||||
freeWhenDone: YES
|
||||
size: s
|
||||
eofPosition: i
|
||||
prefix: p
|
||||
position: i];
|
||||
}
|
||||
#endif
|
||||
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
prefix: (unsigned)p
|
||||
{
|
||||
return [self _initOnMallocBuffer: 0
|
||||
freeWhenDone: YES
|
||||
size: capacity
|
||||
eofPosition: 0
|
||||
prefix: p
|
||||
position: 0];
|
||||
}
|
||||
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
{
|
||||
return [self _initOnMallocBuffer: 0
|
||||
freeWhenDone: YES
|
||||
size: capacity
|
||||
eofPosition: 0
|
||||
prefix: 0
|
||||
position: 0];
|
||||
}
|
||||
|
||||
- initWithData: (id)anObject
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
if (anObject && [anObject isKindOfClass:[NSData class]])
|
||||
{
|
||||
data = [anObject retain];
|
||||
if ([data isKindOfClass:[NSMutableData class]])
|
||||
isMutable = YES;
|
||||
eof_position = [data length];
|
||||
position = 0;
|
||||
prefix = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self dealloc];
|
||||
self = nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#if 0
|
||||
- initWithSize: (unsigned)s
|
||||
{
|
||||
return [self initWithCapacity:s];
|
||||
}
|
||||
#endif
|
||||
|
||||
- init
|
||||
{
|
||||
return [self initWithCapacity: DEFAULT_MEMORY_STREAM_SIZE];
|
||||
}
|
||||
|
||||
- (BOOL) isWritable
|
||||
{
|
||||
return isMutable;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
+ newWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) mutableData
|
||||
{
|
||||
if (isMutable)
|
||||
return data;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (int) writeBytes: (const void*)b length: (int)l
|
||||
{
|
||||
unsigned size;
|
||||
|
||||
if (isMutable)
|
||||
{
|
||||
size = [data capacity];
|
||||
if (prefix+position+l > size)
|
||||
{
|
||||
size = MAX(prefix+position+l, size*2);
|
||||
[data setCapacity: size];
|
||||
}
|
||||
if (position+prefix+l > [data length])
|
||||
[data setLength: position+prefix+l];
|
||||
memcpy([data mutableBytes]+prefix+position, b, l);
|
||||
position += l;
|
||||
if (position > eof_position)
|
||||
eof_position = position;
|
||||
return l;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int) readBytes: (void*)b length: (int)l
|
||||
{
|
||||
if (position+l > eof_position)
|
||||
l = eof_position-position;
|
||||
memcpy(b, [data bytes]+prefix+position, l);
|
||||
position += l;
|
||||
return l;
|
||||
}
|
||||
|
||||
- (NSString*) readLine
|
||||
{
|
||||
char *nl = memchr([data bytes]+prefix+position, '\n', eof_position-position);
|
||||
char *ret = NULL;
|
||||
if (nl)
|
||||
{
|
||||
int len = nl-((char*)[data bytes])-prefix-position;
|
||||
ret = objc_malloc (len+1);
|
||||
strncpy(ret, ((char*)[data bytes])+prefix+position, len);
|
||||
ret[len] = '\0';
|
||||
position += len+1;
|
||||
}
|
||||
return [[[NSString alloc] initWithCStringNoCopy: ret
|
||||
length: strlen (ret)
|
||||
freeWhenDone: YES]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
/* Making these nested functions (which is what I'd like to do) is
|
||||
crashing the va_arg stuff in vscanf(). Why? */
|
||||
#define MS ((MemoryStream*)s)
|
||||
|
||||
int outchar_func(void *s, int c)
|
||||
{
|
||||
if (MS->isMutable)
|
||||
{
|
||||
if (MS->prefix + MS->position >= [MS->data capacity])
|
||||
return EOF;
|
||||
((char*)[MS->data mutableBytes])[MS->prefix + MS->position++] = (char)c;
|
||||
return 1;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int inchar_func(void *s)
|
||||
{
|
||||
if (MS->prefix + MS->position >= [MS->data length])
|
||||
return EOF;
|
||||
return (int) ((char*)[MS->data bytes])[MS->prefix + MS->position++];
|
||||
}
|
||||
|
||||
void unchar_func(void *s, int c)
|
||||
{
|
||||
if (MS->position > 0)
|
||||
MS->position--;
|
||||
if (MS->isMutable)
|
||||
((char*)[MS->data mutableBytes])[MS->prefix + MS->position] = (char)c;
|
||||
}
|
||||
|
||||
#if HAVE_VSPRINTF
|
||||
- (int) writeFormat: (NSString*)format
|
||||
arguments: (va_list)arg
|
||||
{
|
||||
unsigned size;
|
||||
int ret;
|
||||
|
||||
if (!isMutable)
|
||||
return 0;
|
||||
/* xxx Using this ugliness we at least let ourselves safely print
|
||||
formatted strings up to 128 bytes long.
|
||||
It's digusting, though, and we need to fix it.
|
||||
Using GNU stdio streams would do the trick.
|
||||
*/
|
||||
size = [data capacity];
|
||||
if (size - (prefix + position) < 128)
|
||||
size = MAX(size+128, size*2);
|
||||
[data setLength: size];
|
||||
|
||||
ret = VSPRINTF_LENGTH (vsprintf([data mutableBytes]+prefix+position,
|
||||
[format cString], arg));
|
||||
position += ret;
|
||||
/* xxx Make sure we didn't overrun our buffer.
|
||||
As per above kludge, this would happen if we happen to have more than
|
||||
128 bytes left in the buffer and we try to write a string longer than
|
||||
the num bytes left in the buffer. */
|
||||
NSAssert(prefix + position <= [data capacity], @"buffer overrun");
|
||||
if (position > eof_position)
|
||||
eof_position = position;
|
||||
[data setLength:eof_position + prefix];
|
||||
if (debug_memory_stream)
|
||||
{
|
||||
*(char*)([data mutableBytes]+prefix+position) = '\0';
|
||||
fprintf(stderr, "%s\n", (char*)[data mutableBytes]+prefix);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (int) readFormat: (NSString*)format, ...
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = o_vscanf(self, inchar_func, unchar_func,
|
||||
[format cString], ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)mode
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case STREAM_SEEK_FROM_START:
|
||||
position = i;
|
||||
break;
|
||||
case STREAM_SEEK_FROM_CURRENT:
|
||||
position += i;
|
||||
break;
|
||||
case STREAM_SEEK_FROM_END:
|
||||
position = eof_position + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) streamPosition
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
[self flushStream];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[data release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL) streamEof
|
||||
{
|
||||
if (position == eof_position)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (unsigned) streamBufferCapacity
|
||||
{
|
||||
if (isMutable)
|
||||
return [data capacity];
|
||||
return [data length];
|
||||
}
|
||||
|
||||
- (char*) streamBuffer
|
||||
{
|
||||
if (isMutable)
|
||||
return (char*)[data mutableBytes];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void) setStreamBufferCapacity: (unsigned)s
|
||||
{
|
||||
if (isMutable)
|
||||
if (s > prefix + eof_position)
|
||||
[data setCapacity:s];
|
||||
}
|
||||
|
||||
- (unsigned) streamEofPosition
|
||||
{
|
||||
return eof_position;
|
||||
}
|
||||
|
||||
- (void) setStreamEofPosition: (unsigned)i
|
||||
{
|
||||
if (i < [data length] - prefix)
|
||||
eof_position = i;
|
||||
}
|
||||
|
||||
- (unsigned) streamBufferPrefix
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
- (unsigned) streamBufferLength
|
||||
{
|
||||
return prefix + eof_position;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,221 +0,0 @@
|
|||
/* Interface to 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.
|
||||
*/
|
||||
|
||||
#ifndef __NotificationDispatcher_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __NotificationDispatcher_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
/* A class for posting notifications to observer objects that request
|
||||
them.
|
||||
|
||||
This implementation has several advantages over OpenStep's
|
||||
NSNotificationCenter:
|
||||
|
||||
(1) Heavy use of hash tables and the use of LinkedList's make it
|
||||
faster. Removing from the middle of LinkedList's is much more
|
||||
efficient than removing from the middle of Array's.
|
||||
|
||||
(2) The way in which notifications are dispatched can be specified as
|
||||
invocation objects instead of just selectors. Invocation objects
|
||||
are more flexible than selectors in that they can hold more context
|
||||
and, if desired, can call C functions instead of sending a message
|
||||
to an object; (this way you may be able to avoid creating a new
|
||||
class just to handle certain notifications).
|
||||
|
||||
(3) Instead of sending +defaultCenter, you can simply send +add...,
|
||||
+remove... and +post... messages directly to the class object.
|
||||
The class uses a static variable directly, instead of taking
|
||||
the time for the extra +defaultCenter method call. It's both
|
||||
easier for the user and more time efficient.
|
||||
|
||||
(4) You can call -addObserver:... with both name and object being
|
||||
nil. This request will receive postings of *all* notifications.
|
||||
Wow.
|
||||
|
||||
Although it offers extra features, the implementation has an
|
||||
OpenStep-style interface also.
|
||||
|
||||
*/
|
||||
|
||||
#include <base/LinkedList.h>
|
||||
#include <base/Array.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
|
||||
@interface NotificationDispatcher : NSObject
|
||||
{
|
||||
/* `nr' stands for Notification Request Object; the interface for
|
||||
this class is defined in the .m file. One of these is created
|
||||
for each -add... call. */
|
||||
|
||||
/* For those observer requests with NAME=nil and OBJECT=nil. */
|
||||
LinkedList *_anonymous_nr_list;
|
||||
/* For those observer requests with NAME=nil and OBJECT!=nil. */
|
||||
NSMapTable *_object_2_nr_list;
|
||||
/* For those observer requests with NAME!=nil, OBJECT may or may not =nil .*/
|
||||
NSMapTable *_name_2_nr_list;
|
||||
|
||||
/* The keys are observers; the values are Array's containing all
|
||||
NotificationInvocation objects associated with the observer key. */
|
||||
NSMapTable *_observer_2_nr_array;
|
||||
|
||||
/* A mutex lock for making the ivars thread-safe. */
|
||||
NSRecursiveLock *_lock;
|
||||
}
|
||||
|
||||
|
||||
/* Adding new observers. */
|
||||
|
||||
/* Register INVOCATION to receive future notifictions that match NAME
|
||||
and OBJECT. A nil passed as either NAME or OBJECT acts as a
|
||||
wild-card. If NAME is nil, the NotificationDispatcher will send to
|
||||
the observer all notification pertaining to OBJECT. If OBJECT is
|
||||
nil, the NotificationDispatcher will send to the observer all
|
||||
notification pertaining to NAME. If both OBJECT and NAME are nil,
|
||||
send to the observer all notifications.
|
||||
|
||||
The notification will be posted by sending -invokeWithObject: to
|
||||
INVOCATION argument. The argument of -invokeWithObject: will be a
|
||||
Notification object. This use of Invocation objects is more
|
||||
flexible than using a selector, since Invocation's can be set up
|
||||
with more arguments, hold more context, and can be C functions.
|
||||
|
||||
OBJECT is not retained; this is done so these objects can tell when
|
||||
there are no outstanding non-notification references remaining. If
|
||||
an object may have added itself as an observer, it should call
|
||||
+removeObserver: in its -dealloc method.
|
||||
|
||||
INVOCATION and NAME, however, are retained. */
|
||||
|
||||
- (void) addInvocation: (id <Invoking>)invocation
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
|
||||
/* Register OBSERVER to receive future notifications that match NAME
|
||||
and OBJECT. A nil passed as either NAME or OBJECT acts as a
|
||||
wild-card. If NAME is nil, the NotificationDispatcher will send to
|
||||
the observer all notification pertaining to OBJECT. If OBJECT is
|
||||
nil, the NotificationDispatcher will send to the observer all
|
||||
notification pertaining to NAME. If both OBJECT and NAME are nil,
|
||||
send to the observer all notifications.
|
||||
|
||||
The notification will be posted by sending -perform:withObject:
|
||||
to the observer, with SEL and a Notification object as arguments.
|
||||
|
||||
Neither OBSERVER nor OBJECT are retained; this is done so these
|
||||
objects can tell when there are no outstanding non-notification
|
||||
references remaining. If an object may have added itself as an
|
||||
observer, it should call +removeObserver: in its -dealloc method.
|
||||
|
||||
INVOCATION and NAME, however, are retained. */
|
||||
|
||||
- (void) addObserver: observer
|
||||
selector: (SEL)sel
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
|
||||
/* Class versions of the above two methods that send these messages
|
||||
to the default NotificationDispatcher for the class. */
|
||||
|
||||
+ (void) addInvocation: (id <Invoking>)invocation
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
+ (void) addObserver: observer
|
||||
selector: (SEL)sel
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
|
||||
|
||||
|
||||
/* Removing observers. */
|
||||
|
||||
/* Remove all notification requests that would be sent to INVOCATION. */
|
||||
|
||||
- (void) removeInvocation: 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;
|
||||
|
||||
/* Remove all records pertaining to OBSERVER. For instance, this
|
||||
should be called before the OBSERVER is -dealloc'ed. */
|
||||
|
||||
- (void) removeObserver: observer;
|
||||
|
||||
/* Remove the notification requests for the given NAME and OBJECT
|
||||
parameters. As with adding an observation request, nil NAME or
|
||||
OBJECT act as wildcards. */
|
||||
|
||||
- (void) removeObserver: observer
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
|
||||
/* Class versions of the above four methods that send these messages
|
||||
to the default NotificationDispatcher for the class. */
|
||||
|
||||
+ (void) removeInvocation: invocation;
|
||||
+ (void) removeInvocation: invocation
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
+ (void) removeObserver: observer;
|
||||
+ (void) removeObserver: observer
|
||||
name: (NSString*)name
|
||||
object: object;
|
||||
|
||||
|
||||
|
||||
/* Post NOTIFICATION to all the observers that match its NAME and OBJECT.
|
||||
The INFO arguent does not have to be a Dictionary. If there is a single
|
||||
object that should be associated with the notification, you can simply
|
||||
pass that single object instead of a Dictionary containing the object. */
|
||||
|
||||
- (void) postNotification: notification;
|
||||
- (void) postNotificationName: (NSString*)name
|
||||
object: object;
|
||||
- (void) postNotificationName: (NSString*)name
|
||||
object: object
|
||||
userInfo: info;
|
||||
|
||||
/* Class versions of the above three methods that send these messages
|
||||
to the default NotificationDispatcher for the class. */
|
||||
|
||||
+ (void) postNotification: notification;
|
||||
+ (void) postNotificationName: (NSString*)name
|
||||
object: object;
|
||||
+ (void) postNotificationName: (NSString*)name
|
||||
object: object
|
||||
userInfo: info;
|
||||
|
||||
+ defaultInstance;
|
||||
|
||||
@end
|
||||
|
||||
@interface NotificationDispatcher (OpenStepCompat)
|
||||
+ defaultCenter;
|
||||
@end
|
||||
|
||||
#endif /* __NotificationDispatcher_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,558 +0,0 @@
|
|||
#if NEW_DO
|
||||
/* Interface for GNU Objective-C version of NSConnection
|
||||
Copyright (C) 1997,2000 Free Software Foundation, Inc.
|
||||
|
||||
Original by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Version for OPENSTEP by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Created: August 1997, updated June 2000
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __NSConnection_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __NSConnection_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSTimer.h>
|
||||
#include <Foundation/NSRunLoop.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@class NSDistantObject;
|
||||
@class NSPort;
|
||||
@class NSPortNameServer;
|
||||
@class NSData;
|
||||
|
||||
/*
|
||||
* Keys for the NSDictionary returned by [NSConnection -statistics]
|
||||
*/
|
||||
/* These in OPENSTEP 4.2 */
|
||||
GS_EXPORT NSString *NSConnectionRepliesReceived;
|
||||
GS_EXPORT NSString *NSConnectionRepliesSent;
|
||||
GS_EXPORT NSString *NSConnectionRequestsReceived;
|
||||
GS_EXPORT NSString *NSConnectionRequestsSent;
|
||||
/* These Are GNUstep extras */
|
||||
GS_EXPORT NSString *NSConnectionLocalCount; /* Objects sent out */
|
||||
GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* NSConnection class interface.
|
||||
*
|
||||
* A few methods are in the specification but not yet implemented.
|
||||
*/
|
||||
@interface NSConnection : NSObject
|
||||
{
|
||||
@private
|
||||
BOOL _isValid;
|
||||
BOOL _independentQueueing;
|
||||
BOOL _authenticateIn;
|
||||
BOOL _authenticateOut;
|
||||
BOOL _multipleThreads;
|
||||
NSPort *_receivePort;
|
||||
NSPort *_sendPort;
|
||||
unsigned _requestDepth;
|
||||
unsigned _messageCount;
|
||||
unsigned _reqOutCount;
|
||||
unsigned _reqInCount;
|
||||
unsigned _repOutCount;
|
||||
unsigned _repInCount;
|
||||
#ifndef _IN_CONNECTION_M
|
||||
#define GSIMapTable void*
|
||||
#endif
|
||||
GSIMapTable _localObjects;
|
||||
GSIMapTable _localTargets;
|
||||
GSIMapTable _remoteProxies;
|
||||
GSIMapTable _replyMap;
|
||||
#ifndef _IN_CONNECTION_M
|
||||
#undef GSIMapTable
|
||||
#endif
|
||||
NSTimeInterval _replyTimeout;
|
||||
NSTimeInterval _requestTimeout;
|
||||
NSMutableArray *_requestModes;
|
||||
NSMutableArray *_runLoops;
|
||||
NSMutableArray *_requestQueue;
|
||||
id _delegate;
|
||||
NSRecursiveLock *_refGate;
|
||||
NSMutableArray *_cachedDecoders;
|
||||
NSMutableArray *_cachedEncoders;
|
||||
NSString *_registeredName;
|
||||
NSPortNameServer *_nameServer;
|
||||
}
|
||||
|
||||
+ (NSArray*) allConnections;
|
||||
+ (NSConnection*) connectionWithReceivePort: (NSPort*)r
|
||||
sendPort: (NSPort*)s;
|
||||
+ (NSConnection*) connectionWithRegisteredName: (NSString*)n
|
||||
host: (NSString*)h;
|
||||
+ (NSConnection*) connectionWithRegisteredName: (NSString*)n
|
||||
host: (NSString*)h
|
||||
usingNameServer: (NSPortNameServer*)s;
|
||||
+ (id) currentConversation;
|
||||
+ (NSConnection*) defaultConnection;
|
||||
+ (NSDistantObject*) rootProxyForConnectionWithRegisteredName: (NSString*)name
|
||||
host: (NSString*)host;
|
||||
+ (NSDistantObject*) rootProxyForConnectionWithRegisteredName: (NSString*)name
|
||||
host: (NSString*)host usingNameServer: (NSPortNameServer*)s;
|
||||
|
||||
|
||||
- (void) addRequestMode: (NSString*)mode;
|
||||
- (void) addRunLoop: (NSRunLoop*)runloop;
|
||||
- (id) delegate;
|
||||
- (void) enableMultipleThreads;
|
||||
- (BOOL) independentConversationQueueing;
|
||||
- (id) initWithReceivePort: (NSPort*)r
|
||||
sendPort: (NSPort*)s;
|
||||
- (void) invalidate;
|
||||
- (BOOL) isValid;
|
||||
- (NSArray*)localObjects;
|
||||
- (BOOL) multipleThreadsEnabled;
|
||||
- (NSPort*) receivePort;
|
||||
- (BOOL) registerName: (NSString*)name;
|
||||
- (BOOL) registerName: (NSString*)name withNameServer: (NSPortNameServer*)svr;
|
||||
- (NSArray*) remoteObjects;
|
||||
- (void) removeRequestMode: (NSString*)mode;
|
||||
- (void) removeRunLoop: (NSRunLoop *)runloop;
|
||||
- (NSTimeInterval) replyTimeout;
|
||||
- (NSArray*) requestModes;
|
||||
- (NSTimeInterval) requestTimeout;
|
||||
- (id) rootObject;
|
||||
- (NSDistantObject*) rootProxy;
|
||||
- (void) runInNewThread;
|
||||
- (NSPort*) sendPort;
|
||||
- (void) setDelegate: anObj;
|
||||
- (void) setIndependentConversationQueueing: (BOOL)flag;
|
||||
- (void) setReplyTimeout: (NSTimeInterval)seconds;
|
||||
- (void) setRequestMode: (NSString*)mode;
|
||||
- (void) setRequestTimeout: (NSTimeInterval)seconds;
|
||||
- (void) setRootObject: anObj;
|
||||
- (NSDictionary*) statistics;
|
||||
@end
|
||||
|
||||
|
||||
/*
|
||||
* This catagory contains legacy methods from the original GNU 'Connection'
|
||||
* class, and useful extensions to NSConnection.
|
||||
*/
|
||||
@interface NSConnection (GNUstepExtensions) <GCFinalization>
|
||||
|
||||
+ (NSConnection*) newRegisteringAtName: (NSString*)n
|
||||
withRootObject: (id)anObject;
|
||||
|
||||
- (void) gcFinalize;
|
||||
|
||||
- (retval_t) forwardForProxy: (NSDistantObject*)object
|
||||
selector: (SEL)sel
|
||||
argFrame: (arglist_t)frame;
|
||||
- (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target;
|
||||
|
||||
@end
|
||||
|
||||
GS_EXPORT NSString *ConnectionBecameInvalidNotification;
|
||||
|
||||
@interface Object (NSConnectionDelegate)
|
||||
/*
|
||||
* This method may be used to ask a delegates permission to create
|
||||
* a new connection from the old one.
|
||||
* This method should be implemented in preference to the
|
||||
* [makeNewConnection:sender:] which is obsolete.
|
||||
*/
|
||||
- (BOOL) connection: (NSConnection*)parent
|
||||
shouldMakeNewConnection: (NSConnection*)newConnection;
|
||||
|
||||
/*
|
||||
* This is the old way of doing the same thing as
|
||||
* [connection:shouldMakeNewConnection:]
|
||||
* It is obsolete - don't use it.
|
||||
*/
|
||||
- (BOOL) makeNewConnection: (NSConnection*)newConnection
|
||||
sender: (NSConnection*)parent;
|
||||
|
||||
/*
|
||||
* If the delegate responds to this method, it will be used to ask the
|
||||
* delegate's permission to establish a new connection from the old one.
|
||||
* Often this is used so that the delegate can register for invalidation
|
||||
* notification on new child connections.
|
||||
* This is a GNUstep extension
|
||||
* Normally return newConn.
|
||||
*/
|
||||
- (NSConnection*) connection: (NSConnection*)ancestorConn
|
||||
didConnect: (NSConnection*)newConn;
|
||||
|
||||
/*
|
||||
* These are like the MacOS-X delegate methods, except that we provide the
|
||||
* components in mutable arrays, so that the delegate can alter the data
|
||||
* items in the array. Of course, you must do that WITH CARE.
|
||||
*/
|
||||
- (BOOL) authenticateComponents: (NSMutableArray*)components
|
||||
withData: (NSData*)authenticationData;
|
||||
- (NSData*) authenticationDataForComponents: (NSMutableArray*)components;
|
||||
|
||||
@end
|
||||
|
||||
@interface Object (NSPortCoder)
|
||||
- (Class) classForPortCoder;
|
||||
/*
|
||||
* Must return the class that will be created on the remote side
|
||||
* of the connection. If the class to be created is not the same
|
||||
* as that of the object returned by replacementObjectForPortCoder:
|
||||
* then the class must be capable of recognising the object it
|
||||
* actually gets in its initWithCoder: method.
|
||||
* The default operation is to return NSDistantObject unless the
|
||||
* object is being sent bycopy, in which case the objects actual
|
||||
* class is returned. To force bycopy operation the object should
|
||||
* return its own class.
|
||||
*/
|
||||
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder;
|
||||
/*
|
||||
* This message is sent to an object about to be encoded for sending
|
||||
* over the wire. The default action is to return an NSDistantObject
|
||||
* which is a local proxy for the object unless the object is being
|
||||
* sent bycopy, in which case the actual object is returned.
|
||||
* To force bycopy, an object should return itsself.
|
||||
*/
|
||||
|
||||
@end
|
||||
|
||||
#define CONNECTION_DEFAULT_TIMEOUT 15.0 /* in seconds */
|
||||
|
||||
/*
|
||||
* NSRunLoop mode, NSNotification name and NSException strings.
|
||||
*/
|
||||
GS_EXPORT NSString *NSConnectionReplyMode;
|
||||
GS_EXPORT NSString *NSConnectionDidDieNotification;
|
||||
GS_EXPORT NSString *NSConnectionDidInitializeNotification; /* OPENSTEP */
|
||||
GS_EXPORT NSString *NSFailedAuthenticationException; /* MacOS-X */
|
||||
|
||||
#endif /* __NSConnection_h_GNUSTEP_BASE_INCLUDE */
|
||||
#else
|
||||
/* Interface for GNU Objective-C version of NSConnection
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
Original by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Version for OPENSTEP by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Created: August 1997
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __NSConnection_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __NSConnection_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSTimer.h>
|
||||
#include <Foundation/NSRunLoop.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@class NSDistantObject;
|
||||
@class NSPort;
|
||||
@class NSData;
|
||||
|
||||
/*
|
||||
* Keys for the NSDictionary returned by [NSConnection -statistics]
|
||||
*/
|
||||
/* These in OPENSTEP 4.2 */
|
||||
GS_EXPORT NSString *NSConnectionRepliesReceived;
|
||||
GS_EXPORT NSString *NSConnectionRepliesSent;
|
||||
GS_EXPORT NSString *NSConnectionRequestsReceived;
|
||||
GS_EXPORT NSString *NSConnectionRequestsSent;
|
||||
/* These Are GNUstep extras */
|
||||
GS_EXPORT NSString *NSConnectionLocalCount; /* Objects sent out */
|
||||
GS_EXPORT NSString *NSConnectionProxyCount; /* Objects received */
|
||||
|
||||
|
||||
/*
|
||||
* NSConnection class interface.
|
||||
*
|
||||
* A few methods are in the specification but not yet implemented.
|
||||
*/
|
||||
@interface NSConnection : NSObject
|
||||
{
|
||||
@private
|
||||
BOOL is_valid;
|
||||
BOOL independent_queueing;
|
||||
unsigned request_depth;
|
||||
NSPort *receive_port;
|
||||
NSPort *send_port;
|
||||
unsigned message_count;
|
||||
unsigned req_out_count;
|
||||
unsigned req_in_count;
|
||||
unsigned rep_out_count;
|
||||
unsigned rep_in_count;
|
||||
NSMapTable *local_objects;
|
||||
NSMapTable *local_targets;
|
||||
NSMapTable *remote_proxies;
|
||||
NSTimeInterval reply_timeout;
|
||||
NSTimeInterval request_timeout;
|
||||
Class receive_port_class;
|
||||
Class send_port_class;
|
||||
Class encoding_class;
|
||||
id delegate;
|
||||
NSMutableArray *request_modes;
|
||||
}
|
||||
|
||||
+ (NSArray*) allConnections;
|
||||
+ (NSConnection*) connectionWithRegisteredName: (NSString*)n
|
||||
host: (NSString*)h;
|
||||
+ (id)currentConversation;
|
||||
+ (NSConnection*) defaultConnection;
|
||||
+ (NSDistantObject*) rootProxyForConnectionWithRegisteredName: (NSString*)name
|
||||
host: (NSString*)host;
|
||||
|
||||
- (void) addRequestMode: (NSString*)mode;
|
||||
- (void) addRunLoop: (NSRunLoop *)runloop;
|
||||
- (id) delegate;
|
||||
- (void) enableMultipleThreads;
|
||||
- (BOOL) multipleThreadsEnabled;
|
||||
- (BOOL) independentConversationQueueing;
|
||||
- (void) invalidate;
|
||||
- (BOOL) isValid;
|
||||
- (BOOL) registerName: (NSString*)name;
|
||||
- (NSArray *) remoteObjects;
|
||||
- (void) removeRequestMode: (NSString*)mode;
|
||||
- (void) removeRunLoop: (NSRunLoop *)runloop;
|
||||
- (NSTimeInterval) replyTimeout;
|
||||
- (NSArray*) requestModes;
|
||||
- (NSTimeInterval) requestTimeout;
|
||||
- (id) rootObject;
|
||||
- (NSDistantObject*) rootProxy;
|
||||
- (void) setDelegate: anObj;
|
||||
- (void) setIndependentConversationQueueing: (BOOL)flag;
|
||||
- (void) setReplyTimeout: (NSTimeInterval)seconds;
|
||||
- (void) setRequestMode: (NSString*)mode;
|
||||
- (void) setRequestTimeout: (NSTimeInterval)seconds;
|
||||
- (void) setRootObject: anObj;
|
||||
- (NSDictionary*) statistics;
|
||||
@end
|
||||
|
||||
|
||||
/*
|
||||
* This catagory contains methods which were not in the original
|
||||
* OpenStep specification, but which are in OPENSTEP.
|
||||
* Some methods are not yet implemented.
|
||||
*/
|
||||
@interface NSConnection (OPENSTEP)
|
||||
+ (NSConnection*) connectionWithReceivePort: (NSPort*)r
|
||||
sendPort: (NSPort*)s;
|
||||
- initWithReceivePort: (NSPort*)r
|
||||
sendPort: (NSPort*)s;
|
||||
- (NSPort*) receivePort;
|
||||
- (void) runInNewThread;
|
||||
- (NSPort*) sendPort;
|
||||
@end
|
||||
|
||||
|
||||
/*
|
||||
* This catagory contains legacy methods from the original GNU 'Connection'
|
||||
* class, and useful extensions to NSConnection.
|
||||
*/
|
||||
@interface NSConnection (GNUstepExtensions) <GCFinalization>
|
||||
|
||||
- (void) gcFinalize;
|
||||
|
||||
/* Setting and getting class configuration */
|
||||
+ (Class) defaultReceivePortClass;
|
||||
+ (void) setDefaultReceivePortClass: (Class) aPortClass;
|
||||
+ (Class) defaultSendPortClass;
|
||||
+ (void) setDefaultSendPortClass: (Class) aPortClass;
|
||||
+ (Class) defaultProxyClass;
|
||||
+ (void) setDefaultProxyClass: (Class) aClass;
|
||||
+ (int) defaultOutTimeout;
|
||||
+ (void) setDefaultOutTimeout: (int)to;
|
||||
+ (int) defaultInTimeout;
|
||||
+ (void) setDefaultInTimeout: (int)to;
|
||||
|
||||
/* Querying the state of all the connections */
|
||||
+ (int) messagesReceived;
|
||||
+ (unsigned) connectionsCount;
|
||||
+ (unsigned) connectionsCountWithInPort: (NSPort*)aPort;
|
||||
|
||||
/* Registering your server object on the network.
|
||||
These methods create a new connection object that must be "run" in order
|
||||
to start handling requests from clients.
|
||||
These method names may change when we get the capability to register
|
||||
ports with names after the ports have been created. */
|
||||
/* I want the second method name to clearly indicate that we're not
|
||||
connecting to a pre-existing registration name, we're registering a
|
||||
new name, and this method will fail if that name has already been
|
||||
registered. This is why I don't like "newWithRegisteredName:" ---
|
||||
it's unclear if we're connecting to another NSConnection that already
|
||||
registered with that name. */
|
||||
+ (NSConnection*) newWithRootObject: anObj;
|
||||
+ (NSConnection*) newRegisteringAtName: (NSString*)n
|
||||
withRootObject: anObj;
|
||||
+ (NSConnection*) newRegisteringAtName: (NSString*)n
|
||||
atPort: (int)portn
|
||||
withRootObject: anObj;
|
||||
|
||||
+ (NSConnection*) connectionByOutPort: (NSPort*)aPort;
|
||||
/* Get a proxy to a remote server object.
|
||||
A new connection is created if necessary. */
|
||||
+ (NSDistantObject*) rootProxyAtName: (NSString*)name onHost: (NSString*)host;
|
||||
+ (NSDistantObject*) rootProxyAtName: (NSString*)name;
|
||||
+ (NSDistantObject*) rootProxyAtPort: (NSPort*)anOutPort;
|
||||
+ (NSDistantObject*) rootProxyAtPort: (NSPort*)anOutPort withInPort: (NSPort*)anInPort;
|
||||
|
||||
/* This is the designated initializer for the NSConnection class.
|
||||
You don't need to call it yourself. */
|
||||
+ (NSConnection*) newForInPort: (NSPort*)anInPort outPort: (NSPort*)anOutPort
|
||||
ancestorConnection: (NSConnection*)ancestor;
|
||||
|
||||
/* Make a connection object start listening for incoming requests. After
|
||||
after DATE. */
|
||||
- (void) runConnectionUntilDate: date;
|
||||
|
||||
/* Same as above, but never time out. */
|
||||
- (void) runConnection;
|
||||
|
||||
/* When you get an invalidation notification from a connection, use
|
||||
this method in order to find out if any of the proxy objects you're
|
||||
using are going away. */
|
||||
- (id) proxies;
|
||||
|
||||
|
||||
/* For getting the root object of a connection or port */
|
||||
+ rootObjectForInPort: (NSPort*)aPort;
|
||||
|
||||
/* Used for setting the root object of a connection that we
|
||||
created without one, or changing the root object of a connection
|
||||
that already has one. */
|
||||
+ (void) setRootObject: anObj forInPort: (NSPort*)aPort;
|
||||
|
||||
/* Querying and setting some instance variables */
|
||||
- (Class) receivePortClass;
|
||||
- (Class) sendPortClass;
|
||||
- (void) setReceivePortClass: (Class)aPortClass;
|
||||
- (void) setSendPortClass: (Class)aPortClass;
|
||||
- (Class) proxyClass;
|
||||
- (Class) encodingClass;
|
||||
- (Class) decodingClass;
|
||||
|
||||
|
||||
/* Only subclassers and power-users need worry about these */
|
||||
- (void) addProxy: (NSDistantObject*)aProxy;
|
||||
- (id) includesProxyForTarget: (gsu32)target;
|
||||
- (void) removeProxy: (NSDistantObject*)aProxy;
|
||||
|
||||
// It seems to be a non pure-OPENSTEP definition...
|
||||
//
|
||||
// new def :
|
||||
- (NSArray*)localObjects;
|
||||
- (void) addLocalObject: anObj;
|
||||
- (id) includesLocalObject: anObj;
|
||||
- (void) removeLocalObject: anObj;
|
||||
- (retval_t) forwardForProxy: (NSDistantObject*)object
|
||||
selector: (SEL)sel
|
||||
argFrame: (arglist_t)frame;
|
||||
- (const char *) typeForSelector: (SEL)sel remoteTarget: (unsigned)target;
|
||||
|
||||
@end
|
||||
|
||||
GS_EXPORT NSString *ConnectionBecameInvalidNotification;
|
||||
|
||||
@interface Object (NSConnectionDelegate)
|
||||
- (BOOL) connection: (NSConnection*)parent
|
||||
shouldMakeNewConnection: (NSConnection*)newConnection;
|
||||
/*
|
||||
* This method may be used to ask a delegates permission to create
|
||||
* a new connection from the old one.
|
||||
* This method should be implemented in preference to the
|
||||
* [makeNewConnection:sender:] which is obsolete.
|
||||
*/
|
||||
- (BOOL) makeNewConnection: (NSConnection*)newConnection
|
||||
sender: (NSConnection*)parent;
|
||||
/*
|
||||
* This is the old way of doing the same thing as
|
||||
* [connection:shouldMakeNewConnection:]
|
||||
* It is obsolete - don't use it.
|
||||
*/
|
||||
- (NSConnection*) connection: ancestorConn didConnect: newConn;
|
||||
/*
|
||||
* If the delegate responds to this method, it will be used to ask the
|
||||
* delegate's permission to establish a new connection from the old one.
|
||||
* Often this is used so that the delegate can register for invalidation
|
||||
* notification on new child connections.
|
||||
* This is a GNUstep extension
|
||||
* Normally return newConn.
|
||||
*/
|
||||
@end
|
||||
|
||||
@interface Object (NSPortCoder)
|
||||
- (Class) classForPortCoder;
|
||||
/*
|
||||
* Must return the class that will be created on the remote side
|
||||
* of the connection. If the class to be created is not the same
|
||||
* as that of the object returned by replacementObjectForPortCoder:
|
||||
* then the class must be capable of recognising the object it
|
||||
* actually gets in its initWithCoder: method.
|
||||
* The default operation is to return NSDistantObject unless the
|
||||
* object is being sent bycopy, in which case the objects actual
|
||||
* class is returned. To force bycopy operation the object should
|
||||
* return its own class.
|
||||
*/
|
||||
- (id) replacementObjectForPortCoder: (NSPortCoder*)aCoder;
|
||||
/*
|
||||
* This message is sent to an object about to be encoded for sending
|
||||
* over the wire. The default action is to return an NSDistantObject
|
||||
* which is a local proxy for the object unless the object is being
|
||||
* sent bycopy, in which case the actual object is returned.
|
||||
* To force bycopy, an object should return itsself.
|
||||
*/
|
||||
|
||||
|
||||
- (BOOL)authenticateComponents: (NSArray *)components
|
||||
withData: (NSData *)authenticationData;
|
||||
- (NSData *)authenticationDataForComponents: (NSArray *)components;
|
||||
|
||||
@end
|
||||
|
||||
#define CONNECTION_DEFAULT_TIMEOUT 15.0 /* in seconds */
|
||||
|
||||
/*
|
||||
* NSRunLoop mode, NSNotification name and NSException strings.
|
||||
*/
|
||||
GS_EXPORT NSString *NSConnectionReplyMode;
|
||||
GS_EXPORT NSString *NSConnectionDidDieNotification;
|
||||
GS_EXPORT NSString *NSConnectionDidInitializeNotification; /* OPENSTEP */
|
||||
|
||||
/*
|
||||
* For compatibility with old GNU DO code -
|
||||
*/
|
||||
#define RunLoopConnectionReplyMode NSConnectionReplyMode
|
||||
#define ConnectionBecameInvalidNotification NSConnectionDidDieNotification
|
||||
#define ConnectionWasCreatedNotification NSConnectionDidInitializeNotification
|
||||
|
||||
#endif /* __NSConnection_h_GNUSTEP_BASE_INCLUDE */
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -1,147 +0,0 @@
|
|||
/* Interface for NSPortCoder object for distributed objects
|
||||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Date: June 2000
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __NSPortCoder_h
|
||||
#define __NSPortCoder_h
|
||||
|
||||
#include <Foundation/NSCoder.h>
|
||||
|
||||
@class NSMutableArray;
|
||||
@class NSMutableDictionary;
|
||||
@class NSConnection;
|
||||
@class NSPort;
|
||||
|
||||
@interface NSPortCoder : NSCoder
|
||||
{
|
||||
@private
|
||||
NSMutableArray *_comp;
|
||||
NSConnection *_conn;
|
||||
BOOL _is_by_copy;
|
||||
BOOL _is_by_ref;
|
||||
// Encoding
|
||||
BOOL _encodingRoot;
|
||||
BOOL _initialPass;
|
||||
id _dst; /* Serialization destination. */
|
||||
IMP _eObjImp; /* Method to encode an id. */
|
||||
IMP _eValImp; /* Method to encode others. */
|
||||
#ifndef _IN_PORT_CODER_M
|
||||
#define GSIMapTable void*
|
||||
#endif
|
||||
GSIMapTable _clsMap; /* Class cross references. */
|
||||
GSIMapTable _cIdMap; /* Conditionally coded. */
|
||||
GSIMapTable _uIdMap; /* Unconditionally coded. */
|
||||
GSIMapTable _ptrMap; /* Constant pointers. */
|
||||
#ifndef _IN_PORT_CODER_M
|
||||
#undef GSIMapTable
|
||||
#endif
|
||||
unsigned _xRefC; /* Counter for cross-reference. */
|
||||
unsigned _xRefO; /* Counter for cross-reference. */
|
||||
unsigned _xRefP; /* Counter for cross-reference. */
|
||||
// Decoding
|
||||
id _src; /* Deserialization source. */
|
||||
IMP _dDesImp; /* Method to deserialize with. */
|
||||
void (*_dTagImp)(id,SEL,unsigned char*,unsigned*,unsigned*);
|
||||
IMP _dValImp; /* Method to decode data with. */
|
||||
#ifndef _IN_PORT_CODER_M
|
||||
#define GSIArray void*
|
||||
#endif
|
||||
GSIArray _clsAry; /* Class crossreference map. */
|
||||
GSIArray _objAry; /* Object crossreference map. */
|
||||
GSIArray _ptrAry; /* Pointer crossreference map. */
|
||||
#ifndef _IN_PORT_CODER_M
|
||||
#undef GSIArray
|
||||
#endif
|
||||
NSMutableDictionary *_cInfo; /* Class version information. */
|
||||
unsigned _cursor; /* Position in data buffer. */
|
||||
unsigned _version; /* Version of archiver used. */
|
||||
NSZone *_zone; /* Zone for allocating objs. */
|
||||
}
|
||||
|
||||
+ (NSPortCoder*) portCoderWithReceivePort: (NSPort*)recv
|
||||
sendPort: (NSPort*)send
|
||||
components: (NSArray*)comp;
|
||||
- (id) initWithReceivePort: (NSPort*)recv
|
||||
sendPort: (NSPort*)send
|
||||
components: (NSArray*)comp;
|
||||
|
||||
- (NSConnection*) connection;
|
||||
- (NSPort*) decodePortObject;
|
||||
- (void) dispatch;
|
||||
- (void) encodePortObject: (NSPort*)aPort;
|
||||
- (BOOL) isBycopy;
|
||||
- (BOOL) isByref;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSPortCoder (Private)
|
||||
- (NSMutableArray*) _components;
|
||||
@end
|
||||
|
||||
|
||||
#endif /* __NSPortCoder_h */
|
||||
#else
|
||||
/* Interface for NSPortCoder object for distributed objects
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Date: August 1997
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __NSPortCoder_h
|
||||
#define __NSPortCoder_h
|
||||
|
||||
#include <Foundation/NSCoder.h>
|
||||
|
||||
@class NSConnection;
|
||||
@class NSPort;
|
||||
|
||||
@interface NSPortCoder : NSCoder
|
||||
{
|
||||
}
|
||||
|
||||
- (NSConnection*) connection;
|
||||
- (NSPort*) decodePortObject;
|
||||
- (void) encodePortObject: (NSPort*)aPort;
|
||||
- (BOOL) isBycopy;
|
||||
- (BOOL) isByref;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif /* __NSPortCoder_h */
|
2437
Old/OldNSPortCoder.m
2437
Old/OldNSPortCoder.m
File diff suppressed because it is too large
Load diff
|
@ -1,65 +0,0 @@
|
|||
/* Protocol for Objective-C objects that hold elements, user gets to set order
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: 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.
|
||||
*/
|
||||
|
||||
/* The <OrderedCollecting> protocol inherits from the
|
||||
<KeyedCollecting> protocol.
|
||||
|
||||
The <OrderedCollecting> protocol defines the interface to a
|
||||
collection of elements that are accessible by a key that is an index,
|
||||
where the indeces in a collection are a contiguous series of unsigned
|
||||
integers beginning at 0. This is the root of the protocol heirarchy
|
||||
for all collections that hold their elements in some order. Elements
|
||||
may be accessed, inserted, replaced and removed by their index.
|
||||
*/
|
||||
|
||||
#ifndef __OrderedCollecting_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __OrderedCollecting_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/IndexedCollecting.h>
|
||||
|
||||
@protocol OrderedCollecting <IndexedCollecting>
|
||||
|
||||
// ADDING;
|
||||
- (void) insertObject: newObject atIndex: (unsigned)index;
|
||||
- (void) insertObject: newObject before: oldObject;
|
||||
- (void) insertObject: newObject after: oldObject;
|
||||
- (void) insertContentsOf: (id <ConstantCollecting>)aCollection
|
||||
atIndex: (unsigned)index;
|
||||
- (void) appendObject: newObject;
|
||||
- (void) prependObject: newObject;
|
||||
- (void) appendContentsOf: (id <ConstantCollecting>)aCollection;
|
||||
- (void) prependContentsOf: (id <ConstantCollecting>)aCollection;
|
||||
|
||||
// SWAPPING AND SORTING
|
||||
- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2;
|
||||
- (void) sortContents;
|
||||
|
||||
// REPLACING;
|
||||
- (void) replaceRange: (IndexRange)aRange
|
||||
with: (id <ConstantCollecting>)aCollection;
|
||||
- replaceRange: (IndexRange)aRange
|
||||
using: (id <ConstantCollecting>)aCollection;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __OrderedCollecting_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,38 +0,0 @@
|
|||
/* Interface for Objective-C Ordered Collection object.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 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.
|
||||
*/
|
||||
|
||||
#ifndef __OrderedCollection_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __OrderedCollection_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/IndexedCollection.h>
|
||||
#include <base/OrderedCollecting.h>
|
||||
|
||||
@interface OrderedCollection : IndexedCollection
|
||||
@end
|
||||
|
||||
|
||||
/* Put this on category instead of class to avoid bogus complaint from gcc */
|
||||
@interface OrderedCollection (Protocol) <OrderedCollecting>
|
||||
@end
|
||||
|
||||
#endif /* __OrderedCollection_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,47 +0,0 @@
|
|||
/* Protocol for Objective-C objects that can be ordered.
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __Ordering_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Ordering_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol Ordering
|
||||
|
||||
- (int) compare: anObject;
|
||||
|
||||
- (BOOL) greaterThan: anObject;
|
||||
- (BOOL) greaterThanOrEqual: anObject;
|
||||
|
||||
- (BOOL) lessThan: anObject;
|
||||
- (BOOL) lessThanOrEqual: anObject;
|
||||
|
||||
- (BOOL) between: firstObject and: secondObject;
|
||||
|
||||
- maximum: anObject;
|
||||
- minimum: anObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Ordering_h_GNUSTEP_BASE_INCLUDE */
|
119
Old/Port.h
119
Old/Port.h
|
@ -1,119 +0,0 @@
|
|||
/* Interface for abstract superclass port for use with Connection
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: 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.
|
||||
*/
|
||||
|
||||
#ifndef __Port_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Port_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coding.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <Foundation/NSPort.h>
|
||||
#include <Foundation/NSDate.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
/* xxx Use something like this? */
|
||||
@protocol PacketSending
|
||||
@end
|
||||
|
||||
@interface Port : NSPort
|
||||
{
|
||||
}
|
||||
- (void) close;
|
||||
|
||||
+ (Class) outPacketClass;
|
||||
- (Class) outPacketClass;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface InPort : Port
|
||||
{
|
||||
id _packet_invocation;
|
||||
}
|
||||
|
||||
+ newForReceiving;
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name;
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name fromPort: (int)port;
|
||||
|
||||
/* Register/Unregister this port for input handling through RunLoop
|
||||
RUN_LOOP in mode MODE. */
|
||||
- (void) addToRunLoop: run_loop forMode: (NSString*)mode;
|
||||
- (void) removeFromRunLoop: run_loop forMode: (NSString*)mode;
|
||||
|
||||
/* When a RunLoop is handling this InPort, and a new incoming
|
||||
packet arrives, INVOCATION will be invoked with the new packet
|
||||
as an argument. The INVOCATION is responsible for releasing
|
||||
the packet. */
|
||||
- (void) setReceivedPacketInvocation: (id)invocation;
|
||||
|
||||
/* An alternative to the above way for receiving packets from this port.
|
||||
Get a packet from the net and return it. If no packet is received
|
||||
within MILLISECONDS, then return nil. The caller is responsible
|
||||
for releasing the packet. */
|
||||
- receivePacketWithTimeout: (int)milliseconds;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OutPort : Port
|
||||
|
||||
+ newForSendingToRegisteredName: (NSString*)name
|
||||
onHost: (NSString*)hostname;
|
||||
- (BOOL) sendPacket: packet timeout: (NSTimeInterval)t;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* Objects for holding incoming/outgoing data to/from ports. */
|
||||
|
||||
@interface InPacket : MemoryStream
|
||||
{
|
||||
id _receiving_in_port;
|
||||
id _reply_out_port;
|
||||
}
|
||||
|
||||
- replyOutPort;
|
||||
- receivingInPort;
|
||||
|
||||
/* Do not call this method yourself; it is to be called by subclassers.
|
||||
InPackets are created for you by the InPort object, and are
|
||||
made available as the argument to the received packet invocation. */
|
||||
- initForReceivingWithCapacity: (unsigned)s
|
||||
receivingInPort: ip
|
||||
replyOutPort: op;
|
||||
|
||||
@end
|
||||
|
||||
@interface OutPacket : MemoryStream
|
||||
{
|
||||
id _reply_in_port;
|
||||
}
|
||||
|
||||
- initForSendingWithCapacity: (unsigned)c
|
||||
replyInPort: p;
|
||||
- replyInPort;
|
||||
|
||||
+ (unsigned) prefixSize;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Port_h_GNUSTEP_BASE_INCLUDE */
|
210
Old/Port.m
210
Old/Port.m
|
@ -1,210 +0,0 @@
|
|||
/* Implementation of abstract superclass port for use with Connection
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: 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/Port.h>
|
||||
#include <base/Coder.h> /* for Coding protocol in Object category */
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
@implementation Port
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_is_valid = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
+ (Class) outPacketClass
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) outPacketClass
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) classForPortCoder
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy,
|
||||
i.e. as our own class, not a Proxy class. */
|
||||
return [self class];
|
||||
}
|
||||
- replacementObjectForPortCoder: aRmc
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)anEncoder
|
||||
{
|
||||
[super encodeWithCoder: anEncoder];
|
||||
/* xxx What else? */
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
/* xxx What else? */
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation InPort
|
||||
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_packet_invocation = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name fromPort: (int)port
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ newForReceiving
|
||||
{
|
||||
return [self newForReceivingFromRegisteredName: nil];
|
||||
}
|
||||
|
||||
- receivePacketWithTimeout: (int)milliseconds
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) setReceivedPacketInvocation: (id)invocation
|
||||
{
|
||||
NSAssert(!_packet_invocation, NSInternalInconsistencyException);
|
||||
_packet_invocation = invocation;
|
||||
}
|
||||
|
||||
- (void) addToRunLoop: run_loop forMode: (NSString*)mode
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) removeFromRunLoop: run_loop forMode: (NSString*)mode
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OutPort
|
||||
|
||||
+ newForSendingToRegisteredName: (NSString*)name
|
||||
onHost: (NSString*)hostname
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL) sendPacket: packet timeout: (NSTimeInterval)t
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation InPacket
|
||||
|
||||
/* The designated initializer. */
|
||||
- initForReceivingWithCapacity: (unsigned)c
|
||||
receivingInPort: ip
|
||||
replyOutPort: op
|
||||
{
|
||||
self = [super initWithCapacity: c prefix: 0];
|
||||
if (self)
|
||||
{
|
||||
NSAssert([op isValid], NSInternalInconsistencyException);
|
||||
NSAssert(!ip || [ip isValid], NSInternalInconsistencyException);
|
||||
_reply_out_port = op;
|
||||
_receiving_in_port = ip;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- replyOutPort
|
||||
{
|
||||
return _reply_out_port;
|
||||
}
|
||||
|
||||
- receivingInPort
|
||||
{
|
||||
return _receiving_in_port;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OutPacket
|
||||
|
||||
/* The designated initializer. */
|
||||
- initForSendingWithCapacity: (unsigned)c
|
||||
replyInPort: ip
|
||||
{
|
||||
self = [super initWithCapacity: c prefix: [[self class] prefixSize]];
|
||||
if (self)
|
||||
{
|
||||
NSAssert([ip isValid], NSInternalInconsistencyException);
|
||||
_reply_in_port = ip;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (unsigned) prefixSize
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- replyInPort
|
||||
{
|
||||
return _reply_in_port;
|
||||
}
|
||||
|
||||
@end
|
||||
|
36
Old/Queue.h
36
Old/Queue.h
|
@ -1,36 +0,0 @@
|
|||
/* Interface 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.
|
||||
*/
|
||||
|
||||
#ifndef __Queue_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Queue_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/CircularArray.h>
|
||||
|
||||
@interface Queue : CircularArray
|
||||
|
||||
- (void) enqueueObject: newObject;
|
||||
- dequeueObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Queue_h_GNUSTEP_BASE_INCLUDE */
|
48
Old/Queue.m
48
Old/Queue.m
|
@ -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
|
39
Old/RBTree.h
39
Old/RBTree.h
|
@ -1,39 +0,0 @@
|
|||
/* Interface for Objective-C Red-Black Tree collection 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.
|
||||
*/
|
||||
|
||||
#ifndef __RBTree_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RBTree_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/BinaryTree.h>
|
||||
|
||||
@protocol RBTreeComprising <BinaryTreeComprising>
|
||||
- (BOOL) isRed;
|
||||
- setRed;
|
||||
- setBlack;
|
||||
@end
|
||||
|
||||
@interface RBTree : BinaryTree
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __RBTree_h_GNUSTEP_BASE_INCLUDE */
|
250
Old/RBTree.m
250
Old/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,36 +0,0 @@
|
|||
/* Interface for Objective-C RBTreeNode 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.
|
||||
*/
|
||||
|
||||
#ifndef __RBTreeNode_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RBTreeNode_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/BinaryTreeNode.h>
|
||||
#include <base/RBTree.h>
|
||||
|
||||
@interface RBTreeNode : BinaryTreeNode <RBTreeComprising>
|
||||
{
|
||||
BOOL _red;
|
||||
}
|
||||
@end
|
||||
|
||||
#endif /* __RBTreeNode_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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
|
16
Old/README
16
Old/README
|
@ -1,16 +0,0 @@
|
|||
|
||||
* WARNING *
|
||||
This directory contains code that does not (and is not intended to) build.
|
||||
* WARNING *
|
||||
|
||||
The source code here is obsolete - mostly from the original libObjects library
|
||||
that was used as a basis for GNUstep-base. The GNUstep base library has been
|
||||
almost entirely rewritten since this code was used!
|
||||
|
||||
The files have been preserved in case we want to use them at some point,
|
||||
as the basis/inspiration for an additional library.
|
||||
|
||||
They are NOT part of GNUstep-base proper and are not supported in any way,
|
||||
they are also unlikely to be preserved indefinately, and will probably be
|
||||
removed from the CVS repository at some point.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
/* Interface for additive congruential pseudo-random num generating
|
||||
Copyright (C) 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.
|
||||
*/
|
||||
|
||||
/* Additive Congruential Method,
|
||||
from Robert Sedgewick, "Algorithms" */
|
||||
|
||||
#ifndef __RNGAdditiveCongruential_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RNGAdditiveCongruential_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/RandomGenerating.h>
|
||||
|
||||
@interface RNGAdditiveCongruential : NSObject <RandomGenerating>
|
||||
{
|
||||
long *table;
|
||||
int table_size;
|
||||
int tap1;
|
||||
int tap2;
|
||||
int index;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __RNGAdditiveCongruential_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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,73 +0,0 @@
|
|||
/* Interface for Berkeley random()-compatible generation for Objective-C
|
||||
|
||||
Reworked 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.
|
||||
*/
|
||||
|
||||
#ifndef __RNGBerkeley_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RNGBerkeley_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983 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 <base/RandomGenerating.h>
|
||||
|
||||
@interface RNGBerkeley : NSObject <RandomGenerating>
|
||||
{
|
||||
int foo[2];
|
||||
long int randtbl[32]; /* Size must match DEG_3 + 1 from RNGBerkeley.m */
|
||||
long int *fptr;
|
||||
long int *rptr;
|
||||
long int *state;
|
||||
int rand_type;
|
||||
int rand_deg;
|
||||
int rand_sep;
|
||||
long int *end_ptr;
|
||||
}
|
||||
|
||||
- (void) _srandom: (unsigned int)x;
|
||||
- (void*) _initstateSeed: (unsigned int)seed
|
||||
state: (void*)arg_state
|
||||
size: (size_t)n;
|
||||
- (void*) _setstate: (void*)arg_state;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __RNGBerkeley_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -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
|
68
Old/Random.h
68
Old/Random.h
|
@ -1,68 +0,0 @@
|
|||
/* Interface for Objective-C object providing randoms in uniform distribution
|
||||
Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef __Random_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Random_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/RandomGenerating.h>
|
||||
|
||||
@interface Random : NSObject
|
||||
{
|
||||
id <RandomGenerating> rng;
|
||||
}
|
||||
|
||||
+ initialize;
|
||||
+ (id <RandomGenerating>) defaultRandomGeneratorClass;
|
||||
+ setDefaultRandomGeneratorClass: (id <RandomGenerating>)aRNG;
|
||||
|
||||
+ (float) chiSquareOfRandomGenerator: (id <RandomGenerating>)aRNG
|
||||
iterations: (int)n
|
||||
range: (long)r;
|
||||
+ (float) chiSquareOfRandomGenerator: (id <RandomGenerating>)aRNG;
|
||||
|
||||
- init;
|
||||
|
||||
- setRandomSeedFromClock;
|
||||
- setRandomSeed: (long)seed;
|
||||
|
||||
- (long) randomInt;
|
||||
- (long) randomIntBetween: (long)lowBound and: (long)highBound;
|
||||
- (long) randomDie: (long)numSides; /* between 0 and numSides-1 */
|
||||
|
||||
- (BOOL) randomCoin;
|
||||
- (BOOL) randomCoinWithProbability: (double)p;
|
||||
|
||||
- (float) randomFloat;
|
||||
- (float) randomFloatBetween: (float)lowBound and: (float)highBound;
|
||||
- (float) randomFloatProbability;
|
||||
|
||||
- (double) randomDouble;
|
||||
- (double) randomDoubleBetween: (double)lowBound and: (double)highBound;
|
||||
- (double) randomDoubleProbability;
|
||||
|
||||
- read: (TypedStream*)aStream;
|
||||
- write: (TypedStream*)aStream;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Random_h_GNUSTEP_BASE_INCLUDE */
|
306
Old/Random.m
306
Old/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
|
|
@ -1,36 +0,0 @@
|
|||
/* Protocol for Objective-C objects that generate random bits
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __RandomGenerating_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RandomGenerating_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol RandomGenerating <NSObject, NSCoding>
|
||||
|
||||
- (void) setRandomSeed: (long)seed;
|
||||
- (long) nextRandom;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __RandomGenerating_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,36 +0,0 @@
|
|||
/* Interface for GNU Objective-C raw stream object for archiving
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 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.
|
||||
*/
|
||||
|
||||
#ifndef __RawCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RawCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStream.h>
|
||||
|
||||
@interface RawCStream : CStream
|
||||
|
||||
+ setDebugging: (BOOL)f;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __RawCStream_h_GNUSTEP_BASE_INCLUDE */
|
296
Old/RawCStream.m
296
Old/RawCStream.m
|
@ -1,296 +0,0 @@
|
|||
/* Implementation of GNU Objective-C raw-binary stream for archiving
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 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.
|
||||
*/
|
||||
|
||||
/* Use this CStream subclass when you are encoding/decoding on the
|
||||
same architecture, and you care about time and space.
|
||||
WARNING: This encoding is *not* machine-independent. */
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/RawCStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <base/NSException.h>
|
||||
|
||||
#define DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
@implementation RawCStream
|
||||
|
||||
|
||||
/* For debugging */
|
||||
|
||||
static BOOL debug_binary_coder;
|
||||
|
||||
+ setDebugging: (BOOL)f
|
||||
{
|
||||
debug_binary_coder = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ debugStderrCoder
|
||||
{
|
||||
static id c = nil;
|
||||
|
||||
if (!c)
|
||||
c = [[TextCStream alloc]
|
||||
initForWritingToStream: [StdioStream standardError]];
|
||||
return c;
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*) name
|
||||
{
|
||||
if (debug_binary_coder)
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeName:name];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (NSString*) name
|
||||
{
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType:type
|
||||
at:d
|
||||
withName:name];
|
||||
}
|
||||
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to encode an \"ObjC\" type");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
int length = strlen(*(char**)d);
|
||||
[self encodeValueOfCType:@encode(int)
|
||||
at:&length withName:@"BinaryCStream char* length"];
|
||||
[stream writeBytes:*(char**)d length:length];
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream writeByte:*(unsigned char*)d];
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
case _C_USHT:
|
||||
[stream writeBytes:d length:sizeof(short)];
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
case _C_UINT:
|
||||
[stream writeBytes:d length:sizeof(int)];
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
case _C_ULNG:
|
||||
[stream writeBytes:d length:sizeof(long)];
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
[stream writeBytes:d length:sizeof(float)];
|
||||
break;
|
||||
|
||||
case _C_DBL:
|
||||
[stream writeBytes:d length:sizeof(double)];
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi (type+1); /* xxx why +1 ? */
|
||||
int offset;
|
||||
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
/* Change this so we don't re-write type info every time. */
|
||||
[self encodeValueOfCType: type
|
||||
at: d
|
||||
withName: NULL];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self encodeValueOfCType: type
|
||||
at: ((char*)d)+acc_size
|
||||
withName: NULL];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"Unrecognized Type %s", type];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to decode an \"ObjC\" type");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
int length;
|
||||
[self decodeValueOfCType:@encode(int)
|
||||
at:&length withName:NULL];
|
||||
OBJC_MALLOC(*(char**)d, char, length+1);
|
||||
[stream readBytes:*(char**)d length:length];
|
||||
(*(char**)d)[length] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream readByte:d];
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
case _C_USHT:
|
||||
[stream readBytes:d length:sizeof(short)];
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
case _C_UINT:
|
||||
[stream readBytes:d length:sizeof(int)];
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
case _C_ULNG:
|
||||
[stream readBytes:d length:sizeof(long)];
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
[stream readBytes:d length:sizeof(float)];
|
||||
break;
|
||||
|
||||
case _C_DBL:
|
||||
[stream readBytes:d length:sizeof(double)];
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||
int len = atoi(type+1);
|
||||
int offset;
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
[self decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space just like char* ? No. */
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
const char *save_type = type;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self decodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:namePtr];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
type = save_type;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"Unrecognized Type %s", type];
|
||||
}
|
||||
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"decoding unnamed"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *)n
|
||||
{
|
||||
#if 1
|
||||
if (n)
|
||||
*n = nil;
|
||||
#else
|
||||
if (n)
|
||||
*n = [[[NSString alloc] init] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
100
Old/Retaining.h
100
Old/Retaining.h
|
@ -1,100 +0,0 @@
|
|||
/* Protocol for GNU Objective-C objects that can keep a retain count.
|
||||
Copyright (C) 1993,1994 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.
|
||||
*/
|
||||
|
||||
#ifndef __Retaining_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Retaining_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol Retaining
|
||||
|
||||
- retain;
|
||||
|
||||
/* Use this message when the sender did not allocate the receiving
|
||||
object, but the sender wants to keep a reference to the receiving
|
||||
object. It increments a reference count for the object. The
|
||||
object will not be deallocated until after a matching release
|
||||
message is sent to this object.
|
||||
|
||||
IMPORTANT PROGRAMMING CONVENTION: There is no need to send this
|
||||
message to objects that the sender allocated---allocating an object
|
||||
already implies that the object will not be deallocated until the
|
||||
sender releases it. Just as "retain" and "release" messages cancel
|
||||
each other, one "release" message is needed to cancel the original
|
||||
allocation. */
|
||||
|
||||
|
||||
- (oneway void) release;
|
||||
|
||||
/* Use this message when the sender is done with the receiving object.
|
||||
If the sender had the last reference to the object, the object will
|
||||
be deallocated by sending "dealloc" to it.
|
||||
|
||||
IMPORTANT PROGRAMMING CONVENTION: The sender should only send this
|
||||
to objects that it has allocated or has retain'ed. */
|
||||
|
||||
|
||||
- (void) dealloc;
|
||||
|
||||
/* This method deallocates the memory for this object. You should not
|
||||
send this message yourself; it is sent for you by the release
|
||||
method, which properly manages retain counts. Do, however,
|
||||
override this method to deallocate any memory allocated by this
|
||||
object during initialization; the overriding method should call
|
||||
[super dealloc] at the end. */
|
||||
|
||||
|
||||
- (unsigned) retainCount;
|
||||
|
||||
/* This method returns the retain count to this object. It does
|
||||
not, however, include the decrements due to stackRelease's. Note
|
||||
that the returned number is not quite a "reference count" in the
|
||||
traditional sense; it is less by one in that it is actually a count
|
||||
of the number of unreleased retain messages sent. A retainCount of
|
||||
zero implies that there is still one more release necessary to
|
||||
deallocate the receiver. For example, after an object is created,
|
||||
its retainCount is zero, but another "release" message is still
|
||||
required before the object will be deallocated. */
|
||||
|
||||
|
||||
- autorelease;
|
||||
|
||||
/* Use this message when the sender is done with this object, but the
|
||||
sender doesn't want the object to be deallocated immediately
|
||||
because the function that sends this message will use this object
|
||||
as its return value. The object will be queued to receive the
|
||||
actual "release" message later.
|
||||
|
||||
Due to this delayed release, the function that receives the object
|
||||
as a return value will have the opportunity to retain the object
|
||||
before the "release" instigated by the "autorelease" actually
|
||||
takes place.
|
||||
|
||||
For the object to be autoreleased, you must have previously created
|
||||
a AutoreleasePool or an AutoreleaseStack. If you don't, however,
|
||||
your program won't crash, the release corresponding to the
|
||||
autorelease will just never happen. */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Retaining_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef __RunLoop_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RunLoop_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSRunLoop.h>
|
||||
|
||||
#define RunLoop NSRunLoop
|
||||
#define RunLoopDefaultMode NSDefaultRunLoopMode
|
||||
|
||||
#endif /* __RunLoop_h_GNUSTEP_BASE_INCLUDE */
|
52
Old/Set.h
52
Old/Set.h
|
@ -1,52 +0,0 @@
|
|||
/* Interface for Objective-C Set 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.
|
||||
*/
|
||||
|
||||
#ifndef __Set_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Set_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Collection.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
|
||||
@interface Set : Collection
|
||||
{
|
||||
NSHashTable *_contents_hash; // a hashtable to hold the contents;
|
||||
}
|
||||
|
||||
// MANAGING CAPACITY;
|
||||
+ (unsigned) defaultCapacity;
|
||||
|
||||
// INITIALIZING AND FREEING;
|
||||
- initWithCapacity: (unsigned)aCapacity;
|
||||
|
||||
// SET OPERATIONS;
|
||||
- (void) intersectWithCollection: (id <Collecting>)aCollection;
|
||||
- (void) unionWithCollection: (id <Collecting>)aCollection;
|
||||
- (void) differenceWithCollection: (id <Collecting>)aCollection;
|
||||
|
||||
- shallowCopyIntersectWithCollection: (id <Collecting>)aCollection;
|
||||
- shallowCopyUnionWithCollection: (id <Collecting>)aCollection;
|
||||
- shallowCopyDifferenceWithCollection: (id <Collecting>)aCollection;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Set_h_GNUSTEP_BASE_INCLUDE */
|
229
Old/Set.m
229
Old/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,47 +0,0 @@
|
|||
/* Interface 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Splay Tree.
|
||||
Sleator and Tarjan. "Self-adjusting binary search trees."
|
||||
Journal of the ACM, 32(3):652-686, 1985.
|
||||
|
||||
includesObject:, minObject, maxObject, nextObject:, sortAddObject,
|
||||
and removeObject: operations can all be done in O(lg n) amortized time.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SplayTree_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __SplayTree_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/BinaryTree.h>
|
||||
|
||||
@interface SplayTree : BinaryTree
|
||||
{
|
||||
}
|
||||
|
||||
- (void) splayNode: aNode;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __SplayTree_h_GNUSTEP_BASE_INCLUDE */
|
102
Old/SplayTree.m
102
Old/SplayTree.m
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue