diff --git a/Headers/gnustep/base/CoderPrivate.h b/Headers/gnustep/base/CoderPrivate.h new file mode 100644 index 000000000..1c48d0ba9 --- /dev/null +++ b/Headers/gnustep/base/CoderPrivate.h @@ -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 + 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 +#include +#include + +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 ) 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 */ diff --git a/Headers/gnustep/base/Enumerating.h b/Headers/gnustep/base/Enumerating.h new file mode 100644 index 000000000..5fe967e7e --- /dev/null +++ b/Headers/gnustep/base/Enumerating.h @@ -0,0 +1,37 @@ +/* Protocol for GNU Objective C invocations + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 + +@protocol Enumerating + +- initWithCollection: aCollection; +- nextObject; + +@end + +#endif /* __Enumerating_h__OBJECTS_INCLUDE */ + diff --git a/Headers/gnustep/base/Invoking.h b/Headers/gnustep/base/Invoking.h new file mode 100644 index 000000000..87909ccde --- /dev/null +++ b/Headers/gnustep/base/Invoking.h @@ -0,0 +1,42 @@ +/* Protocol for GNU Objective C invocations + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 + +@protocol Invoking + +- invoke; +- invokeWithObject: anObject; + +- objectReturnValue; +- (int) intReturnValue; + +- (BOOL) returnValueIsTrue; + +@end + +#endif /* __Invoking_h__OBJECTS_INCLUDE */ + diff --git a/Headers/gnustep/base/OrderedCollecting.h b/Headers/gnustep/base/OrderedCollecting.h new file mode 100644 index 000000000..972daefc6 --- /dev/null +++ b/Headers/gnustep/base/OrderedCollecting.h @@ -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 + 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 protocol inherits from the + protocol. + + The 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 +#include + +@protocol OrderedCollecting + +// ADDING; +- (void) insertObject: newObject atIndex: (unsigned)index; +- (void) insertObject: newObject before: oldObject; +- (void) insertObject: newObject after: oldObject; +- (void) insertContentsOf: (id )aCollection + atIndex: (unsigned)index; +- (void) appendObject: newObject; +- (void) prependObject: newObject; +- (void) appendContentsOf: (id )aCollection; +- (void) prependContentsOf: (id )aCollection; + +// SWAPPING AND SORTING +- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2; +- (void) sortContents; + +// REPLACING; +- (void) replaceRange: (IndexRange)aRange + with: (id )aCollection; +- replaceRange: (IndexRange)aRange + using: (id )aCollection; + +@end + +#endif /* __OrderedCollecting_h_OBJECTS_INCLUDE */ diff --git a/Headers/gnustep/base/OrderedCollection.h b/Headers/gnustep/base/OrderedCollection.h new file mode 100644 index 000000000..7913359e8 --- /dev/null +++ b/Headers/gnustep/base/OrderedCollection.h @@ -0,0 +1,39 @@ +/* Interface for Objective-C Ordered Collection object. + Copyright (C) 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 +#include +#include + +@interface OrderedCollection : IndexedCollection +@end + + +/* Put this on category instead of class to avoid bogus complaint from gcc */ +@interface OrderedCollection (Protocol) +@end + +#endif /* __OrderedCollection_h_INCLUDE_GNU */ diff --git a/Source/Decoder.m b/Source/Decoder.m new file mode 100644 index 000000000..53c8427eb --- /dev/null +++ b/Source/Decoder.m @@ -0,0 +1,737 @@ +/* Abstract class for reading objects from a stream + Copyright (C) 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 +#include +#include +#include +#include +#include +#include +#include + +#define debug_coder 0 + +@implementation Decoder + + +/* Signature Handling. */ + ++ (void) readSignatureFromCStream: (id ) 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 ) 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 ) filename +{ + return [self newReadingFromStream: + [StdioStream streamWithFilename: filename + fmode: "r"]]; +} + ++ decodeObjectWithName: (id *) name + fromStream: (id )stream; +{ + id c, o; + c = [self newReadingFromStream:stream]; + [c decodeObjectAt: &o withName: name]; + [c release]; + return [o autorelease]; +} + ++ decodeObjectWithName: (id *) name + fromFile: (id ) 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 *)namePtr +{ + [cstream decodeValueOfCType:type + at:d + withName:namePtr]; +} + +- (void) decodeBytes: (char *)b + count: (unsigned*)c + withName: (id *) 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 *) 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 *) 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 *) name +{ + [self startDecodingInterconnectedObjects]; + [self decodeObjectAt:ret withName:name]; + [self finishDecodingInterconnectedObjects]; +} + + +- (void) decodeValueOfObjCType: (const char*)type + at: (void*)d + withName: (id *)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 *) 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 *)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 *)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 *) 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 *)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 diff --git a/Source/Encoder.m b/Source/Encoder.m new file mode 100644 index 000000000..7501eb643 --- /dev/null +++ b/Source/Encoder.m @@ -0,0 +1,798 @@ +/* Abstract class for writing objects to a stream + Copyright (C) 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 +#include +#include +#include +#include +#include +#include + +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 ) 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 ) s + withCStreamClass: (Class) cStreamClass +{ + return [self initForWritingToStream: s + withFormatVersion: DEFAULT_FORMAT_VERSION + cStreamClass: cStreamClass + cStreamFormatVersion: [cStreamClass defaultFormatVersion]]; +} + +- initForWritingToStream: (id ) s +{ + return [self initForWritingToStream: s + withCStreamClass: [[self class] defaultCStreamClass]]; +} + +- initForWritingToFile: (id ) 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 ) filename + withCStreamClass: (Class) cStreamClass +{ + return [self initForWritingToStream: [StdioStream + streamWithFilename: filename + fmode: "w"] + withCStreamClass: cStreamClass]; +} + +- initForWritingToFile: (id ) filename +{ + return [self initForWritingToStream: + [StdioStream streamWithFilename: filename + fmode: "w"]]; +} + ++ newWritingToStream: (id )s +{ + return [[self alloc] initForWritingToStream: s]; +} + ++ newWritingToFile: (id )filename +{ + return [self newWritingToStream: + [StdioStream streamWithFilename: filename + fmode: "w"]]; +} + ++ (BOOL) encodeRootObject: anObject + withName: (id ) name + toStream: (id )stream +{ + id c = [[self alloc] initForWritingToStream: stream]; + [c encodeRootObject: anObject withName: name]; + [c closeCoding]; + [c release]; + return YES; +} + ++ (BOOL) encodeRootObject: anObject + withName: (id ) name + toFile: (id ) 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 )name +{ + [cstream encodeValueOfCType:type + at:d + withName:name]; +} + +- (void) encodeBytes: (const char *)b + count: (unsigned)c + withName: (id )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 ) 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 ) 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 ) 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 )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 ) 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 )name +{ + [self _encodeObject:anObj withName:name isBycopy:NO isForwardReference:NO]; +} + + +- (void) encodeBycopyObject: anObj + withName: (id )name +{ + [self _encodeObject:anObj withName:name isBycopy:YES isForwardReference:NO]; +} + +- (void) encodeObjectReference: anObj + withName: (id )name +{ + [self _encodeObject:anObj withName:name isBycopy:NO isForwardReference:YES]; +} + + + +- (void) encodeWithName: (id )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 )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 )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 )n +{ + [cstream encodeName: n]; +} + + +/* Substituting Classes */ + +- (id ) classNameEncodedForTrueClassName: (id ) 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 ) trueName + intoClassName: (id ) 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 diff --git a/Source/NSCallBacks.m b/Source/NSCallBacks.m new file mode 100644 index 000000000..f2ace036a --- /dev/null +++ b/Source/NSCallBacks.m @@ -0,0 +1,236 @@ +/* GNUStep callback functions. Implicitly required by the standard. + * Copyright (C) 1996 Free Software Foundation, Inc. + * + * Author: Albin L. Jones + * 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 +#include +#include + +/**** 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 o) +{ + return [o hash]; +} + +BOOL +_NS_non_retained_id_is_equal (void *table, id o, id 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 o) +{ + return; +} + +void +_NS_non_retained_id_release (void *table, id o) +{ + return; +} + +NSString * +_NS_non_retained_id_describe (void *table, id 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 o) +{ + /* See above. */ + return [o hash]; +} + +BOOL +_NS_id_is_equal (void *table, id o, id p) +{ + return [o isEqual:p]; +} + +void +_NS_id_retain (void *table, id o) +{ + [o retain]; + return; +} + +void +_NS_id_release (void *table, id o) +{ + [o release]; + return; +} + +NSString * +_NS_id_describe (void *table, id 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]; +} diff --git a/Source/objects/CoderPrivate.h b/Source/objects/CoderPrivate.h new file mode 100644 index 000000000..1c48d0ba9 --- /dev/null +++ b/Source/objects/CoderPrivate.h @@ -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 + 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 +#include +#include + +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 ) 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 */ diff --git a/Source/objects/Enumerating.h b/Source/objects/Enumerating.h new file mode 100644 index 000000000..5fe967e7e --- /dev/null +++ b/Source/objects/Enumerating.h @@ -0,0 +1,37 @@ +/* Protocol for GNU Objective C invocations + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 + +@protocol Enumerating + +- initWithCollection: aCollection; +- nextObject; + +@end + +#endif /* __Enumerating_h__OBJECTS_INCLUDE */ + diff --git a/Source/objects/Invoking.h b/Source/objects/Invoking.h new file mode 100644 index 000000000..87909ccde --- /dev/null +++ b/Source/objects/Invoking.h @@ -0,0 +1,42 @@ +/* Protocol for GNU Objective C invocations + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 + +@protocol Invoking + +- invoke; +- invokeWithObject: anObject; + +- objectReturnValue; +- (int) intReturnValue; + +- (BOOL) returnValueIsTrue; + +@end + +#endif /* __Invoking_h__OBJECTS_INCLUDE */ + diff --git a/Source/objects/OrderedCollecting.h b/Source/objects/OrderedCollecting.h new file mode 100644 index 000000000..972daefc6 --- /dev/null +++ b/Source/objects/OrderedCollecting.h @@ -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 + 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 protocol inherits from the + protocol. + + The 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 +#include + +@protocol OrderedCollecting + +// ADDING; +- (void) insertObject: newObject atIndex: (unsigned)index; +- (void) insertObject: newObject before: oldObject; +- (void) insertObject: newObject after: oldObject; +- (void) insertContentsOf: (id )aCollection + atIndex: (unsigned)index; +- (void) appendObject: newObject; +- (void) prependObject: newObject; +- (void) appendContentsOf: (id )aCollection; +- (void) prependContentsOf: (id )aCollection; + +// SWAPPING AND SORTING +- (void) swapAtIndeces: (unsigned)index1 : (unsigned)index2; +- (void) sortContents; + +// REPLACING; +- (void) replaceRange: (IndexRange)aRange + with: (id )aCollection; +- replaceRange: (IndexRange)aRange + using: (id )aCollection; + +@end + +#endif /* __OrderedCollecting_h_OBJECTS_INCLUDE */ diff --git a/Source/objects/OrderedCollection.h b/Source/objects/OrderedCollection.h new file mode 100644 index 000000000..7913359e8 --- /dev/null +++ b/Source/objects/OrderedCollection.h @@ -0,0 +1,39 @@ +/* Interface for Objective-C Ordered Collection object. + Copyright (C) 1996 Free Software Foundation, Inc. + + Written by: R. Andrew McCallum + 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 +#include +#include + +@interface OrderedCollection : IndexedCollection +@end + + +/* Put this on category instead of class to avoid bogus complaint from gcc */ +@interface OrderedCollection (Protocol) +@end + +#endif /* __OrderedCollection_h_INCLUDE_GNU */