From 66356eb5088633d70bd82cde3f053ed3ac558c06 Mon Sep 17 00:00:00 2001 From: Andrew McCallum Date: Fri, 19 Apr 1996 23:15:30 +0000 Subject: [PATCH] (USE_OPENSTEP_STYLE_FORWARD_REFERENCES): New macro. (NSGArchiverNullCStream): New class, interface and implementation. ([NSGArchiverNullCStream -decodeValueOfCType:at:withName:]): New method. ([NSGArchiverNullCStream -decodeValueOfCType:at:withName:]): New method. ([NSGArchiver -encodeRootObject:withName:]): New method. ([NSGArchiver -encodeConditionalObject:]): New method. ([NSGArchiver -_coderCreateReferenceForObject:]): New method. ([NSGArchiver -_coderCreateForwardReferenceForObject:]): New method. ([NSGArchiver -_coderForwardReferenceForObject:]): New method. ([NSGArchiver -_objectWillBeInProgress:]): New method. ([NSGArchiver -_objectNoLongerInProgress:]): New method. ([NSGArchiver -defaultDecoderClassname]): New method. ([NSGUnarchiver -_createReferenceBeforeInit]): New method. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1483 72102866-910b-0410-8b05-ffd578937521 --- Source/NSGArchiver.m | 163 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 2 deletions(-) diff --git a/Source/NSGArchiver.m b/Source/NSGArchiver.m index 7ecf3f3fe..b76bbabda 100644 --- a/Source/NSGArchiver.m +++ b/Source/NSGArchiver.m @@ -24,8 +24,41 @@ #include #include #include +#include #include +#include +#include +#define USE_OPENSTEP_STYLE_FORWARD_REFERENCES 1 + +#if USE_OPENSTEP_STYLE_FORWARD_REFERENCES + +@interface NSGArchiverNullCStream : CStream +@end + +@implementation NSGArchiverNullCStream +- (void) encodeValueOfCType: (const char*)type + at: (const void*)d + withName: (id ) name +{ + return; +} +- (void) decodeValueOfCType: (const char*)type + at: (void*)d + withName: (id *)namePtr +{ + [self shouldNotImplement: _cmd]; +} +@end + +@interface NSGArchiver (Private) +- (void) _coderInternalCreateReferenceForObject: anObj; +- (void) encodeTag: (unsigned char)t; +@end + +#endif /* USE_OPENSTEP_STYLE_FORWARD_REFERENCES */ + + @implementation NSGArchiver + (void) initialize @@ -34,6 +67,125 @@ class_add_behavior([NSGArchiver class], [Archiver class]); } +#if USE_OPENSTEP_STYLE_FORWARD_REFERENCES + +/* Use this if you want to define any other methods... */ +//#define self ((Archiver*)self) +#define cstream (((Archiver*)self)->cstream) +#define in_progress_table (((Archiver*)self)->in_progress_table) +#define object_2_fref (((Archiver*)self)->object_2_fref) +#define object_2_xref (((Archiver*)self)->object_2_xref) +#define const_ptr_2_xref (((Archiver*)self)->const_ptr_2_xref) +#define fref_counter (((Archiver*)self)->fref_counter) + +/* Unlike the GNU version, this cannot be called recursively. */ +- (void) encodeRootObject: anObj + withName: (id )name +{ + id saved_cstream; + + /* Make sure that we're in a clean state. */ + NSParameterAssert (!object_2_xref); + NSParameterAssert (!object_2_fref); + + object_2_fref = + NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks, + NSIntMapValueCallBacks, 0); + + /* First encode to a null cstream, and record all the objects that + will be encoded. They will get recorded in [NSGArchiver + -_coderCreateReferenceForObject:] */ + saved_cstream = cstream; + cstream = [[NSGArchiverNullCStream alloc] init]; + [self startEncodingInterconnectedObjects]; + [self encodeObject: anObj withName: name]; + [self finishEncodingInterconnectedObjects]; + + [cstream release]; + cstream = saved_cstream; + /* Reset ourselves, except for object_2_fref. */ + assert (!in_progress_table); + NSResetMapTable (object_2_xref); + NSResetMapTable (const_ptr_2_xref); + assert (fref_counter == 0); + + /* Then encode everything "for real". */ + [self encodeName: @"Root Object"]; + [self encodeIndent]; + [(id)self encodeTag: CODER_OBJECT_ROOT]; + [self startEncodingInterconnectedObjects]; + [self encodeObject: anObj withName: name]; + [self finishEncodingInterconnectedObjects]; + [self encodeUnindent]; +} + +- (void) encodeConditionalObject: (id)anObject +{ + if ([cstream class] == [NSGArchiverNullCStream class]) + /* If we're gathering a list of all the objects that will be + encoded (for the first half of a -encodeRootObject:), then do + nothing. */ + return; + else + { + /* Otherwise, we've already gathered a list of all the objects + into objects_2_fref; if the object is there, encode it. */ + if (NSMapGet (object_2_fref, anObject)) + [self encodeObject: anObject]; + else + [self encodeObject: nil]; + } +} + +- (unsigned) _coderCreateReferenceForObject: anObj +{ + if ([cstream class] == [NSGArchiverNullCStream class]) + /* If we're just gathering a list of all the objects that will be + encoded (for the first half of a -encodeRootObject:), then just + put it in object_2_fref. */ + NSMapInsert (object_2_fref, anObj, (void*)1); + + /* Do the normal thing. */ + return (unsigned) CALL_METHOD_IN_CLASS ([Archiver class], + _coderCreateReferenceForObject:, + anObj); +} + +- (unsigned) _coderCreateForwardReferenceForObject: anObject +{ + /* We should never get here. */ + [self shouldNotImplement: _cmd]; + return 0; +} + +- (unsigned) _coderForwardReferenceForObject: anObject +{ + return 0; +} + +- (void) _objectWillBeInProgress: anObj +{ + /* OpenStep-style coding doesn't keep an in-progress table. */ + /* Register that we have encoded it so that future encoding can + do backward references properly. */ + [self _coderInternalCreateReferenceForObject: anObj]; +} + +- (void) _objectNoLongerInProgress: anObj +{ + /* OpenStep-style coding doesn't keep an in-progress table. */ + return; +} + +/* xxx This method interface may change in the future. */ +- (const char *) defaultDecoderClassname +{ + return "NSGUnarchiver"; +} + +#undef self +#endif /* USE_OPENSTEP_STYLE_FORWARD_REFERENCES */ + @end @implementation NSGUnarchiver @@ -44,7 +196,14 @@ class_add_behavior([NSGUnarchiver class], [Unarchiver class]); } +#if USE_OPENSTEP_STYLE_FORWARD_REFERENCES + +- (BOOL) _createReferenceBeforeInit +{ + return YES; +} + +#endif /* USE_OPENSTEP_STYLE_FORWARD_REFERENCES */ + @end -/* Use this if you want to define any other methods... */ -#define self ((Coder*)self)