mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
Obsolete files
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@7189 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
a051ddd885
commit
cc36fcd0ee
122 changed files with 28849 additions and 0 deletions
41
Old/Archiver.h
Normal file
41
Old/Archiver.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* 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 */
|
38
Old/Archiver.m
Normal file
38
Old/Archiver.m
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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
Normal file
72
Old/Array.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* 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
Normal file
263
Old/Array.m
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
/* 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
|
87
Old/ArrayPrivate.h
Normal file
87
Old/ArrayPrivate.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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
Normal file
50
Old/Bag.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* 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
Normal file
211
Old/Bag.m
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
|
42
Old/BinaryCStream.h
Normal file
42
Old/BinaryCStream.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* 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 */
|
646
Old/BinaryCStream.m
Normal file
646
Old/BinaryCStream.m
Normal file
|
@ -0,0 +1,646 @@
|
||||||
|
/* 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
|
||||||
|
|
76
Old/BinaryTree.h
Normal file
76
Old/BinaryTree.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/* 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
Normal file
607
Old/BinaryTree.m
Normal file
|
@ -0,0 +1,607 @@
|
||||||
|
/* 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
|
40
Old/BinaryTreeNode.h
Normal file
40
Old/BinaryTreeNode.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* 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 */
|
104
Old/BinaryTreeNode.m
Normal file
104
Old/BinaryTreeNode.m
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/* 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
|
||||||
|
|
62
Old/CStream.h
Normal file
62
Old/CStream.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* 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
Normal file
287
Old/CStream.m
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
/* 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
|
59
Old/CStreaming.h
Normal file
59
Old/CStreaming.h
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/* 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 */
|
||||||
|
|
37
Old/CircularArray.h
Normal file
37
Old/CircularArray.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* 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 */
|
197
Old/CircularArray.m
Normal file
197
Old/CircularArray.m
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/* 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
|
||||||
|
|
74
Old/CircularArrayPrivate.h
Normal file
74
Old/CircularArrayPrivate.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/* 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
Normal file
141
Old/Coder.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/* 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
Normal file
310
Old/Coder.m
Normal file
|
@ -0,0 +1,310 @@
|
||||||
|
/* 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
|
66
Old/CoderPrivate.h
Normal file
66
Old/CoderPrivate.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* 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
Normal file
165
Old/Coding.h
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/* 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
Normal file
129
Old/Collecting.h
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/* 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
Normal file
102
Old/Collection.h
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* 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
Normal file
839
Old/Collection.m
Normal file
|
@ -0,0 +1,839 @@
|
||||||
|
/* 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
|
50
Old/CollectionPrivate.h
Normal file
50
Old/CollectionPrivate.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* 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
Normal file
878
Old/Decoder.m
Normal file
|
@ -0,0 +1,878 @@
|
||||||
|
/* 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
|
74
Old/DelegatePool.h
Normal file
74
Old/DelegatePool.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/* 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 */
|
210
Old/DelegatePool.m
Normal file
210
Old/DelegatePool.m
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/* 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
|
40
Old/Dictionary.h
Normal file
40
Old/Dictionary.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* 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
Normal file
209
Old/Dictionary.m
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
/* 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
Normal file
883
Old/Encoder.m
Normal file
|
@ -0,0 +1,883 @@
|
||||||
|
/* 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
|
36
Old/Enumerating.h
Normal file
36
Old/Enumerating.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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 */
|
||||||
|
|
38
Old/GapArray.h
Normal file
38
Old/GapArray.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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
Normal file
144
Old/GapArray.m
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/* 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
|
||||||
|
|
88
Old/GapArrayPrivate.h
Normal file
88
Old/GapArrayPrivate.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/* 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
Normal file
36
Old/Heap.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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
Normal file
102
Old/Heap.m
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* 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
|
132
Old/IndexedCollecting.h
Normal file
132
Old/IndexedCollecting.h
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/* 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 */
|
110
Old/IndexedCollection.h
Normal file
110
Old/IndexedCollection.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* 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 */
|
466
Old/IndexedCollection.m
Normal file
466
Old/IndexedCollection.m
Normal file
|
@ -0,0 +1,466 @@
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
|
40
Old/IndexedCollectionPrivate.h
Normal file
40
Old/IndexedCollectionPrivate.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* 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 */
|
38
Old/InvalidationListening.h
Normal file
38
Old/InvalidationListening.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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 */
|
98
Old/Invocation.h
Normal file
98
Old/Invocation.h
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#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
Normal file
861
Old/Invocation.m
Normal file
|
@ -0,0 +1,861 @@
|
||||||
|
/* 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
|
42
Old/Invoking.h
Normal file
42
Old/Invoking.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* 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 */
|
||||||
|
|
81
Old/KeyedCollecting.h
Normal file
81
Old/KeyedCollecting.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/* 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 */
|
79
Old/KeyedCollection.h
Normal file
79
Old/KeyedCollection.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/* 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 */
|
280
Old/KeyedCollection.m
Normal file
280
Old/KeyedCollection.m
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
/* 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
|
||||||
|
|
50
Old/LinkedList.h
Normal file
50
Old/LinkedList.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* 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
Normal file
408
Old/LinkedList.m
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
|
||||||
|
|
38
Old/LinkedListNode.h
Normal file
38
Old/LinkedListNode.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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 */
|
84
Old/LinkedListNode.m
Normal file
84
Old/LinkedListNode.m
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/* 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
|
34
Old/Locking.h
Normal file
34
Old/Locking.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* 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 */
|
39
Old/MachPort.h
Normal file
39
Old/MachPort.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* 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
Normal file
196
Old/MachPort.m
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/* 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__ */
|
33
Old/Magnitude.h
Normal file
33
Old/Magnitude.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* 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 */
|
99
Old/Magnitude.m
Normal file
99
Old/Magnitude.m
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* 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
|
40
Old/MappedCollector.h
Normal file
40
Old/MappedCollector.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* 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 */
|
138
Old/MappedCollector.m
Normal file
138
Old/MappedCollector.m
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/* 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
|
90
Old/MemoryStream.h
Normal file
90
Old/MemoryStream.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/* 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 */
|
435
Old/MemoryStream.m
Normal file
435
Old/MemoryStream.m
Normal file
|
@ -0,0 +1,435 @@
|
||||||
|
/* 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
|
221
Old/NotificationDispatcher.h
Normal file
221
Old/NotificationDispatcher.h
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
/* 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 */
|
750
Old/NotificationDispatcher.m
Normal file
750
Old/NotificationDispatcher.m
Normal file
|
@ -0,0 +1,750 @@
|
||||||
|
/* 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
|
558
Old/OldNSConnection.h
Normal file
558
Old/OldNSConnection.h
Normal file
|
@ -0,0 +1,558 @@
|
||||||
|
#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
|
5072
Old/OldNSConnection.m
Normal file
5072
Old/OldNSConnection.m
Normal file
File diff suppressed because it is too large
Load diff
147
Old/OldNSPortCoder.h
Normal file
147
Old/OldNSPortCoder.h
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
/* 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
Normal file
2437
Old/OldNSPortCoder.m
Normal file
File diff suppressed because it is too large
Load diff
65
Old/OrderedCollecting.h
Normal file
65
Old/OrderedCollecting.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/* 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 */
|
38
Old/OrderedCollection.h
Normal file
38
Old/OrderedCollection.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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 */
|
265
Old/OrderedCollection.m
Normal file
265
Old/OrderedCollection.m
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
/* 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
|
47
Old/Ordering.h
Normal file
47
Old/Ordering.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/* 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
Normal file
119
Old/Port.h
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/* 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
Normal file
210
Old/Port.m
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/* 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
Normal file
36
Old/Queue.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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
Normal file
48
Old/Queue.m
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* 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
Normal file
39
Old/RBTree.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* 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
Normal file
250
Old/RBTree.m
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/* 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
|
||||||
|
|
36
Old/RBTreeNode.h
Normal file
36
Old/RBTreeNode.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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 */
|
87
Old/RBTreeNode.m
Normal file
87
Old/RBTreeNode.m
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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
|
13
Old/README
Normal file
13
Old/README
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
* 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 bais for gstep-base.
|
||||||
|
|
||||||
|
The files have been preserved in case we want to re-use them at some point,
|
||||||
|
or use them as the basis/inspiration for an additional library.
|
||||||
|
|
||||||
|
They are NOT part of gstep-base proper.
|
||||||
|
|
43
Old/RNGAdditiveCongruential.h
Normal file
43
Old/RNGAdditiveCongruential.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* 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 */
|
112
Old/RNGAdditiveCongruential.m
Normal file
112
Old/RNGAdditiveCongruential.m
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/* 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
|
73
Old/RNGBerkeley.h
Normal file
73
Old/RNGBerkeley.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* 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 */
|
443
Old/RNGBerkeley.m
Normal file
443
Old/RNGBerkeley.m
Normal file
|
@ -0,0 +1,443 @@
|
||||||
|
/* 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
Normal file
68
Old/Random.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/* 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
Normal file
306
Old/Random.m
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
/* 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
|
36
Old/RandomGenerating.h
Normal file
36
Old/RandomGenerating.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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 */
|
36
Old/RawCStream.h
Normal file
36
Old/RawCStream.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* 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
Normal file
296
Old/RawCStream.m
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
/* 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
Normal file
100
Old/Retaining.h
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* 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 */
|
9
Old/RunLoop.h
Normal file
9
Old/RunLoop.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#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
Normal file
52
Old/Set.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/* 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
Normal file
229
Old/Set.m
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/* 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
|
||||||
|
|
47
Old/SplayTree.h
Normal file
47
Old/SplayTree.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/* 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
Normal file
102
Old/SplayTree.m
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/* 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
|
40
Old/Stack.h
Normal file
40
Old/Stack.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* Interface for Objective-C Stack object
|
||||||
|
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||||
|
Created: May 1993
|
||||||
|
|
||||||
|
This file is part of the GNUstep Base Library.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __Stack_h_GNUSTEP_BASE_INCLUDE
|
||||||
|
#define __Stack_h_GNUSTEP_BASE_INCLUDE
|
||||||
|
|
||||||
|
#include <base/Array.h>
|
||||||
|
|
||||||
|
@interface Stack : Array
|
||||||
|
|
||||||
|
- (void) pushObject: anObject;
|
||||||
|
- popObject;
|
||||||
|
- topObject;
|
||||||
|
- (void) duplicateTop;
|
||||||
|
- (void) exchangeTop;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* __Stack_h_GNUSTEP_BASE_INCLUDE */
|
||||||
|
|
66
Old/Stack.m
Normal file
66
Old/Stack.m
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* Implementation for Objective-C Stack object
|
||||||
|
Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||||
|
Created: May 1993
|
||||||
|
|
||||||
|
This file is part of the GNUstep Base Library.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <base/Stack.h>
|
||||||
|
#include <base/ArrayPrivate.h>
|
||||||
|
|
||||||
|
@implementation Stack
|
||||||
|
|
||||||
|
- (void) pushObject: newObject
|
||||||
|
{
|
||||||
|
[self appendObject: newObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overriding */
|
||||||
|
- (void) addObject: newObject
|
||||||
|
{
|
||||||
|
[self pushObject: newObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
- popObject
|
||||||
|
{
|
||||||
|
id ret;
|
||||||
|
ret = [[self lastObject] retain];
|
||||||
|
[self removeLastObject];
|
||||||
|
return [ret autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
- topObject
|
||||||
|
{
|
||||||
|
return [self lastObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* xxx Yipes. What copying semantics do we want here? */
|
||||||
|
- (void) duplicateTop
|
||||||
|
{
|
||||||
|
[self pushObject: [self topObject]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) exchangeTop
|
||||||
|
{
|
||||||
|
if (_count > 1)
|
||||||
|
[self swapAtIndeces:_count-1 :_count-2];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
55
Old/StdioStream.h
Normal file
55
Old/StdioStream.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* Interface for GNU Objective C stdio 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __StdioStream_h__GNUSTEP_BASE_INCLUDE
|
||||||
|
#define __StdioStream_h__GNUSTEP_BASE_INCLUDE
|
||||||
|
|
||||||
|
#include <base/Stream.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@interface StdioStream : Stream
|
||||||
|
{
|
||||||
|
int mode;
|
||||||
|
FILE *fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ standardIn;
|
||||||
|
+ standardOut;
|
||||||
|
+ standardError;
|
||||||
|
|
||||||
|
+ streamWithFilename: (NSString*)name fmode: (const char *)m;
|
||||||
|
/* xxx Add the others too. */
|
||||||
|
|
||||||
|
- initWithFilePointer: (FILE*)afp fmode: (const char *)m;
|
||||||
|
- initWithFilename: (NSString*)name fmode: (const char *)m;
|
||||||
|
- initWithFileDescriptor: (int)fd fmode: (const char *)m;
|
||||||
|
|
||||||
|
- initWithPipeTo: (NSString*)systemCommand;
|
||||||
|
- initWithPipeFrom: (NSString*)systemCommand;
|
||||||
|
|
||||||
|
- (void) rewindStream;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* __StdioStream_h__GNUSTEP_BASE_INCLUDE */
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue