00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPData.j"
00024 @import "CPCoder.j"
00025 @import "CPArray.j"
00026 @import "CPString.j"
00027 @import "CPNumber.j"
00028 @import "CPDictionary.j"
00029 @import "CPValue.j"
00030
00031
00032 var CPArchiverReplacementClassNames = nil;
00033
00034 var _CPKeyedArchiverDidEncodeObjectSelector = 1,
00035 _CPKeyedArchiverWillEncodeObjectSelector = 2,
00036 _CPKeyedArchiverWillReplaceObjectWithObjectSelector = 4,
00037 _CPKeyedArchiverDidFinishSelector = 8,
00038 _CPKeyedArchiverWillFinishSelector = 16;
00039
00040 var _CPKeyedArchiverNullString = "$null",
00041 _CPKeyedArchiverNullReference = nil,
00042
00043 _CPKeyedArchiverUIDKey = "CP$UID",
00044
00045 _CPKeyedArchiverTopKey = "$top",
00046 _CPKeyedArchiverObjectsKey = "$objects",
00047 _CPKeyedArchiverArchiverKey = "$archiver",
00048 _CPKeyedArchiverVersionKey = "$version",
00049
00050 _CPKeyedArchiverClassNameKey = "$classname",
00051 _CPKeyedArchiverClassesKey = "$classes",
00052 _CPKeyedArchiverClassKey = "$class";
00053
00054 var _CPKeyedArchiverStringClass = Nil,
00055 _CPKeyedArchiverNumberClass = Nil;
00056
00057
00058 @implementation _CPKeyedArchiverValue : CPValue
00059 {
00060 }
00061 @end
00062
00102 @implementation CPKeyedArchiver : CPCoder
00103 {
00104 id _delegate;
00105 unsigned _delegateSelectors;
00106
00107 CPData _data;
00108
00109 CPArray _objects;
00110
00111 CPDictionary _UIDs;
00112 CPDictionary _conditionalUIDs;
00113
00114 CPDictionary _replacementObjects;
00115 CPDictionary _replacementClassNames;
00116
00117 id _plistObject;
00118 CPMutableArray _plistObjects;
00119
00120 CPPropertyListFormat _outputFormat;
00121
00122 }
00123
00124
00125
00126
00127 + (void)initialize
00128 {
00129 if (self != [CPKeyedArchiver class])
00130 return;
00131
00132 _CPKeyedArchiverStringClass = [CPString class];
00133 _CPKeyedArchiverNumberClass = [CPNumber class];
00134
00135 _CPKeyedArchiverNullReference = [CPDictionary dictionaryWithObject:0 forKey:_CPKeyedArchiverUIDKey];
00136 }
00137
00138 + (BOOL)allowsKeyedCoding
00139 {
00140 return YES;
00141 }
00142
00148 + (CPData)archivedDataWithRootObject:(id)anObject
00149 {
00150 var data = [CPData dataWithPlistObject:nil],
00151 archiver = [[self alloc] initForWritingWithMutableData:data];
00152
00153 [archiver encodeObject:anObject forKey:@"root"];
00154 [archiver finishEncoding];
00155
00156 return data;
00157 }
00158
00159
00165 - (id)initForWritingWithMutableData:(CPMutableData)data
00166 {
00167 self = [super init];
00168
00169 if (self)
00170 {
00171 _data = data;
00172
00173 _objects = [];
00174
00175 _UIDs = [CPDictionary dictionary];
00176 _conditionalUIDs = [CPDictionary dictionary];
00177
00178 _replacementObjects = [CPDictionary dictionary];
00179
00180 _data = data;
00181
00182 _plistObject = [CPDictionary dictionary];
00183 _plistObjects = [CPArray arrayWithObject:_CPKeyedArchiverNullString];
00184 }
00185
00186 return self;
00187 }
00188
00189
00194 - (void)finishEncoding
00195 {
00196 if (_delegate && _delegateSelectors & _CPKeyedArchiverWillFinishSelector)
00197 [_delegate archiverWillFinish:self];
00198
00199 var i = 0,
00200 topObject = _plistObject,
00201 classes = [];
00202
00203 for (; i < _objects.length; ++i)
00204 {
00205 var object = _objects[i],
00206 theClass = [object classForKeyedArchiver];
00207
00208
00209
00210
00211 _plistObject = _plistObjects[[_UIDs objectForKey:[object UID]]];
00212 [object encodeWithCoder:self];
00213
00214 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidEncodeObjectSelector)
00215 [_delegate archiver:self didEncodeObject:object];
00216 }
00217
00218 _plistObject = [CPDictionary dictionary];
00219
00220 [_plistObject setObject:topObject forKey:_CPKeyedArchiverTopKey];
00221 [_plistObject setObject:_plistObjects forKey:_CPKeyedArchiverObjectsKey];
00222 [_plistObject setObject:[self className] forKey:_CPKeyedArchiverArchiverKey];
00223 [_plistObject setObject:@"100000" forKey:_CPKeyedArchiverVersionKey];
00224
00225 [_data setPlistObject:_plistObject];
00226
00227 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishSelector)
00228 [_delegate archiverDidFinish:self];
00229 }
00230
00234 - (CPPropertyListFormat)outputFormat
00235 {
00236 return _outputFormat;
00237 }
00238
00243 - (void)setOutputFormat:(CPPropertyListFormat)aPropertyListFormat
00244 {
00245 _outputFormat = aPropertyListFormat;
00246 }
00247
00253 - (void)encodeBool:(BOOL)aBOOL forKey:(CPString)aKey
00254 {
00255 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aBOOL, NO) forKey:aKey];
00256 }
00257
00263 - (void)encodeDouble:(double)aDouble forKey:(CPString)aKey
00264 {
00265 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aDouble, NO) forKey:aKey];
00266 }
00267
00273 - (void)encodeFloat:(float)aFloat forKey:(CPString)aKey
00274 {
00275 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aFloat, NO) forKey:aKey];
00276 }
00277
00283 - (void)encodeInt:(float)anInt forKey:(CPString)aKey
00284 {
00285 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anInt, NO) forKey:aKey];
00286 }
00287
00288
00292 - (void)setDelegate:(id)aDelegate
00293 {
00294 _delegate = aDelegate;
00295
00296 if ([_delegate respondsToSelector:@selector(archiver:didEncodeObject:)])
00297 _delegateSelectors |= _CPKeyedArchiverDidEncodeObjectSelector;
00298
00299 if ([_delegate respondsToSelector:@selector(archiver:willEncodeObject:)])
00300 _delegateSelectors |= _CPKeyedArchiverWillEncodeObjectSelector;
00301
00302 if ([_delegate respondsToSelector:@selector(archiver:willReplaceObject:withObject:)])
00303 _delegateSelectors |= _CPKeyedArchiverWillReplaceObjectWithObjectSelector;
00304
00305 if ([_delegate respondsToSelector:@selector(archiver:didFinishEncoding:)])
00306 _delegateSelectors |= _CPKeyedArchiverDidFinishEncodingSelector;
00307
00308 if ([_delegate respondsToSelector:@selector(archiver:willFinishEncoding:)])
00309 _delegateSelectors |= _CPKeyedArchiverWillFinishEncodingSelector;
00310
00311 }
00312
00316 - (id)delegate
00317 {
00318 return _delegate;
00319 }
00320
00326 - (void)encodePoint:(CGPoint)aPoint forKey:(CPString)aKey
00327 {
00328 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CPStringFromPoint(aPoint), NO) forKey:aKey];
00329 }
00330
00336 - (void)encodeRect:(CGRect)aRect forKey:(CPString)aKey
00337 {
00338 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CPStringFromRect(aRect), NO) forKey:aKey];
00339 }
00340
00346 - (void)encodeSize:(CGSize)aSize forKey:(CPString)aKey
00347 {
00348 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CPStringFromSize(aSize), NO) forKey:aKey];
00349 }
00350
00358 - (void)encodeConditionalObject:(id)anObject forKey:(CPString)aKey
00359 {
00360 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, YES) forKey:aKey];
00361 }
00362
00368 - (void)encodeNumber:(CPNumber)aNumber forKey:(CPString)aKey
00369 {
00370 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aNumber, NO) forKey:aKey];
00371 }
00372
00378 - (void)encodeObject:(id)anObject forKey:(CPString)aKey
00379 {
00380 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, NO) forKey:aKey];
00381 }
00382
00383
00384 - (void)_encodeArrayOfObjects:(CPArray)objects forKey:(CPString)aKey
00385 {
00386 var i = 0,
00387 count = objects.length,
00388 references = [CPArray arrayWithCapacity:count];
00389
00390 for (; i < count; ++i)
00391 [references addObject:_CPKeyedArchiverEncodeObject(self, objects[i], NO)];
00392
00393 [_plistObject setObject:references forKey:aKey];
00394 }
00395
00396
00397 - (void)_encodeDictionaryOfObjects:(CPDictionary)aDictionary forKey:(CPString)aKey
00398 {
00399 var key,
00400 keys = [aDictionary keyEnumerator],
00401 references = [CPDictionary dictionary];
00402
00403 while (key = [keys nextObject])
00404 [references setObject:_CPKeyedArchiverEncodeObject(self, [aDictionary objectForKey:key], NO) forKey:key];
00405
00406 [_plistObject setObject:references forKey:aKey];
00407 }
00408
00409
00417 + (void)setClassName:(CPString)aClassName forClass:(Class)aClass
00418 {
00419 if (!CPArchiverReplacementClassNames)
00420 CPArchiverReplacementClassNames = [CPDictionary dictionary];
00421
00422 [CPArchiverReplacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)];
00423 }
00424
00432 + (CPString)classNameForClass:(Class)aClass
00433 {
00434 if (!CPArchiverReplacementClassNames)
00435 return aClass.name;
00436
00437 var className = [CPArchiverReplacementClassNames objectForKey:CPStringFromClass(aClassName)];
00438
00439 return className ? className : aClass.name;
00440 }
00441
00449 - (void)setClassName:(CPString)aClassName forClass:(Class)aClass
00450 {
00451 if (!_replacementClassNames)
00452 _replacementClassNames = [CPDictionary dictionary];
00453
00454 [_replacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)];
00455 }
00456
00462 - (CPString)classNameForClass:(Class)aClass
00463 {
00464 if (!_replacementClassNames)
00465 return aClass.name;
00466
00467 var className = [_replacementClassNames objectForKey:CPStringFromClass(aClassName)];
00468
00469 return className ? className : aClass.name;
00470 }
00471
00472 @end
00473
00474 var _CPKeyedArchiverEncodeObject = function(self, anObject, isConditional)
00475 {
00476
00477
00478
00479 if (anObject !== nil && !anObject.isa)
00480 anObject = [_CPKeyedArchiverValue valueWithJSObject:anObject];
00481
00482
00483 var GUID = [anObject UID],
00484 object = [self._replacementObjects objectForKey:GUID];
00485
00486
00487
00488 if (object === nil)
00489 {
00490 object = [anObject replacementObjectForKeyedArchiver:self];
00491
00492
00493 if (self._delegate)
00494 {
00495 if (object !== anObject && self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector)
00496 [self._delegate archiver:self willReplaceObject:anObject withObject:object];
00497
00498 if (self._delegateSelectors & _CPKeyedArchiverWillEncodeObjectSelector)
00499 {
00500 anObject = [self._delegate archiver:self willEncodeObject:object];
00501
00502 if (anObject !== object && self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector)
00503 [self._delegate archiver:self willReplaceObject:object withObject:anObject];
00504
00505 object = anObject;
00506 }
00507 }
00508
00509 [self._replacementObjects setObject:object forKey:GUID];
00510 }
00511
00512
00513
00514
00515 if (object === nil)
00516 return _CPKeyedArchiverNullReference;
00517
00518
00519 var UID = [self._UIDs objectForKey:GUID = [object UID]];
00520
00521
00522
00523
00524 if (UID === nil)
00525 {
00526
00527 if (isConditional)
00528 {
00529
00530 if ((UID = [self._conditionalUIDs objectForKey:GUID]) === nil)
00531 {
00532
00533 [self._conditionalUIDs setObject:UID = [self._plistObjects count] forKey:GUID];
00534 [self._plistObjects addObject:_CPKeyedArchiverNullString];
00535 }
00536 }
00537 else
00538 {
00539 var theClass = [object classForKeyedArchiver],
00540 plistObject = nil;
00541
00542 if ((theClass === _CPKeyedArchiverStringClass) || (theClass === _CPKeyedArchiverNumberClass))
00543 plistObject = object;
00544 else
00545 {
00546
00547 plistObject = [CPDictionary dictionary];
00548
00549 [self._objects addObject:object];
00550
00551 var className = [self classNameForClass:theClass];
00552
00553 if (!className)
00554 className = [[self class] classNameForClass:theClass];
00555
00556 if (!className)
00557 className = theClass.name;
00558 else
00559 theClass = CPClassFromString(className);
00560
00561 var classUID = [self._UIDs objectForKey:className];
00562
00563 if (!classUID)
00564 {
00565 var plistClass = [CPDictionary dictionary],
00566 hierarchy = [];
00567
00568 [plistClass setObject:className forKey:_CPKeyedArchiverClassNameKey];
00569
00570 do
00571 {
00572 [hierarchy addObject:CPStringFromClass(theClass)];
00573 } while (theClass = [theClass superclass]);
00574
00575 [plistClass setObject:hierarchy forKey:_CPKeyedArchiverClassesKey];
00576
00577 classUID = [self._plistObjects count];
00578 [self._plistObjects addObject:plistClass];
00579 [self._UIDs setObject:classUID forKey:className];
00580 }
00581
00582 [plistObject setObject:[CPDictionary dictionaryWithObject:classUID forKey:_CPKeyedArchiverUIDKey] forKey:_CPKeyedArchiverClassKey];
00583 }
00584
00585 UID = [self._conditionalUIDs objectForKey:GUID];
00586
00587
00588 if (UID !== nil)
00589 {
00590 [self._UIDs setObject:UID forKey:GUID];
00591 [self._plistObjects replaceObjectAtIndex:UID withObject:plistObject];
00592 }
00593 else
00594 {
00595 [self._UIDs setObject:UID = [self._plistObjects count] forKey:GUID];
00596 [self._plistObjects addObject:plistObject];
00597 }
00598 }
00599 }
00600
00601 return [CPDictionary dictionaryWithObject:UID forKey:_CPKeyedArchiverUIDKey];
00602 }