More keyed coding updates.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18495 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2004-01-28 07:33:20 +00:00
parent 811be03fe2
commit 5893a40526
11 changed files with 326 additions and 118 deletions

View file

@ -1,7 +1,16 @@
2004-01-28 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSKeyedUnrchiver.m: Store objects in map while they are
decoding themselves, s they can be self referential.
decoding themselves so they can be self referential.
* Source/GSArray.m:
* Source/NSArray.m:
* Source/GSSet.m:
* Source/NSSet.m:
* Source/GSDictionary.m:
* Source/NSDictionary.m:
* Source/NSString.m:
Made keyed decoding able to handle more variations.
Added keyed encoding support.
2004-01-27 Fred Kiefer <FredKiefer@gmx.de>

View file

@ -215,9 +215,11 @@
@interface NSKeyedArchiver (Internal)
- (void) _encodeArrayOfObjects: (NSArray*)anArray forKey: (NSString*)aKey;
- (void) _encodePropertyList: (id)anObject forKey: (NSString*)aKey;
@end
@interface NSKeyedUnarchiver (Internal)
- (id) _decodeArrayOfObjectsForKey: (NSString*)aKey;
- (id) _decodePropertyListForKey: (NSString*)aKey;
@end

View file

@ -168,13 +168,22 @@ static Class GSInlineArrayClass;
- (void) encodeWithCoder: (NSCoder*)aCoder
{
[aCoder encodeValueOfObjCType: @encode(unsigned)
at: &_count];
if (_count > 0)
if ([aCoder allowsKeyedCoding])
{
[aCoder encodeArrayOfObjCType: @encode(id)
count: _count
at: _contents_array];
[super encodeWithCoder: aCoder];
}
else
{
/* For performace we encode directly ... must exactly match the
* superclass implemenation. */
[aCoder encodeValueOfObjCType: @encode(unsigned)
at: &_count];
if (_count > 0)
{
[aCoder encodeArrayOfObjCType: @encode(id)
count: _count
at: _contents_array];
}
}
}
@ -182,27 +191,26 @@ static Class GSInlineArrayClass;
{
if ([aCoder allowsKeyedCoding])
{
NSArray *array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
[self initWithArray: array];
self = [super initWithCoder: aCoder];
}
else
{
[aCoder decodeValueOfObjCType: @encode(unsigned)
at: &_count];
if (_count > 0)
{
_contents_array = NSZoneCalloc([self zone], _count, sizeof(id));
if (_contents_array == 0)
{
[NSException raise: NSMallocException
format: @"Unable to make array"];
}
[aCoder decodeArrayOfObjCType: @encode(id)
count: _count
at: _contents_array];
}
/* for performance, we decode directly into memory rather than
* using the superclass method. Must exactly match superclass. */
[aCoder decodeValueOfObjCType: @encode(unsigned)
at: &_count];
if (_count > 0)
{
_contents_array = NSZoneCalloc([self zone], _count, sizeof(id));
if (_contents_array == 0)
{
[NSException raise: NSMallocException
format: @"Unable to make array"];
}
[aCoder decodeArrayOfObjCType: @encode(id)
count: _count
at: _contents_array];
}
}
return self;
}

View file

