[eo removeObject:_object fromPropertyWithKey:dk];
}
+/* key/value archiving */
+
+- (id)initWithKeyValueUnarchiver:(EOKeyValueUnarchiver *)_unarchiver {
+ /*
+ dataSource = {
+ class = EODetailDataSource;
+ detailKey = roles;
+ masterClassDescription = Movie;
+ };
+ */
+ if ((self = [super init])) {
+ NSString *ename;
+
+ self->detailKey = [[_unarchiver decodeObjectForKey:@"detailKey"] copy];
+
+ ename = [_unarchiver decodeObjectForKey:@"masterClassDescription"];
+ NSLog(@"TODO(%s): set class description: %@",
+ __PRETTY_FUNCTION__, ename);
+ }
+ return self;
+}
+- (void)encodeWithKeyValueArchiver:(EOKeyValueArchiver *)_archiver {
+ [_archiver encodeObject:[self detailKey] forKey:@"detailKey"];
+ [_archiver encodeObject:[[self masterClassDescription] entityName]
+ forKey:@"masterClassDescription"];
+}
+
@end /* EODetailDataSource */
@end /* EOKeyValueArchiver */
+
@implementation EOKeyValueUnarchiver
- (id)initWithDictionary:(NSDictionary *)_dict {
self->plist = [_dict copy];
- self->unarchivedObjects = [[NSMutableArray alloc] init];
- self->awakeObjects = [[NSMutableSet alloc] init]; // should be a hashtable
+ self->unarchivedObjects = [[NSMutableArray alloc] initWithCapacity:16];
+ // should be a hashtable
+ self->awakeObjects = [[NSMutableSet alloc] initWithCapacity:16];
return self;
}
- (id)init {
/* decoding */
+- (id)_decodeCurrentPlist {
+ NSString *className;
+ Class clazz;
+ id obj;
+
+ if ([self->plist isKindOfClass:[NSArray class]]) {
+ unsigned count;
+
+ if ((count = [self->plist count]) == 0)
+ obj = [[self->plist copy] autorelease];
+ else {
+ unsigned i;
+ id *objs;
+
+ objs = calloc(count + 1, sizeof(id));
+ for (i = 0; i < count; i++)
+ objs[i] = [self decodeObjectAtIndex:i];
+
+ obj = [NSArray arrayWithObjects:objs count:count];
+ if (objs != NULL) free(objs);
+ }
+ return obj;
+ }
+
+ if (![self->plist isKindOfClass:[NSDictionary class]])
+ return [[self->plist copy] autorelease];
+
+ /* handle dictionary */
+
+ if ((className = [self->plist objectForKey:@"class"]) == nil)
+ return [[self->plist copy] autorelease]; /* treat as plain dictionary */
+
+ if ((clazz = [self classForName:className]) == nil) {
+ NSLog(@"WARNING(%s): did not find class specified in archive '%@': %@",
+ __PRETTY_FUNCTION__, className, self->plist);
+ return nil;
+ }
+
+ /* create custom object */
+
+ obj = [clazz alloc];
+ obj = [obj initWithKeyValueUnarchiver:self];
+
+ if (obj != nil)
+ [self->unarchivedObjects addObject:obj];
+ else {
+ NSLog(@"WARNING(%s): could not unarchive object %@",
+ __PRETTY_FUNCTION__, self->plist);
+ }
+ if (self->unarchivedObjects != nil)
+ [obj release];
+ else
+ [obj autorelease];
+
+ return obj;
+}
+
+- (id)decodeObjectAtIndex:(unsigned)_idx {
+ NSDictionary *lastParent;
+ id obj;
+
+ /* push */
+ lastParent = self->parent;
+ self->parent = self->plist;
+ self->plist = [(NSArray *)self->parent objectAtIndex:_idx];
+
+ obj = [self _decodeCurrentPlist];
+
+ /* pop */
+ self->plist = self->parent;
+ self->parent = lastParent;
+
+ return obj ? obj : [NSNull null];
+}
+
- (id)decodeObjectForKey:(NSString *)_key {
- NSString *className;
NSDictionary *lastParent;
id obj;
+ /* push */
lastParent = self->parent;
self->parent = self->plist;
self->plist = [(NSDictionary *)self->parent objectForKey:_key];
- if (![self->plist isKindOfClass:[NSDictionary class]]) {
- obj = [[self->plist copy] autorelease];
- }
- else if ((className = [self->plist objectForKey:@"class"]) != nil) {
- Class clazz;
-
- if ((clazz = [self classForName:className]) != nil) {
- obj = [clazz alloc];
- obj = [obj initWithKeyValueUnarchiver:self];
-
- if (obj != nil)
- [self->unarchivedObjects addObject:obj];
- else {
- NSLog(@"WARNING(%s): could not unarchive object %@",
- __PRETTY_FUNCTION__, self->plist);
- }
- if (self->unarchivedObjects != nil)
- [obj release];
- else
- [obj autorelease];
- }
- else {
- NSLog(@"WARNING(%s): did not find class specified in archive '%@': %@",
- __PRETTY_FUNCTION__, className, self->plist);
- }
- }
- else {
- obj = nil;
- }
+ obj = [self _decodeCurrentPlist];
+ /* pop */
self->plist = self->parent;
self->parent = lastParent;
@selector(unarchiver:objectForReference:)]) {
obj = [self->delegate unarchiver:self objectForReference:refObj];
- [self->unarchivedObjects addObject:obj];
+ if (obj != nil)
+ [self->unarchivedObjects addObject:obj];
}
else {
/* if delegate does not dereference, pass back the reference object */
id obj;
e = [self->unarchivedObjects objectEnumerator];
- while ((obj = [e nextObject]))
+ while ((obj = [e nextObject]) != nil)
[self ensureObjectAwake:obj];
}
id obj;
e = [self->unarchivedObjects objectEnumerator];
- while ((obj = [e nextObject])) {
+ while ((obj = [e nextObject]) != nil) {
if ([obj respondsToSelector:
@selector(finishInitializationWithKeyValueUnarchiver:)])
[obj finishInitializationWithKeyValueUnarchiver:self];