]> err.no Git - sope/blob - sope-core/EOControl/EOKeyValueArchiver.m
fixed gcc 4.0 warnings
[sope] / sope-core / EOControl / EOKeyValueArchiver.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include "EOKeyValueArchiver.h"
23 #include "common.h"
24
25 @implementation EOKeyValueArchiver
26
27 - (id)init {
28   if ((self = [super init])) {
29     self->plist = [[NSMutableDictionary alloc] init];
30   }
31   return self;
32 }
33
34 - (void)dealloc {
35   [self->plist release];
36   [super dealloc];
37 }
38
39 /* coding */
40
41 static BOOL isPListObject(id _obj) {
42   if ([_obj isKindOfClass:[NSString class]])
43     return YES;
44   if ([_obj isKindOfClass:[NSData class]])
45     return YES;
46   if ([_obj isKindOfClass:[NSArray class]])
47     return YES;
48   return NO;
49 }
50
51 - (void)encodeObject:(id)_obj forKey:(NSString *)_key {
52   NSMutableDictionary *oldPlist;
53
54   if (isPListObject(_obj)) {
55     id c;
56     c = [_obj copy];
57     [self->plist setObject:c forKey:_key];
58     [c release];
59     return;
60   }
61   
62   oldPlist = self->plist;
63   self->plist = [[NSMutableDictionary alloc] init];
64   
65   if (_obj) {
66     /* store class name */
67     [self->plist setObject:NSStringFromClass([_obj class]) forKey:@"class"];
68
69     /* let object store itself */
70     [_obj encodeWithKeyValueArchiver:self];
71   }
72   else {
73     /* nil ??? */
74   }
75
76   [oldPlist setObject:self->plist forKey:_key];
77   [self->plist release];
78   self->plist = oldPlist;
79 }
80
81 - (void)encodeReferenceToObject:(id)_obj forKey:(NSString *)_key {
82   if ([self->delegate respondsToSelector:
83            @selector(archiver:referenceToEncodeForObject:)])
84     _obj = [self->delegate archiver:self referenceToEncodeForObject:_obj];
85
86   /* if _obj wasn't replaced by the delegate, encode the object in place .. */
87   [self encodeObject:_obj forKey:_key];
88 }
89
90 - (void)encodeBool:(BOOL)_flag forKey:(NSString *)_key {
91   /* NO values are not archived .. */
92   if (_flag) {
93     [self->plist setObject:@"YES" forKey:_key];
94   }
95 }
96 - (void)encodeInt:(int)_value forKey:(NSString *)_key {
97   [self->plist setObject:[NSString stringWithFormat:@"%i", _value] forKey:_key];
98 }
99
100 - (NSDictionary *)dictionary {
101   return [[self->plist copy] autorelease];
102 }
103
104 /* delegate */
105
106 - (void)setDelegate:(id)_delegate {
107   self->delegate = _delegate;
108 }
109 - (id)delegate {
110   return self->delegate;
111 }
112
113 @end /* EOKeyValueArchiver */
114
115 @implementation EOKeyValueUnarchiver
116
117 - (id)initWithDictionary:(NSDictionary *)_dict {
118   self->plist = [_dict copy];
119   self->unarchivedObjects = [[NSMutableArray alloc] init];
120   self->awakeObjects      = [[NSMutableSet alloc] init]; // should be a hashtable
121   return self;
122 }
123 - (id)init {
124   [self release];
125   return nil;
126 }
127
128 - (void)dealloc {
129   [self->awakeObjects      release];
130   [self->unarchivedObjects release];
131   [self->plist             release];
132   [super dealloc];
133 }
134
135 /* decoding */
136
137 - (id)decodeObjectForKey:(NSString *)_key {
138   NSString     *className;
139   NSDictionary *lastParent;
140   id obj;
141
142   lastParent   = self->parent;
143   self->parent = self->plist;
144   self->plist  = [(NSDictionary *)self->parent objectForKey:_key];
145
146   if (![self->plist isKindOfClass:[NSDictionary class]]) {
147     obj = [[self->plist copy] autorelease];
148   }
149   else if ((className = [self->plist objectForKey:@"class"]) != nil) {
150     obj = [NSClassFromString(className) alloc];
151     obj = [obj initWithKeyValueUnarchiver:self];
152     
153     [self->unarchivedObjects addObject:obj];
154     [obj release];
155   }
156   else {
157     obj = nil;
158   }
159   
160   self->plist  = self->parent;
161   self->parent = lastParent;
162   
163   return obj;
164 }
165 - (id)decodeObjectReferenceForKey:(NSString *)_key {
166   id refObj, obj;
167
168   refObj = [self decodeObjectForKey:_key];
169
170   if ([self->delegate respondsToSelector:
171            @selector(unarchiver:objectForReference:)]) {
172     obj = [self->delegate unarchiver:self objectForReference:refObj];
173     
174     [self->unarchivedObjects addObject:obj];
175   }
176   else {
177     /* if delegate does not dereference, pass back the reference object */
178     obj = refObj;
179   }
180   return obj;
181 }
182
183 - (BOOL)decodeBoolForKey:(NSString *)_key {
184   return [[self->plist objectForKey:_key] boolValue];
185 }
186 - (int)decodeIntForKey:(NSString *)_key {
187   return [[self->plist objectForKey:_key] intValue];
188 }
189
190 /* operations */
191
192 - (void)ensureObjectAwake:(id)_object {
193   if (![self->awakeObjects containsObject:_object]) {
194     if ([_object respondsToSelector:@selector(awakeFromKeyValueUnarchiver:)]) {
195       [_object awakeFromKeyValueUnarchiver:self];
196     }
197     [self->awakeObjects addObject:_object];
198   }
199 }
200 - (void)awakeObjects {
201   NSEnumerator *e;
202   id obj;
203
204   e = [self->unarchivedObjects objectEnumerator];
205   while ((obj = [e nextObject]))
206     [self ensureObjectAwake:obj];
207 }
208
209 - (void)finishInitializationOfObjects {
210   NSEnumerator *e;
211   id obj;
212
213   e = [self->unarchivedObjects objectEnumerator];
214   while ((obj = [e nextObject])) {
215     if ([obj respondsToSelector:
216                @selector(finishInitializationWithKeyValueUnarchiver:)])
217       [obj finishInitializationWithKeyValueUnarchiver:self];
218   }
219 }
220
221 - (id)parent {
222   return self->parent;
223 }
224
225 /* delegate */
226
227 - (void)setDelegate:(id)_delegate {
228   self->delegate = _delegate;
229 }
230 - (id)delegate {
231   return self->delegate;
232 }
233
234 @end /* EOKeyValueUnarchiver */