00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPCoder.j"
00024 @import "CPNull.j"
00025
00026
00027 CPInvalidUnarchiveOperationException = @"CPInvalidUnarchiveOperationException";
00028
00029 var _CPKeyedUnarchiverCannotDecodeObjectOfClassNameOriginalClassesSelector = 1 << 0,
00030 _CPKeyedUnarchiverDidDecodeObjectSelector = 1 << 1,
00031 _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector = 1 << 2,
00032 _CPKeyedUnarchiverWillFinishSelector = 1 << 3,
00033 _CPKeyedUnarchiverDidFinishSelector = 1 << 4,
00034 CPKeyedUnarchiverDelegate_unarchiver_cannotDecodeObjectOfClassName_originalClasses_ = 1 << 5;
00035
00036 var _CPKeyedArchiverNullString = "$null"
00037
00038 _CPKeyedArchiverUIDKey = "CP$UID",
00039
00040 _CPKeyedArchiverTopKey = "$top",
00041 _CPKeyedArchiverObjectsKey = "$objects",
00042 _CPKeyedArchiverArchiverKey = "$archiver",
00043 _CPKeyedArchiverVersionKey = "$version",
00044
00045 _CPKeyedArchiverClassNameKey = "$classname",
00046 _CPKeyedArchiverClassesKey = "$classes",
00047 _CPKeyedArchiverClassKey = "$class";
00048
00049 var CPArrayClass = Nil,
00050 CPMutableArrayClass = Nil,
00051 CPStringClass = Nil,
00052 CPDictionaryClass = Nil,
00053 CPMutableDictionaryClass = Nil,
00054 CPNumberClass = Nil,
00055 CPDataClass = Nil,
00056 _CPKeyedArchiverValueClass = Nil;
00057
00104 @implementation CPKeyedUnarchiver : CPCoder
00105 {
00106 id _delegate;
00107 unsigned _delegateSelectors;
00108
00109 CPData _data;
00110
00111 CPDictionary _replacementClasses;
00112
00113 CPArray _objects;
00114 CPDictionary _archive;
00115
00116 CPDictionary _plistObject;
00117 CPArray _plistObjects;
00118 }
00119
00120
00121
00122
00123 + (void)initialize
00124 {
00125 if (self !== [CPKeyedUnarchiver class])
00126 return;
00127
00128 CPArrayClass = [CPArray class];
00129 CPMutableArrayClass = [CPMutableArray class];
00130 CPStringClass = [CPString class];
00131 CPDictionaryClass = [CPDictionary class];
00132 CPMutableDictionaryClass = [CPMutableDictionary class];
00133 CPNumberClass = [CPNumber class];
00134 CPDataClass = [CPData class];
00135 _CPKeyedArchiverValueClass = [_CPKeyedArchiverValue class];
00136 }
00137
00138
00139
00140
00141
00142
00143 - (id)initForReadingWithData:(CPData)data
00144 {
00145 self = [super init];
00146
00147 if (self)
00148 {
00149 _archive = [data plistObject];
00150 _objects = [[CPNull null]];
00151
00152 _plistObject = [_archive objectForKey:_CPKeyedArchiverTopKey];
00153 _plistObjects = [_archive objectForKey:_CPKeyedArchiverObjectsKey];
00154
00155 _replacementClasses = new CFMutableDictionary();
00156 }
00157
00158 return self;
00159 }
00160
00161
00162
00163
00164
00165
00166 + (id)unarchiveObjectWithData:(CPData)aData
00167 {
00168 if (!aData)
00169 {
00170 CPLog.error("Null data passed to -[CPKeyedUnarchiver unarchiveObjectWithData:].");
00171 return nil;
00172 }
00173
00174 var unarchiver = [[self alloc] initForReadingWithData:aData],
00175 object = [unarchiver decodeObjectForKey:@"root"];
00176
00177 [unarchiver finishDecoding];
00178
00179 return object;
00180 }
00181
00182
00183
00184
00185 + (id)unarchiveObjectWithFile:(CPString)aFilePath
00186 {
00187 }
00188
00189
00190
00191
00192 + (id)unarchiveObjectWithFile:(CPString)aFilePath asynchronously:(BOOL)aFlag
00193 {
00194 }
00195
00196
00197
00198
00199
00200 - (BOOL)containsValueForKey:(CPString)aKey
00201 {
00202 return _plistObject.valueForKey(aKey) != nil;
00203 }
00204
00205
00206 - (CPDictionary)_decodeDictionaryOfObjectsForKey:(CPString)aKey
00207 {
00208 var object = _plistObject.valueForKey(aKey),
00209 objectClass = (object != nil) && object.isa;
00210
00211 if (objectClass === CPDictionaryClass || objectClass === CPMutableDictionaryClass)
00212 {
00213 var keys = object.keys(),
00214 index = 0,
00215 count = keys.length,
00216 dictionary = new CFMutableDictionary();
00217
00218 for (; index < count; ++index)
00219 {
00220 var key = keys[index];
00221
00222 dictionary.setValueForKey(key, _CPKeyedUnarchiverDecodeObjectAtIndex(self, object.valueForKey(key).valueForKey(_CPKeyedArchiverUIDKey)));
00223 }
00224
00225 return dictionary;
00226 }
00227
00228 return nil;
00229 }
00230
00231
00232
00233
00234
00235
00236 - (BOOL)decodeBoolForKey:(CPString)aKey
00237 {
00238 return [self decodeObjectForKey:aKey];
00239 }
00240
00241
00242
00243
00244
00245
00246 - (float)decodeFloatForKey:(CPString)aKey
00247 {
00248 return [self decodeObjectForKey:aKey];
00249 }
00250
00251
00252
00253
00254
00255
00256 - (double)decodeDoubleForKey:(CPString)aKey
00257 {
00258 return [self decodeObjectForKey:aKey];
00259 }
00260
00261
00262
00263
00264
00265
00266 - (int)decodeIntForKey:(CPString)aKey
00267 {
00268 return [self decodeObjectForKey:aKey];
00269 }
00270
00271
00272
00273
00274
00275
00276 - (CGPoint)decodePointForKey:(CPString)aKey
00277 {
00278 var object = [self decodeObjectForKey:aKey];
00279
00280 if(object)
00281 return CPPointFromString(object);
00282 else
00283 return CPPointMake(0.0, 0.0);
00284 }
00285
00286
00287
00288
00289
00290
00291 - (CGRect)decodeRectForKey:(CPString)aKey
00292 {
00293 var object = [self decodeObjectForKey:aKey];
00294
00295 if(object)
00296 return CPRectFromString(object);
00297 else
00298 return CPRectMakeZero();
00299 }
00300
00301
00302
00303
00304
00305
00306 - (CGSize)decodeSizeForKey:(CPString)aKey
00307 {
00308 var object = [self decodeObjectForKey:aKey];
00309
00310 if(object)
00311 return CPSizeFromString(object);
00312 else
00313 return CPSizeMake(0.0, 0.0);
00314 }
00315
00316
00317
00318
00319
00320
00321 - (id)decodeObjectForKey:(CPString)aKey
00322 {
00323 var object = _plistObject.valueForKey(aKey),
00324 objectClass = (object != nil) && object.isa;
00325
00326 if (objectClass === CPDictionaryClass || objectClass === CPMutableDictionaryClass)
00327 return _CPKeyedUnarchiverDecodeObjectAtIndex(self, object.valueForKey(_CPKeyedArchiverUIDKey));
00328
00329 else if (objectClass === CPNumberClass || objectClass === CPDataClass || objectClass === CPStringClass)
00330 return object;
00331
00332 else if (objectClass === CPArrayClass || objectClass === CPMutableArrayClass)
00333 {
00334 var index = 0,
00335 count = object.length,
00336 array = [];
00337
00338 for (; index < count; ++index)
00339 array[index] = _CPKeyedUnarchiverDecodeObjectAtIndex(self, object[index].valueForKey(_CPKeyedArchiverUIDKey));
00340
00341 return array;
00342 }
00343
00344
00345
00346 return nil;
00347 }
00348
00349
00350
00351
00352
00353
00354 - (id)decodeBytesForKey:(CPString)aKey
00355 {
00356
00357 var data = [self decodeObjectForKey:aKey],
00358 objectClass = data.isa;
00359
00360 if (objectClass === CPDataClass)
00361 return data.bytes;
00362
00363 return nil;
00364 }
00365
00366
00367
00368
00369 - (void)finishDecoding
00370 {
00371 if (_delegateSelectors & _CPKeyedUnarchiverWillFinishSelector)
00372 [_delegate unarchiverWillFinish:self];
00373
00374 if (_delegateSelectors & _CPKeyedUnarchiverDidFinishSelector)
00375 [_delegate unarchiverDidFinish:self];
00376 }
00377
00378
00379
00380
00381 - (id)delegate
00382 {
00383 return _delegate;
00384 }
00385
00386
00387
00388
00389
00390 - (void)setDelegate:(id)aDelegate
00391 {
00392 _delegate = aDelegate;
00393
00394 if ([_delegate respondsToSelector:@selector(unarchiver:cannotDecodeObjectOfClassName:originalClasses:)])
00395 _delegateSelectors |= _CPKeyedUnarchiverCannotDecodeObjectOfClassNameOriginalClassesSelector;
00396
00397 if ([_delegate respondsToSelector:@selector(unarchiver:didDecodeObject:)])
00398 _delegateSelectors |= _CPKeyedUnarchiverDidDecodeObjectSelector;
00399
00400 if ([_delegate respondsToSelector:@selector(unarchiver:willReplaceObject:withObject:)])
00401 _delegateSelectors |= _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector;
00402
00403 if ([_delegate respondsToSelector:@selector(unarchiverWillFinish:)])
00404 _delegateSelectors |= _CPKeyedUnarchiverWilFinishSelector;
00405
00406 if ([_delegate respondsToSelector:@selector(unarchiverDidFinish:)])
00407 _delegateSelectors |= _CPKeyedUnarchiverDidFinishSelector;
00408
00409 if ([_delegate respondsToSelector:@selector(unarchiver:cannotDecodeObjectOfClassName:originalClasses:)])
00410 _delegateSelectors |= CPKeyedUnarchiverDelegate_unarchiver_cannotDecodeObjectOfClassName_originalClasses_;
00411 }
00412
00413 - (void)setClass:(Class)aClass forClassName:(CPString)aClassName
00414 {
00415 _replacementClasses.setValueForKey(aClassName, aClass);
00416 }
00417
00418 - (Class)classForClassName:(CPString)aClassName
00419 {
00420 return _replacementClasses.valueForKey(aClassName);
00421 }
00422
00423 - (BOOL)allowsKeyedCoding
00424 {
00425 return YES;
00426 }
00427
00428 @end
00429
00430 var _CPKeyedUnarchiverDecodeObjectAtIndex = function(self, anIndex)
00431 {
00432 var object = self._objects[anIndex];
00433
00434 if (object)
00435 if (object === self._objects[0])
00436 return nil;
00437 else
00438 return object;
00439
00440 var object,
00441 plistObject = self._plistObjects[anIndex],
00442 plistObjectClass = plistObject.isa;
00443
00444 if (plistObjectClass === CPDictionaryClass || plistObjectClass === CPMutableDictionaryClass)
00445 {
00446 var plistClass = self._plistObjects[plistObject.valueForKey(_CPKeyedArchiverClassKey).valueForKey(_CPKeyedArchiverUIDKey)],
00447 className = plistClass.valueForKey(_CPKeyedArchiverClassNameKey),
00448 classes = plistClass.valueForKey(_CPKeyedArchiverClassesKey),
00449 theClass = [self classForClassName:className];
00450
00451 if (!theClass)
00452 theClass = CPClassFromString(className);
00453
00454 if (!theClass && (self._delegateSelectors & CPKeyedUnarchiverDelegate_unarchiver_cannotDecodeObjectOfClassName_originalClasses_))
00455 theClass = [_delegate unarchiver:self cannotDecodeObjectOfClassName:className originalClasses:classes];
00456
00457 if (!theClass)
00458 [CPException raise:CPInvalidUnarchiveOperationException reason:@"-[CPKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (" + className + @")"];
00459
00460 var savedPlistObject = self._plistObject;
00461
00462 self._plistObject = plistObject;
00463
00464
00465 object = [theClass allocWithCoder:self];
00466
00467
00468 self._objects[anIndex] = object;
00469
00470 var processedObject = [object initWithCoder:self];
00471
00472 self._plistObject = savedPlistObject;
00473
00474 if (processedObject !== object)
00475 {
00476 if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
00477 [self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
00478
00479 object = processedObject;
00480 self._objects[anIndex] = processedObject;
00481 }
00482
00483 processedObject = [object awakeAfterUsingCoder:self];
00484
00485 if (processedObject !== object)
00486 {
00487 if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
00488 [self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
00489
00490 object = processedObject;
00491 self._objects[anIndex] = processedObject;
00492 }
00493
00494 if (self._delegate)
00495 {
00496 if (self._delegateSelectors & _CPKeyedUnarchiverDidDecodeObjectSelector)
00497 processedObject = [self._delegate unarchiver:self didDecodeObject:object];
00498
00499 if (processedObject != object)
00500 {
00501 if (self._delegateSelectors & _CPKeyedUnarchiverWillReplaceObjectWithObjectSelector)
00502 [self._delegate unarchiver:self willReplaceObject:object withObject:processedObject];
00503
00504 object = processedObject;
00505 self._objects[anIndex] = processedObject;
00506 }
00507 }
00508 }
00509 else
00510 {
00511 self._objects[anIndex] = object = plistObject;
00512
00513 if ([object class] === CPStringClass)
00514 {
00515 if (object === _CPKeyedArchiverNullString)
00516 {
00517 self._objects[anIndex] = self._objects[0];
00518
00519 return nil;
00520 }
00521 else
00522 self._objects[anIndex] = object = plistObject;
00523 }
00524 }
00525
00526
00527
00528 if ((object != nil) && (object.isa === _CPKeyedArchiverValueClass))
00529 object = [object JSObject];
00530
00531 return object;
00532 }