mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 00:11:26 +00:00
New file.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@950 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
16636b8a2f
commit
079a267be8
13 changed files with 2257 additions and 0 deletions
59
Headers/gnustep/base/CoderPrivate.h
Normal file
59
Headers/gnustep/base/CoderPrivate.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Private interface for GNU Objective-C coder object for use serializing
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CoderPrivate_h_OBJECTS_INCLUDE
|
||||
#define __CoderPrivate_h_OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Coder.h>
|
||||
#include <objects/CStreaming.h>
|
||||
|
||||
enum {
|
||||
CODER_OBJECT_NIL = 0,
|
||||
CODER_OBJECT,
|
||||
CODER_OBJECT_ROOT,
|
||||
CODER_OBJECT_REPEATED,
|
||||
CODER_OBJECT_FORWARD_REFERENCE,
|
||||
CODER_OBJECT_FORWARD_SATISFIER,
|
||||
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;
|
||||
- (BOOL) _coderHasObjectReference: (unsigned)xref;
|
||||
@end
|
||||
|
||||
#define SIGNATURE_FORMAT_STRING \
|
||||
@"GNU Objective C Class Library %s version %d\n"
|
||||
|
||||
#define NO_SEL_TYPES "none"
|
||||
|
||||
#endif /* __CoderPrivate_h_OBJECTS_INCLUDE */
|
37
Headers/gnustep/base/Enumerating.h
Normal file
37
Headers/gnustep/base/Enumerating.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __Enumerating_h__OBJECTS_INCLUDE
|
||||
#define __Enumerating_h__OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
|
||||
@protocol Enumerating <NSObject>
|
||||
|
||||
- initWithCollection: aCollection;
|
||||
- nextObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Enumerating_h__OBJECTS_INCLUDE */
|
||||
|
42
Headers/gnustep/base/Invoking.h
Normal file
42
Headers/gnustep/base/Invoking.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __Invoking_h__OBJECTS_INCLUDE
|
||||
#define __Invoking_h__OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
|
||||
@protocol Invoking <NSObject>
|
||||
|
||||
- invoke;
|
||||
- invokeWithObject: anObject;
|
||||
|
||||
- objectReturnValue;
|
||||
- (int) intReturnValue;
|
||||
|
||||
- (BOOL) returnValueIsTrue;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Invoking_h__OBJECTS_INCLUDE */
|
||||
|
66
Headers/gnustep/base/OrderedCollecting.h
Normal file
66
Headers/gnustep/base/OrderedCollecting.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Protocol for Objective-C objects that hold elements, user gets to set order
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: Feb 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, 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_OBJECTS_INCLUDE
|
||||
#define __OrderedCollecting_h_OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/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_OBJECTS_INCLUDE */
|
39
Headers/gnustep/base/OrderedCollection.h
Normal file
39
Headers/gnustep/base/OrderedCollection.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Interface for Objective-C Ordered Collection object.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __OrderedCollection_h_INCLUDE_GNU
|
||||
#define __OrderedCollection_h_INCLUDE_GNU
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/IndexedCollection.h>
|
||||
#include <objects/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_INCLUDE_GNU */
|
737
Source/Decoder.m
Normal file
737
Source/Decoder.m
Normal file
|
@ -0,0 +1,737 @@
|
|||
/* Abstract class for reading objects from a stream
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Coder.h>
|
||||
#include <objects/CoderPrivate.h>
|
||||
#include <objects/CStream.h>
|
||||
#include <objects/Stream.h>
|
||||
#include <objects/StdioStream.h>
|
||||
#include <objects/Array.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
#define debug_coder 0
|
||||
|
||||
@implementation Decoder
|
||||
|
||||
|
||||
/* Signature Handling. */
|
||||
|
||||
+ (void) readSignatureFromCStream: (id <CStreaming>) cs
|
||||
getClassname: (char *) name
|
||||
formatVersion: (int*) version
|
||||
{
|
||||
int got;
|
||||
|
||||
got = [[cs stream] readFormat: SIGNATURE_FORMAT_STRING,
|
||||
name, version];
|
||||
if (got != 2)
|
||||
[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: (id <String>) filename
|
||||
{
|
||||
return [self newReadingFromStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "r"]];
|
||||
}
|
||||
|
||||
+ decodeObjectWithName: (id <String> *) name
|
||||
fromStream: (id <Streaming>)stream;
|
||||
{
|
||||
id c, o;
|
||||
c = [self newReadingFromStream:stream];
|
||||
[c decodeObjectAt: &o withName: name];
|
||||
[c release];
|
||||
return [o autorelease];
|
||||
}
|
||||
|
||||
+ decodeObjectWithName: (id <String> *) name
|
||||
fromFile: (id <String>) 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 refered 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 = [Array new];
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
[xref_2_object appendObject: [NSObject new]];
|
||||
}
|
||||
[xref_2_object appendObject: anObj];
|
||||
/* This return value should be the same as the index of anObj
|
||||
in xref_2_object. */
|
||||
return ([xref_2_object count] - 1);
|
||||
}
|
||||
|
||||
- _coderObjectAtReference: (unsigned)xref
|
||||
{
|
||||
assert (xref_2_object);
|
||||
return [xref_2_object objectAtIndex: xref];
|
||||
}
|
||||
|
||||
|
||||
/* The methods for the root object table */
|
||||
|
||||
- (void) _coderPushRootObjectTable
|
||||
{
|
||||
if (!xref_2_object_root)
|
||||
xref_2_object_root = [Array new];
|
||||
}
|
||||
|
||||
- (void) _coderPopRootObjectTable
|
||||
{
|
||||
assert (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 = [Array new];
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
[xref_2_object_root appendObject: [NSObject new]];
|
||||
}
|
||||
[xref_2_object_root appendObject: 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
|
||||
{
|
||||
assert (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;
|
||||
{
|
||||
assert (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 = objects_list_of_void_p ();
|
||||
objects_list_append_element (fref_stack, NSCreateMap (...));
|
||||
#endif
|
||||
if (!address_2_fref)
|
||||
address_2_fref = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
|
||||
}
|
||||
|
||||
- (void) _coderPopForwardObjectTable
|
||||
{
|
||||
assert (address_2_fref);
|
||||
if (!interconnect_stack_height)
|
||||
{
|
||||
NSFreeMapTable (address_2_fref);
|
||||
address_2_fref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _coderSatisfyForwardReference: (unsigned)fref withObject: anObj
|
||||
{
|
||||
assert (address_2_fref);
|
||||
if (!fref_2_object)
|
||||
fref_2_object = NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks, 0);
|
||||
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. */
|
||||
assert (address_2_fref);
|
||||
/* There should not be duplicate addresses */
|
||||
assert (!NSMapGet (address_2_fref, addr));
|
||||
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
|
||||
"_coderPutObject:atReference" 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Method for decoding things. */
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (id <String> *)namePtr
|
||||
{
|
||||
[cstream decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
}
|
||||
|
||||
- (void) decodeBytes: (char *)b
|
||||
count: (unsigned*)c
|
||||
withName: (id <String> *) name
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- (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)
|
||||
[self error:"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);
|
||||
if (ret == Nil)
|
||||
[self error:"Couldn't find class `%s'", class_name];
|
||||
if (class_get_version(ret) != class_version)
|
||||
[self error:"Class version mismatch, executable %d != encoded %d",
|
||||
class_get_version(ret), class_version];
|
||||
|
||||
{
|
||||
unsigned xref;
|
||||
xref = [self _coderCreateReferenceForConstPtr: ret];
|
||||
if (debug_coder)
|
||||
fprintf(stderr, "Coder decoding registered class xref %u\n", xref);
|
||||
}
|
||||
(*objc_free) (class_name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"unrecognized class tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (const char *) decodeAtomicStringWithName: (id <String> *) 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: (id <String> *) 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)
|
||||
[self error:"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)
|
||||
[self error:"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)))
|
||||
[self error:"ObjC runtime didn't provide SEL with matching type"];
|
||||
#endif
|
||||
{
|
||||
unsigned xref;
|
||||
xref = [self _coderCreateReferenceForConstPtr: ret];
|
||||
if (debug_coder)
|
||||
fprintf(stderr, "Coder decoding registered sel xref %u\n", xref);
|
||||
}
|
||||
(*objc_free)(sel_name);
|
||||
(*objc_free)(sel_types);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"unrecognized selector tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
- (void) startDecodingInterconnectedObjects
|
||||
{
|
||||
interconnect_stack_height++;
|
||||
[self _coderPushRootObjectTable];
|
||||
[self _coderPushForwardObjectTable];
|
||||
}
|
||||
|
||||
- (void) finishDecodingInterconnectedObjects
|
||||
{
|
||||
SEL awake_sel = sel_get_any_uid("awakeAfterUsingCoder:");
|
||||
|
||||
assert (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. */
|
||||
|
||||
/* resolve object forward references */
|
||||
[self _coderResolveTopForwardReferences];
|
||||
[self _coderPopForwardObjectTable];
|
||||
|
||||
#if 0
|
||||
When should this be done?
|
||||
/* send "-awakeAfterUsingCoder:" to all the objects that were read */
|
||||
/* xxx But this doesn't currently handle the return of a different
|
||||
object than was messaged! */
|
||||
if (awake_sel)
|
||||
{
|
||||
void ask_awake(elt e)
|
||||
{
|
||||
if (__objc_responds_to(e.id_u, awake_sel))
|
||||
(*objc_msg_lookup(e.id_u,awake_sel))(e.id_u, awake_sel, self);
|
||||
}
|
||||
[[self _coderTopRootObjectTable] withElementsCall:ask_awake];
|
||||
}
|
||||
#endif
|
||||
[self _coderPopRootObjectTable];
|
||||
}
|
||||
|
||||
- (void) _decodeRootObjectAt: (id*)ret withName: (id <String> *) name
|
||||
{
|
||||
[self startDecodingInterconnectedObjects];
|
||||
[self decodeObjectAt:ret withName:name];
|
||||
[self finishDecodingInterconnectedObjects];
|
||||
}
|
||||
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (id <String> *)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 */
|
||||
}
|
||||
|
||||
/* This is the designated (and one-and-only) object decoder */
|
||||
- (void) decodeObjectAt: (id*) anObjPtr withName: (id <String> *) name
|
||||
{
|
||||
unsigned char tag;
|
||||
unsigned fref = 0;
|
||||
|
||||
[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:
|
||||
{
|
||||
unsigned fref;
|
||||
|
||||
if (!DOING_ROOT_OBJECT)
|
||||
[self error:"can't decode forward reference when not decoding "
|
||||
"a root object"];
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: NULL];
|
||||
[self _coderAssociateForwardReference: fref
|
||||
withObjectAddress: anObjPtr];
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT_FORWARD_SATISFIER:
|
||||
{
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: NULL];
|
||||
/* NOTE: no "break" here; falling through. */
|
||||
}
|
||||
case CODER_OBJECT:
|
||||
{
|
||||
Class object_class;
|
||||
SEL new_sel = sel_get_any_uid ("newWithCoder:");
|
||||
Method* new_method;
|
||||
|
||||
[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)
|
||||
*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 (init_method)
|
||||
*anObjPtr =
|
||||
(*(init_method->method_imp))(*anObjPtr, init_sel, self);
|
||||
/* xxx else what, error? */
|
||||
}
|
||||
/* xxx Should I sent -awakeUsingCoder: here instead of above? */
|
||||
|
||||
/* If this was a CODER_OBJECT_FORWARD_SATISFIER, then remember it. */
|
||||
if (fref)
|
||||
[self _coderSatisfyForwardReference: fref withObject: *anObjPtr];
|
||||
|
||||
/* Would get error here with Connection-wide object references
|
||||
because addProxy gets called in +newRemote:connection: */
|
||||
{
|
||||
unsigned xref =
|
||||
[self _coderInternalCreateReferenceForObject: *anObjPtr];
|
||||
if (debug_coder)
|
||||
fprintf(stderr, "Coder decoding registered class xref %u\n", xref);
|
||||
}
|
||||
[self decodeUnindent];
|
||||
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];
|
||||
if (!*anObjPtr)
|
||||
[self error: "repeated object cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"unrecognized object tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
}
|
||||
|
||||
|
||||
- (void) decodeWithName: (id <String> *)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: (id <String> *)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: (id <String> *) 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: (id <String> *)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
|
798
Source/Encoder.m
Normal file
798
Source/Encoder.m
Normal file
|
@ -0,0 +1,798 @@
|
|||
/* Abstract class for writing objects to a stream
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Coder.h>
|
||||
#include <objects/CoderPrivate.h>
|
||||
#include <objects/MemoryStream.h>
|
||||
#include <objects/StdioStream.h>
|
||||
#include <objects/BinaryCStream.h>
|
||||
#include <Foundation/NSArchiver.h>
|
||||
|
||||
static int default_format_version;
|
||||
static id default_stream_class;
|
||||
static id default_cstream_class;
|
||||
|
||||
#define debug_coder 0
|
||||
#define DEFAULT_FORMAT_VERSION 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 == [Coder class])
|
||||
{
|
||||
/* This code has not yet been ported to machines for which
|
||||
a pointer is not the same size as an int. */
|
||||
assert(sizeof(void*) == sizeof(unsigned));
|
||||
|
||||
/* Initialize some defaults. */
|
||||
default_stream_class = [MemoryStream class];
|
||||
default_cstream_class = [BinaryCStream class];
|
||||
default_format_version = 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,
|
||||
[self defaultDecoderClassname],
|
||||
format_version];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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];
|
||||
in_progress_table = NULL;
|
||||
object_2_xref = NULL;
|
||||
object_2_fref = NULL;
|
||||
const_ptr_2_xref = NULL;
|
||||
[self writeSignature];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* ..Writing... methods */
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withCStreamClass: (Class) cStreamClass
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withFormatVersion: DEFAULT_FORMAT_VERSION
|
||||
cStreamClass: cStreamClass
|
||||
cStreamFormatVersion: [cStreamClass defaultFormatVersion]];
|
||||
}
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withCStreamClass: [[self class] defaultCStreamClass]];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (id <String>) 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: (id <String>) filename
|
||||
withCStreamClass: (Class) cStreamClass
|
||||
{
|
||||
return [self initForWritingToStream: [StdioStream
|
||||
streamWithFilename: filename
|
||||
fmode: "w"]
|
||||
withCStreamClass: cStreamClass];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (id <String>) filename
|
||||
{
|
||||
return [self initForWritingToStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
+ newWritingToStream: (id <Streaming>)s
|
||||
{
|
||||
return [[self alloc] initForWritingToStream: s];
|
||||
}
|
||||
|
||||
+ newWritingToFile: (id <String>)filename
|
||||
{
|
||||
return [self newWritingToStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (id <String>) name
|
||||
toStream: (id <Streaming>)stream
|
||||
{
|
||||
id c = [[self alloc] initForWritingToStream: stream];
|
||||
[c encodeRootObject: anObject withName: name];
|
||||
[c closeCoding];
|
||||
[c release];
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (id <String>) name
|
||||
toFile: (id <String>) 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.
|
||||
|
||||
For instance, ConnectedCoder keeps cross-references to const
|
||||
pointers on a per-Connection basis instead of a per-Coder basis.
|
||||
We avoid encoding/decoding the same classes and selectors over and
|
||||
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 (const_ptr_2_xref, anObj, (void*)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);
|
||||
else
|
||||
assert(! NSMapGet (const_ptr_2_xref, (void*)xref));
|
||||
xref = NSCountMapTable (const_ptr_2_xref) + 1;
|
||||
NSMapInsert (const_ptr_2_xref, ptr, (void*)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 = NSCountMapTable (object_2_fref) + 1;
|
||||
assert ( ! NSMapGet (object_2_fref, anObject));
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
/* Method for encoding things. */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (id <String>)name
|
||||
{
|
||||
[cstream encodeValueOfCType:type
|
||||
at:d
|
||||
withName:name];
|
||||
}
|
||||
|
||||
- (void) encodeBytes: (const char *)b
|
||||
count: (unsigned)c
|
||||
withName: (id <String>)name
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
|
||||
- (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);
|
||||
|
||||
assert (class_name);
|
||||
assert (*class_name);
|
||||
|
||||
[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: (id <String>) name
|
||||
{
|
||||
/* xxx Add repeat-string-ptr checking here. */
|
||||
[self notImplemented:_cmd];
|
||||
[self encodeValueOfCType:@encode(char*) at:&sp withName:name];
|
||||
}
|
||||
|
||||
- (void) encodeSelector: (SEL)sel withName: (id <String>) 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_uid (sel_get_name (sel)));
|
||||
#endif
|
||||
if (!sel_name) [self error:"ObjC runtime didn't provide SEL name"];
|
||||
if (!*sel_name) [self error:"ObjC runtime didn't provide SEL name"];
|
||||
if (!sel_types) [self error:"ObjC runtime didn't provide SEL type"];
|
||||
if (!*sel_types) [self error:"ObjC runtime didn't provide SEL type"];
|
||||
|
||||
[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: (id <String>) 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: */
|
||||
assert (interconnect_stack_height);
|
||||
interconnect_stack_height--;
|
||||
}
|
||||
|
||||
/* NOTE: Unlike NeXT's, this *can* be called recursively */
|
||||
- (void) encodeRootObject: anObj
|
||||
withName: (id <String>)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 two 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).
|
||||
|
||||
ConnectedCoder 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 ConnectedCoder */
|
||||
- (void) _doEncodeObject: anObj
|
||||
{
|
||||
[self _doEncodeBycopyObject:anObj];
|
||||
}
|
||||
|
||||
|
||||
/* This is the designated object encoder */
|
||||
- (void) _encodeObject: anObj
|
||||
withName: (id <String>) name
|
||||
isBycopy: (BOOL) bycopy_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. */
|
||||
if (!in_progress_table)
|
||||
in_progress_table =
|
||||
NSCreateMapTable (NSObjectMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
NSMapInsert (in_progress_table, anObj, (void*)1);
|
||||
|
||||
/* Find out if this object satisfies any previous forward
|
||||
references. */
|
||||
fref = [self _coderForwardReferenceForObject: anObj];
|
||||
if (fref)
|
||||
{
|
||||
|
||||
/* It does satisfy a forward reference; write the forward
|
||||
reference number, so the decoder can know. */
|
||||
[self encodeTag: CODER_OBJECT_FORWARD_SATISFIER];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It does not satisfy a forward reference. Note: in future
|
||||
encoding we may have backward references to this object,
|
||||
but we will never need forward references to this object. */
|
||||
[self encodeTag: CODER_OBJECT];
|
||||
}
|
||||
/* Encode the object. */
|
||||
[self encodeIndent];
|
||||
if (bycopy_flag)
|
||||
[self _doEncodeBycopyObject:anObj];
|
||||
else
|
||||
[self _doEncodeObject:anObj];
|
||||
[self encodeUnindent];
|
||||
|
||||
/* Register that we have encoded it so that future encoding can
|
||||
do backward references properly. */
|
||||
[self _coderInternalCreateReferenceForObject: anObj];
|
||||
/* Remove it from the forward reference table, since we'll never
|
||||
have another forward reference for this object. */
|
||||
if (fref)
|
||||
[self _coderRemoveForwardReferenceForObject: anObj];
|
||||
/* We're done encoding the object, it's no longer in progress. */
|
||||
NSMapRemove (in_progress_table, anObj);
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
}
|
||||
|
||||
- (void) encodeObject: anObj
|
||||
withName: (id <String>)name
|
||||
{
|
||||
[self _encodeObject:anObj withName:name isBycopy:NO isForwardReference:NO];
|
||||
}
|
||||
|
||||
|
||||
- (void) encodeBycopyObject: anObj
|
||||
withName: (id <String>)name
|
||||
{
|
||||
[self _encodeObject:anObj withName:name isBycopy:YES isForwardReference:NO];
|
||||
}
|
||||
|
||||
- (void) encodeObjectReference: anObj
|
||||
withName: (id <String>)name
|
||||
{
|
||||
[self _encodeObject:anObj withName:name isBycopy:NO isForwardReference:YES];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void) encodeWithName: (id <String>)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: (id <String>)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: (id <String>)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: (id <String>)n
|
||||
{
|
||||
[cstream encodeName: n];
|
||||
}
|
||||
|
||||
|
||||
/* Substituting Classes */
|
||||
|
||||
- (id <String>) classNameEncodedForTrueClassName: (id <String>) trueName
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
|
||||
#if 0
|
||||
if (classname_2_classname)
|
||||
return NSMapGet (classname_2_classname, [trueName cStringNoCopy]);
|
||||
return trueName;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) encodeClassName: (id <String>) trueName
|
||||
intoClassName: (id <String>) 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
|
236
Source/NSCallBacks.m
Normal file
236
Source/NSCallBacks.m
Normal file
|
@ -0,0 +1,236 @@
|
|||
/* GNUStep callback functions. Implicitly required by the standard.
|
||||
* Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
*
|
||||
* Author: Albin L. Jones <Albin.L.Jones@Dartmouth.EDU>
|
||||
* Created: Tue Feb 13 23:10:29 EST 1996
|
||||
* Updated: Tue Feb 13 23:10:29 EST 1996
|
||||
* Serial: 96.02.13.01
|
||||
*
|
||||
* This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/**** Included Headers *******************************************************/
|
||||
|
||||
#include <NSCallBacks.h>
|
||||
#include <Foundation/NSObject.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
/**** Type, Constant, and Macro Definitions **********************************/
|
||||
|
||||
/**** Function Implementations ***********************************************/
|
||||
|
||||
/** For `int's **/
|
||||
|
||||
unsigned int
|
||||
_NS_int_hash (void *table, int i)
|
||||
{
|
||||
return (unsigned int) i;
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_int_is_equal (void *table, int i, int j)
|
||||
{
|
||||
return (i == j) ? YES : NO;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_int_retain (void *table, int i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_int_release (void *table, int i)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_int_describe (void *table, int i)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%d", i];
|
||||
}
|
||||
|
||||
/** For owned `void *' **/
|
||||
|
||||
unsigned int
|
||||
_NS_owned_void_p_hash (void *table, void *p)
|
||||
{
|
||||
/* P may be aligned, so we need to compensate. */
|
||||
return ((unsigned int)p)/4;
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_owned_void_p_is_equal (void *table, void *p, void *q)
|
||||
{
|
||||
return (p == q) ? YES : NO;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_owned_void_p_retain (void *table, void *p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_owned_void_p_release (void *table, void *p)
|
||||
{
|
||||
if (p != 0)
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_owned_void_p_describe (void *table, void *p)
|
||||
{
|
||||
/* This may not be right; I'm doing this off of the top of my head, and
|
||||
* I'm in a hurry. */
|
||||
return [NSString stringWithFormat:@"%0x", p];
|
||||
}
|
||||
|
||||
/** For non-retained Objective-C objects **/
|
||||
unsigned int
|
||||
_NS_non_retained_id_hash (void *table, id <NSObject> o)
|
||||
{
|
||||
return [o hash];
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_non_retained_id_is_equal (void *table, id <NSObject> o, id <NSObject> p)
|
||||
{
|
||||
/* Once again I need a nice way to determine whether or not O
|
||||
* responds to `isEqual:'. */
|
||||
return [o isEqual:p];
|
||||
}
|
||||
|
||||
void
|
||||
_NS_non_retained_id_retain (void *table, id <NSObject> o)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_non_retained_id_release (void *table, id <NSObject> o)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_non_retained_id_describe (void *table, id <NSObject> o)
|
||||
{
|
||||
/* Once again, I need a nice way to determine whether O responds to
|
||||
* `describe'. Help. */
|
||||
return [o description];
|
||||
}
|
||||
|
||||
/** For (retainable) objects **/
|
||||
unsigned int
|
||||
_NS_id_hash (void *table, id <NSObject> o)
|
||||
{
|
||||
/* See above. */
|
||||
return [o hash];
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_id_is_equal (void *table, id <NSObject> o, id <NSObject> p)
|
||||
{
|
||||
return [o isEqual:p];
|
||||
}
|
||||
|
||||
void
|
||||
_NS_id_retain (void *table, id <NSObject> o)
|
||||
{
|
||||
[o retain];
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_id_release (void *table, id <NSObject> o)
|
||||
{
|
||||
[o release];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_id_describe (void *table, id <NSObject> o)
|
||||
{
|
||||
return [o description];
|
||||
}
|
||||
|
||||
|
||||
/** For (non-owned) `void *' **/
|
||||
unsigned int
|
||||
_NS_non_owned_void_p_hash (void *table, void *p)
|
||||
{
|
||||
return ((unsigned int)p)/4;
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_non_owned_void_p_is_equal (void *table, void *p, void *q)
|
||||
{
|
||||
return (p == q) ? YES : NO;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_non_owned_void_p_retain (void *table, void *p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_non_owned_void_p_release (void *table, void *p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_non_owned_void_p_describe (void *table, void *p)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%0x", p];
|
||||
}
|
||||
|
||||
/** For pointers to structures and `int *' **/
|
||||
unsigned int
|
||||
_NS_int_p_hash (void *table, int *p)
|
||||
{
|
||||
return ((unsigned int)p)/4;
|
||||
}
|
||||
|
||||
BOOL
|
||||
_NS_int_p_is_equal (void *table, int *p, int *q)
|
||||
{
|
||||
return (p == q) ? YES : NO;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_int_p_retain (void *table, int *p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
_NS_int_p_release (void *table, int *p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *
|
||||
_NS_int_p_describe (void *table, int *p)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%d (%0x)", *p, p];
|
||||
}
|
59
Source/objects/CoderPrivate.h
Normal file
59
Source/objects/CoderPrivate.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Private interface for GNU Objective-C coder object for use serializing
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CoderPrivate_h_OBJECTS_INCLUDE
|
||||
#define __CoderPrivate_h_OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/Coder.h>
|
||||
#include <objects/CStreaming.h>
|
||||
|
||||
enum {
|
||||
CODER_OBJECT_NIL = 0,
|
||||
CODER_OBJECT,
|
||||
CODER_OBJECT_ROOT,
|
||||
CODER_OBJECT_REPEATED,
|
||||
CODER_OBJECT_FORWARD_REFERENCE,
|
||||
CODER_OBJECT_FORWARD_SATISFIER,
|
||||
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;
|
||||
- (BOOL) _coderHasObjectReference: (unsigned)xref;
|
||||
@end
|
||||
|
||||
#define SIGNATURE_FORMAT_STRING \
|
||||
@"GNU Objective C Class Library %s version %d\n"
|
||||
|
||||
#define NO_SEL_TYPES "none"
|
||||
|
||||
#endif /* __CoderPrivate_h_OBJECTS_INCLUDE */
|
37
Source/objects/Enumerating.h
Normal file
37
Source/objects/Enumerating.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __Enumerating_h__OBJECTS_INCLUDE
|
||||
#define __Enumerating_h__OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
|
||||
@protocol Enumerating <NSObject>
|
||||
|
||||
- initWithCollection: aCollection;
|
||||
- nextObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Enumerating_h__OBJECTS_INCLUDE */
|
||||
|
42
Source/objects/Invoking.h
Normal file
42
Source/objects/Invoking.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __Invoking_h__OBJECTS_INCLUDE
|
||||
#define __Invoking_h__OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
|
||||
@protocol Invoking <NSObject>
|
||||
|
||||
- invoke;
|
||||
- invokeWithObject: anObject;
|
||||
|
||||
- objectReturnValue;
|
||||
- (int) intReturnValue;
|
||||
|
||||
- (BOOL) returnValueIsTrue;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Invoking_h__OBJECTS_INCLUDE */
|
||||
|
66
Source/objects/OrderedCollecting.h
Normal file
66
Source/objects/OrderedCollecting.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Protocol for Objective-C objects that hold elements, user gets to set order
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: Feb 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, 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_OBJECTS_INCLUDE
|
||||
#define __OrderedCollecting_h_OBJECTS_INCLUDE
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/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_OBJECTS_INCLUDE */
|
39
Source/objects/OrderedCollection.h
Normal file
39
Source/objects/OrderedCollection.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* Interface for Objective-C Ordered Collection object.
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: R. Andrew McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNU Objective C Class 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __OrderedCollection_h_INCLUDE_GNU
|
||||
#define __OrderedCollection_h_INCLUDE_GNU
|
||||
|
||||
#include <objects/stdobjects.h>
|
||||
#include <objects/IndexedCollection.h>
|
||||
#include <objects/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_INCLUDE_GNU */
|
Loading…
Add table
Add a link
Reference in a new issue