mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-28 11:10:51 +00:00
([Coder -encodeTag:]): Let the cstream handle it, if it can.
([Coder -decodeTag]): Likewise. ([Coder -encodeClass:]): Perform classname mapping ala encodeClassName:intoClassName. ([Coder -_doEncodeBycopyObject:]): Perform callbacks -replacementObjectForCoder, -replacementObjectForArchiver, -classForCoder, -classForArchiver. ([Coder -encodeClassName:intoClassName:]): Fix typos. ([Coder -encodeConditionalObject:]): Don't encode *forward* references, only backward references; apparently NeXT-style decoding (with -decodeObject, instead of GNU's decodeObjectAt:) can't handle them. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@855 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
609f0e2086
commit
22f3f8f15c
1 changed files with 70 additions and 72 deletions
142
Source/Coder.m
142
Source/Coder.m
|
@ -38,6 +38,7 @@
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
#include <Foundation/NSGeometry.h>
|
#include <Foundation/NSGeometry.h>
|
||||||
#include <Foundation/NSData.h>
|
#include <Foundation/NSData.h>
|
||||||
|
#include <Foundation/NSArchiver.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,6 +83,10 @@ my_object_is_class(id object)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@interface Coder (Private)
|
||||||
|
- (BOOL) _coderHasObjectReference: (unsigned)xref;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation Coder
|
@implementation Coder
|
||||||
|
|
||||||
|
@ -514,18 +519,25 @@ exc_return_null(arglist_t f)
|
||||||
|
|
||||||
- (void) encodeTag: (unsigned char)t
|
- (void) encodeTag: (unsigned char)t
|
||||||
{
|
{
|
||||||
[self encodeValueOfCType:@encode(unsigned char)
|
if ([cstream respondsToSelector: @selector(encodeTag:)])
|
||||||
at:&t
|
[(id)cstream encodeTag:t];
|
||||||
withName:@"Coder tag"];
|
else
|
||||||
|
[self encodeValueOfCType:@encode(unsigned char)
|
||||||
|
at:&t
|
||||||
|
withName:@"Coder tag"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (unsigned char) decodeTag
|
- (unsigned char) decodeTag
|
||||||
{
|
{
|
||||||
unsigned char t;
|
if ([cstream respondsToSelector: @selector(decodeTag)])
|
||||||
[self decodeValueOfCType:@encode(unsigned char)
|
return [(id)cstream decodeTag];
|
||||||
at:&t
|
{
|
||||||
withName:NULL];
|
unsigned char t;
|
||||||
return t;
|
[self decodeValueOfCType:@encode(unsigned char)
|
||||||
|
at:&t
|
||||||
|
withName:NULL];
|
||||||
|
return t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) encodeClass: aClass
|
- (void) encodeClass: aClass
|
||||||
|
@ -552,6 +564,9 @@ exc_return_null(arglist_t f)
|
||||||
|
|
||||||
assert(class_name);
|
assert(class_name);
|
||||||
assert(*class_name);
|
assert(*class_name);
|
||||||
|
/* Do classname substitution, ala encodeClassName:intoClassName */
|
||||||
|
if ([classname_map includesKey: class_name])
|
||||||
|
class_name = [classname_map elementAtKey: class_name].char_ptr_u;
|
||||||
[self encodeTag: CODER_CLASS];
|
[self encodeTag: CODER_CLASS];
|
||||||
[self encodeValueOfCType:@encode(unsigned)
|
[self encodeValueOfCType:@encode(unsigned)
|
||||||
at:&xref
|
at:&xref
|
||||||
|
@ -930,9 +945,23 @@ exc_return_null(arglist_t f)
|
||||||
|
|
||||||
- (void) _doEncodeBycopyObject: anObj
|
- (void) _doEncodeBycopyObject: anObj
|
||||||
{
|
{
|
||||||
[self encodeClass:object_get_class(anObj)];
|
id encoded_object, encoded_class;
|
||||||
|
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 Make sure it responds to this selector! */
|
/* xxx Make sure it responds to this selector! */
|
||||||
[anObj encodeWithCoder:(id)self];
|
[encoded_object encodeWithCoder: (NSCoder*)self];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This method overridden by ConnectedCoder */
|
/* This method overridden by ConnectedCoder */
|
||||||
|
@ -1271,15 +1300,20 @@ exc_return_null(arglist_t f)
|
||||||
|
|
||||||
/* Substituting Classes */
|
/* Substituting Classes */
|
||||||
|
|
||||||
+ (id <String>) classNameEncodedForTrueClassName: (id <String>) trueName
|
- (id <String>) classNameEncodedForTrueClassName: (id <String>) trueName
|
||||||
{
|
{
|
||||||
[self notImplemented:_cmd];
|
assert ( ! [self isDecoding]);
|
||||||
|
return [NSString stringWithCString:
|
||||||
|
[classname_map elementAtKey:
|
||||||
|
[trueName cStringNoCopy]].char_ptr_u];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) encodeClassName: (id <String>) trueName
|
- (void) encodeClassName: (id <String>) trueName
|
||||||
intoClassName: (id <String>) inArchiveName
|
intoClassName: (id <String>) inArchiveName
|
||||||
{
|
{
|
||||||
[self notImplemented:_cmd];
|
assert ( ! [self isDecoding]);
|
||||||
|
[classname_map putElement: [inArchiveName cStringNoCopy]
|
||||||
|
atKey: [trueName cStringNoCopy]];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString*) classNameDecodedForArchiveClassName: (NSString*) inArchiveName
|
+ (NSString*) classNameDecodedForArchiveClassName: (NSString*) inArchiveName
|
||||||
|
@ -1335,60 +1369,7 @@ exc_return_null(arglist_t f)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
/* Here temporarily until GCC category bug is fixed */
|
|
||||||
#include <objects/Connection.h>
|
|
||||||
#include <objects/Proxy.h>
|
|
||||||
#include <objects/ConnectedCoder.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* Eventually put these directly in Object */
|
|
||||||
|
|
||||||
/* By combining these, we're working around the GCC 2.6 bug that
|
|
||||||
causes not all the categories to be processed by the runtime. */
|
|
||||||
|
|
||||||
@implementation NSObject (CoderAdditions)
|
|
||||||
|
|
||||||
/* Now in NSObject.m */
|
|
||||||
#if 0
|
|
||||||
- (void) encodeWithCoder: (id <Encoding>)anEncoder
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- initWithCoder: (id <Decoding>)aDecoder
|
|
||||||
{
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ newWithCoder: (id <Decoding>)aDecoder
|
|
||||||
{
|
|
||||||
return NSAllocateObject(self, 0, NULL); /* xxx Fix this NULL */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* @implementation Object (ConnectionRequests) */
|
|
||||||
|
|
||||||
|
|
||||||
/* By default, Object's encode themselves as proxies across Connection's */
|
|
||||||
- classForConnectedCoder:aRmc
|
|
||||||
{
|
|
||||||
return [[aRmc connection] proxyClass];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* But if any object overrides the above method to return [Object class]
|
|
||||||
instead, the Object implementation of the coding method will actually
|
|
||||||
encode the object itself, not a proxy */
|
|
||||||
+ (void) encodeObject: anObject withConnectedCoder: aRmc
|
|
||||||
{
|
|
||||||
[anObject encodeWithCoder:aRmc];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
|
|
||||||
@implementation Coder (NSCoderCompatibility)
|
@implementation Coder (NSCoderCompatibility)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1407,6 +1388,11 @@ exc_return_null(arglist_t f)
|
||||||
[self encodeArrayOfObjCType: type count: count at: array withName: NULL];
|
[self encodeArrayOfObjCType: type count: count at: array withName: NULL];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) encodeObject: (id)anObject
|
||||||
|
{
|
||||||
|
[self encodeObject: anObject withName: NULL];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) encodeBycopyObject: (id)anObject
|
- (void) encodeBycopyObject: (id)anObject
|
||||||
{
|
{
|
||||||
[self encodeBycopyObject: anObject withName: NULL];
|
[self encodeBycopyObject: anObject withName: NULL];
|
||||||
|
@ -1414,7 +1400,24 @@ exc_return_null(arglist_t f)
|
||||||
|
|
||||||
- (void) encodeConditionalObject: (id)anObject
|
- (void) encodeConditionalObject: (id)anObject
|
||||||
{
|
{
|
||||||
|
/* Apparently, NeXT's implementation doesn't actually
|
||||||
|
handle *forward* references, (hence it's use of -decodeObject,
|
||||||
|
instead of decodeObjectAt:.)
|
||||||
|
So here, we only encode the object for real if the object has
|
||||||
|
already been written.
|
||||||
|
This means that if you encode a web of objects with the more
|
||||||
|
powerful GNU Coder, and then try to decode them with NSArchiver,
|
||||||
|
you could get corrupt data on the stack when Coder resolves its
|
||||||
|
forward references. I recommend just using the GNU Coder. */
|
||||||
|
#if 1
|
||||||
|
unsigned xref = PTR2LONG(anObject);
|
||||||
|
if ([self _coderHasObjectReference:xref])
|
||||||
|
[self encodeObject: anObject];
|
||||||
|
else
|
||||||
|
[self encodeObject: nil];
|
||||||
|
#else
|
||||||
[self encodeObjectReference: anObject withName: NULL];
|
[self encodeObjectReference: anObject withName: NULL];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) encodeDataObject: (NSData*)data
|
- (void) encodeDataObject: (NSData*)data
|
||||||
|
@ -1422,11 +1425,6 @@ exc_return_null(arglist_t f)
|
||||||
[self notImplemented:_cmd];
|
[self notImplemented:_cmd];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) encodeObject: (id)anObject
|
|
||||||
{
|
|
||||||
[self encodeObject: anObject withName: NULL];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) encodePropertyList: (id)plist
|
- (void) encodePropertyList: (id)plist
|
||||||
{
|
{
|
||||||
[self notImplemented:_cmd];
|
[self notImplemented:_cmd];
|
||||||
|
|
Loading…
Reference in a new issue