@ -104,20 +104,27 @@ static SEL objSel;
- (void) encodeWithCoder: (NSCoder*)aCoder
{
unsigned count = map.nodeCount;
SEL sel = @selector(encodeObject:);
IMP imp = [aCoder methodForSelector: sel];
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
while (node != 0)
if ([aCoder allowsKeyedCoding])
{
(*imp)(aCoder, sel, node->key.obj);
(*imp)(aCoder, sel, node->value.obj);
node = GSIMapEnumeratorNextNode(&enumerator);
self = [super initWithCoder: aCoder];
}
else
{
unsigned count = map.nodeCount;
SEL sel = @selector(encodeObject:);
IMP imp = [aCoder methodForSelector: sel];
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
while (node != 0)
{
(*imp)(aCoder, sel, node->key.obj);
(*imp)(aCoder, sel, node->value.obj);
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
- (unsigned) hash
@ -129,12 +136,7 @@ static SEL objSel;
{
if ([aCoder allowsKeyedCoding])
{
NSArray *keys = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.keys"];
NSArray *objects = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
self = [self initWithObjects: objects forKeys: keys];
self = [super initWithCoder: aCoder];
}
else
{

View file

@ -167,19 +167,26 @@ static Class mutableSetClass;
- (void) encodeWithCoder: (NSCoder*)aCoder
{
unsigned count = map.nodeCount;
SEL sel = @selector(encodeObject:);
IMP imp = [aCoder methodForSelector: sel];
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
while (node != 0)
if ([aCoder allowsKeyedCoding])
{
(*imp)(aCoder, sel, node->key.obj);
node = GSIMapEnumeratorNextNode(&enumerator);
[super encodeWithCoder: aCoder];
}
else
{
unsigned count = map.nodeCount;
SEL sel = @selector(encodeObject:);
IMP imp = [aCoder methodForSelector: sel];
GSIMapEnumerator_t enumerator = GSIMapEnumeratorForMap(&map);
GSIMapNode node = GSIMapEnumeratorNextNode(&enumerator);
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
while (node != 0)
{
(*imp)(aCoder, sel, node->key.obj);
node = GSIMapEnumeratorNextNode(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
GSIMapEndEnumerator(&enumerator);
}
- (unsigned) hash
@ -191,10 +198,7 @@ static Class mutableSetClass;
{
if ([aCoder allowsKeyedCoding])
{
NSArray *array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
return [self initWithArray: array];
self = [super initWithCoder: aCoder];
}
else
{
@ -212,9 +216,8 @@ static Class mutableSetClass;
(*imp)(aCoder, sel, type, &value);
GSIMapAddKeyNoRetain(&map, (GSIMapKey)value);
}
return self;
}
return self;
}
/* Designated initialiser */

View file

@ -357,18 +357,45 @@ static SEL rlSel;
{
unsigned count = [self count];
[aCoder encodeValueOfObjCType: @encode(unsigned)
at: &count];
if (count > 0)
if ([aCoder allowsKeyedCoding])
{
GS_BEGINIDBUF(a, count)
/* HACK ... MacOS-X seems to code differently if the coder is an
* actual instance of NSKeyedArchiver
*/
if ([aCoder class] == [NSKeyedArchiver class])
{
[(NSKeyedArchiver*)aCoder _encodeArrayOfObjects: self
forKey: @"NS.objects"];
}
else
{
unsigned i;
[self getObjects: a];
[aCoder encodeArrayOfObjCType: @encode(id)
count: count
at: a];
GS_ENDIDBUF()
for (i = 0; i < count; i++)
{
NSString *key;
key = [NSString stringWithFormat: @"NS.object.%u", i];
[(NSKeyedArchiver*)aCoder encodeObject: [self objectAtIndex: i]
forKey: key];
}
}
}
else
{
[aCoder encodeValueOfObjCType: @encode(unsigned)
at: &count];
if (count > 0)
{
GS_BEGINIDBUF(a, count)
[self getObjects: a];
[aCoder encodeArrayOfObjCType: @encode(id)
count: count
at: a];
GS_ENDIDBUF()
}
}
}
@ -556,10 +583,30 @@ static SEL rlSel;
{
if ([aCoder allowsKeyedCoding])
{
NSArray *array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
id array;
[self initWithArray: array];
array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
if (array == nil)
{
unsigned i = 0;
NSString *key;
id val;
array = [NSMutableArray arrayWithCapacity: 2];
key = [NSString stringWithFormat: @"NS.object.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
while (val != nil)
{
[array addObject: val];
i++;
key = [NSString stringWithFormat: @"NS.object.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
}
}
self = [self initWithArray: array];
}
else
{

View file

@ -180,25 +180,68 @@ static SEL appSel;
{
unsigned count = [self count];
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
if (count > 0)
if ([aCoder allowsKeyedCoding])
{
NSEnumerator *enumerator = [self keyEnumerator];
id key;
IMP enc;
IMP nxt;
IMP ofk;
nxt = [enumerator methodForSelector: @selector(nextObject)];
enc = [aCoder methodForSelector: @selector(encodeObject:)];
ofk = [self methodForSelector: @selector(objectForKey:)];
while ((key = (*nxt)(enumerator, @selector(nextObject))) != nil)
if (count > 0)
{
id val = (*ofk)(self, @selector(objectForKey:), key);
NSEnumerator *enumerator = [self keyEnumerator];
id key;
(*enc)(aCoder, @selector(encodeObject:), key);
(*enc)(aCoder, @selector(encodeObject:), val);
if ([aCoder class] == [NSKeyedArchiver class])
{
NSArray *keys = [self allKeys];
id objects = [NSMutableArray arrayWithCapacity: count];
unsigned i;
for (i = 0; i < count; i++)
{
key = [keys objectAtIndex: i];
[objects addObject: [self objectForKey: key]];
}
[(NSKeyedArchiver*)aCoder _encodeArrayOfObjects: keys
forKey: @"NS.keys"];
[(NSKeyedArchiver*)aCoder _encodeArrayOfObjects: objects
forKey: @"NS.objects"];
}
else
{
unsigned i = 0;
while ((key = [enumerator nextObject]) != nil)
{
NSString *s;
s = [NSString stringWithFormat: @"NS.key.%u", i];
[aCoder encodeObject: key forKey: s];
s = [NSString stringWithFormat: @"NS.object.%u", i];
[aCoder encodeObject: [self objectForKey: key] forKey: s];
i++;
}
}
}
}
else
{
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
if (count > 0)
{
NSEnumerator *enumerator = [self keyEnumerator];
id key;
IMP enc;
IMP nxt;
IMP ofk;
nxt = [enumerator methodForSelector: @selector(nextObject)];
enc = [aCoder methodForSelector: @selector(encodeObject:)];
ofk = [self methodForSelector: @selector(objectForKey:)];
while ((key = (*nxt)(enumerator, @selector(nextObject))) != nil)
{
id val = (*ofk)(self, @selector(objectForKey:), key);
(*enc)(aCoder, @selector(encodeObject:), key);
(*enc)(aCoder, @selector(encodeObject:), val);
}
}
}
}
@ -207,11 +250,35 @@ static SEL appSel;
{
if ([aCoder allowsKeyedCoding])
{
NSArray *keys = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.keys"];
NSArray *objects = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
id keys;
id objects;
keys = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.keys"];
objects = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
if (keys == nil)
{
unsigned i = 0;
NSString *key;
id val;
keys = [NSMutableArray arrayWithCapacity: 2];
objects = [NSMutableArray arrayWithCapacity: 2];
key = [NSString stringWithFormat: @"NS.object.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
while (val != nil)
{
[objects addObject: val];
key = [NSString stringWithFormat: @"NS.key.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
[keys addObject: val];
i++;
key = [NSString stringWithFormat: @"NS.object.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
}
}
self = [self initWithObjects: objects forKeys: keys];
}
else

View file

@ -151,6 +151,12 @@ static NSDictionary *makeReference(unsigned ref)
}
[_enc setObject: o forKey: aKey];
}
- (void) _encodePropertyList: (id)anObject forKey: (NSString*)aKey
{
CHECKKEY
[_enc setObject: anObject forKey: aKey];
}
@end
@implementation NSKeyedArchiver (Private)

View file

@ -115,6 +115,13 @@ static NSMapTable globalClassMap = 0;
}
return o;
}
- (id) _decodePropertyListForKey: (NSString*)aKey
{
id o = [_keyMap objectForKey: aKey];
return o;
}
@end
@implementation NSKeyedUnarchiver (Private)

View file

@ -139,14 +139,42 @@ static Class NSMutableSet_concrete_class;
- (void) encodeWithCoder: (NSCoder*)aCoder
{
unsigned count = [self count];
NSEnumerator *e = [self objectEnumerator];
id o;
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
while ((o = [e nextObject]) != nil)
if ([aCoder allowsKeyedCoding])
{
[aCoder encodeValueOfObjCType: @encode(id) at: &o];
/* HACK ... MacOS-X seems to code differently if the coder is an
* actual instance of NSKeyedArchiver
*/
if ([aCoder class] == [NSKeyedArchiver class])
{
[(NSKeyedArchiver*)aCoder _encodeArrayOfObjects: [self allObjects]
forKey: @"NS.objects"];
}
else
{
unsigned i = 0;
NSEnumerator *e = [self objectEnumerator];
id o;
while ((o = [e nextObject]) != nil)
{
NSString *key;
key = [NSString stringWithFormat: @"NS.object.%u", i++];
[(NSKeyedArchiver*)aCoder encodeObject: o forKey: key];
}
}
}
else
{
unsigned count = [self count];
NSEnumerator *e = [self objectEnumerator];
id o;
[aCoder encodeValueOfObjCType: @encode(unsigned) at: &count];
while ((o = [e nextObject]) != nil)
{
[aCoder encodeValueOfObjCType: @encode(id) at: &o];
}
}
}
@ -170,10 +198,29 @@ static Class NSMutableSet_concrete_class;
if ([aCoder allowsKeyedCoding])
{
NSArray *array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
id array;
return [self initWithArray: array];
array = [(NSKeyedUnarchiver*)aCoder _decodeArrayOfObjectsForKey:
@"NS.objects"];
if (array == nil)
{
unsigned i = 0;
NSString *key;
id val;
array = [NSMutableArray arrayWithCapacity: 2];
key = [NSString stringWithFormat: @"NS.object.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
while (val != nil)
{
[array addObject: val];
i++;
key = [NSString stringWithFormat: @"NS.object.%u", i];
val = [(NSKeyedUnarchiver*)aCoder decodeObjectForKey: key];
}
}
self = [self initWithArray: array];
}
else
{
@ -197,8 +244,8 @@ static Class NSMutableSet_concrete_class;
}
#endif
}
return self;
}
return self;
}
/* <init />

View file

@ -3859,22 +3859,32 @@ handle_printf_atsign (FILE *stream,
- (void) encodeWithCoder: (NSCoder*)aCoder
{
unsigned count = [self length];
[aCoder encodeValueOfObjCType: @encode(unsigned int) at: &count];
if (count > 0)
if ([aCoder allowsKeyedCoding])
{
NSStringEncoding enc = NSUnicodeStringEncoding;
unichar *chars;
// FIXME
[NSException raise: NSInvalidArgumentException
format: @"%@ doesn't know how to encode with keyed coder",
NSStringFromClass([self class])];
}
else
{
unsigned count = [self length];
[aCoder encodeValueOfObjCType: @encode(NSStringEncoding) at: &enc];
[aCoder encodeValueOfObjCType: @encode(unsigned int) at: &count];
if (count > 0)
{
NSStringEncoding enc = NSUnicodeStringEncoding;
unichar *chars;
chars = NSZoneMalloc(NSDefaultMallocZone(), count*sizeof(unichar));
[self getCharacters: chars];
[aCoder encodeArrayOfObjCType: @encode(unichar)
count: count
at: chars];
NSZoneFree(NSDefaultMallocZone(), chars);
[aCoder encodeValueOfObjCType: @encode(NSStringEncoding) at: &enc];
chars = NSZoneMalloc(NSDefaultMallocZone(), count*sizeof(unichar));
[self getCharacters: chars];
[aCoder encodeArrayOfObjCType: @encode(unichar)
count: count
at: chars];
NSZoneFree(NSDefaultMallocZone(), chars);
}
}
}
@ -3917,7 +3927,7 @@ handle_printf_atsign (FILE *stream,
freeWhenDone: YES];
}
else if (enc == NSASCIIStringEncoding
|| enc == _DefaultStringEncoding)
|| enc == _DefaultStringEncoding)
{
unsigned char *chars;