26 var _CPKeyedArchiverDidEncodeObjectSelector = 1,
27 _CPKeyedArchiverWillEncodeObjectSelector = 2,
28 _CPKeyedArchiverWillReplaceObjectWithObjectSelector = 4,
29 _CPKeyedArchiverDidFinishEncodingSelector = 8,
30 _CPKeyedArchiverWillFinishEncodingSelector = 16;
32 var _CPKeyedArchiverNullString =
"$null",
33 _CPKeyedArchiverNullReference = nil,
35 _CPKeyedArchiverUIDKey =
"CP$UID",
37 _CPKeyedArchiverTopKey =
"$top",
38 _CPKeyedArchiverObjectsKey =
"$objects",
39 _CPKeyedArchiverArchiverKey =
"$archiver",
40 _CPKeyedArchiverVersionKey =
"$version",
42 _CPKeyedArchiverClassNameKey =
"$classname",
43 _CPKeyedArchiverClassesKey =
"$classes",
44 _CPKeyedArchiverClassKey =
"$class";
46 var _CPKeyedArchiverStringClass = Nil,
47 _CPKeyedArchiverNumberClass = Nil;
50 @implementation _CPKeyedArchiverValue :
CPValue
99 unsigned _delegateSelectors;
114 CPPropertyListFormat _outputFormat;
125 _CPKeyedArchiverStringClass = [
CPString class];
126 _CPKeyedArchiverNumberClass = [
CPNumber class];
128 _CPKeyedArchiverNullReference = @{ _CPKeyedArchiverUIDKey: 0 };
131 + (BOOL)allowsKeyedCoding
141 + (
CPData)archivedDataWithRootObject:(
id)anObject
144 archiver = [[
self alloc] initForWritingWithMutableData:data];
146 [archiver encodeObject:anObject forKey:@"root"];
147 [archiver finishEncoding];
158 - (id)initForWritingWithMutableData:(CPMutableData)data
169 _conditionalUIDs = @{};
171 _replacementObjects = @{};
174 _plistObjects = [CPArray arrayWithObject:_CPKeyedArchiverNullString];
185 - (void)finishEncoding
187 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishEncodingSelector)
188 [_delegate archiverWillFinish:self];
191 topObject = _plistObject,
194 for (; i < _objects.length; ++i)
196 var
object = _objects[i];
201 _plistObject = _plistObjects[[_UIDs objectForKey:[object UID]]];
202 [object encodeWithCoder:self];
204 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidEncodeObjectSelector)
205 [_delegate archiver:self didEncodeObject:object];
210 [_plistObject setObject:topObject forKey:_CPKeyedArchiverTopKey];
211 [_plistObject setObject:_plistObjects forKey:_CPKeyedArchiverObjectsKey];
212 [_plistObject setObject:[
self className] forKey:_CPKeyedArchiverArchiverKey];
213 [_plistObject setObject:@"100000" forKey:_CPKeyedArchiverVersionKey];
215 [_data setPlistObject:_plistObject];
217 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishEncodingSelector)
218 [_delegate archiverDidFinish:self];
224 - (CPPropertyListFormat)outputFormat
226 return _outputFormat;
233 - (void)setOutputFormat:(CPPropertyListFormat)aPropertyListFormat
235 _outputFormat = aPropertyListFormat;
243 - (void)encodeBool:(BOOL)aBOOL forKey:(
CPString)aKey
245 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aBOOL, NO) forKey:aKey];
253 - (void)encodeDouble:(
double)aDouble forKey:(
CPString)aKey
255 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aDouble, NO) forKey:aKey];
263 - (void)encodeFloat:(
float)aFloat forKey:(
CPString)aKey
265 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aFloat, NO) forKey:aKey];
273 - (void)encodeInt:(
float)anInt forKey:(
CPString)aKey
275 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anInt, NO) forKey:aKey];
282 - (void)setDelegate:(
id)aDelegate
284 _delegate = aDelegate;
286 if ([_delegate respondsToSelector:
@selector(archiver:didEncodeObject:)])
287 _delegateSelectors |= _CPKeyedArchiverDidEncodeObjectSelector;
289 if ([_delegate respondsToSelector:
@selector(archiver:willEncodeObject:)])
290 _delegateSelectors |= _CPKeyedArchiverWillEncodeObjectSelector;
292 if ([_delegate respondsToSelector:
@selector(archiver:willReplaceObject:withObject:)])
293 _delegateSelectors |= _CPKeyedArchiverWillReplaceObjectWithObjectSelector;
295 if ([_delegate respondsToSelector:
@selector(archiver:didFinishEncoding:)])
296 _delegateSelectors |= _CPKeyedArchiverDidFinishEncodingSelector;
298 if ([_delegate respondsToSelector:
@selector(archiver:willFinishEncoding:)])
299 _delegateSelectors |= _CPKeyedArchiverWillFinishEncodingSelector;
316 - (void)encodePoint:(CGPoint)aPoint forKey:(
CPString)aKey
318 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CGStringFromPoint(aPoint), NO) forKey:aKey];
326 - (void)encodeRect:(CGRect)aRect forKey:(
CPString)aKey
328 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CGStringFromRect(aRect), NO) forKey:aKey];
336 - (void)encodeSize:(CGSize)aSize forKey:(
CPString)aKey
338 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CGStringFromSize(aSize), NO) forKey:aKey];
348 - (void)encodeConditionalObject:(
id)anObject forKey:(
CPString)aKey
350 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, YES) forKey:aKey];
360 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aNumber, NO) forKey:aKey];
368 - (void)encodeObject:(
id)anObject forKey:(
CPString)aKey
370 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, NO) forKey:aKey];
374 - (void)_encodeArrayOfObjects:(CPArray)objects forKey:(
CPString)aKey
377 count = objects.length,
380 for (; i < count; ++i)
381 [references addObject:_CPKeyedArchiverEncodeObject(self, objects[i], NO)];
383 [_plistObject setObject:references forKey:aKey];
393 while ((key = [keys nextObject]) !== nil)
394 [references setObject:_CPKeyedArchiverEncodeObject(
self, [aDictionary objectForKey:key], NO) forKey:key];
396 [_plistObject setObject:references forKey:aKey];
407 + (void)setClassName:(
CPString)aClassName forClass:(Class)aClass
412 [CPArchiverReplacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)];
429 return className ? className : aClass.name;
439 - (void)setClassName:(
CPString)aClassName forClass:(Class)aClass
441 if (!_replacementClassNames)
442 _replacementClassNames = @{};
444 [_replacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)];
452 - (
CPString)classNameForClass:(Class)aClass
454 if (!_replacementClassNames)
459 return className ? className : aClass.name;
464 var _CPKeyedArchiverEncodeObject =
function(
self, anObject, isConditional)
469 if (anObject !== nil && anObject !== undefined && !anObject.isa)
470 anObject = [_CPKeyedArchiverValue valueWithJSObject:anObject];
473 var GUID = [anObject UID],
474 object = [
self._replacementObjects objectForKey:GUID];
480 object = [anObject replacementObjectForKeyedArchiver:self];
485 if (
object !== anObject &&
self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector)
486 [
self._delegate archiver:self willReplaceObject:anObject withObject:object];
488 if (
self._delegateSelectors & _CPKeyedArchiverWillEncodeObjectSelector)
490 anObject = [
self._delegate archiver:self willEncodeObject:object];
492 if (anObject !==
object &&
self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector)
493 [
self._delegate archiver:self willReplaceObject:object withObject:anObject];
499 if (
object != nil && GUID != nil)
500 [
self._replacementObjects setObject:object forKey:GUID];
507 return _CPKeyedArchiverNullReference;
510 var UID = [
self._UIDs objectForKey:GUID = [object UID]];
521 if ((UID = [
self._conditionalUIDs objectForKey:GUID]) === nil)
524 [
self._conditionalUIDs setObject:UID = [
self._plistObjects count] forKey:GUID];
525 [
self._plistObjects addObject:_CPKeyedArchiverNullString];
530 var theClass = [object classForKeyedArchiver],
533 if ((theClass === _CPKeyedArchiverStringClass) || (theClass === _CPKeyedArchiverNumberClass))
534 plistObject = object;
540 [
self._objects addObject:object];
542 var className = [
self classNameForClass:theClass];
545 className = [[
self class] classNameForClass:theClass];
548 className = theClass.name;
552 var classUID = [
self._UIDs objectForKey:className];
556 var plistClass = @{},
559 [plistClass setObject:className forKey:_CPKeyedArchiverClassNameKey];
563 [hierarchy addObject:CPStringFromClass(theClass)];
564 }
while (theClass = [theClass superclass]);
566 [plistClass setObject:hierarchy forKey:_CPKeyedArchiverClassesKey];
568 classUID = [
self._plistObjects count];
569 [
self._plistObjects addObject:plistClass];
570 [
self._UIDs setObject:classUID forKey:className];
573 [plistObject setObject:@{ _CPKeyedArchiverUIDKey: classUID } forKey:_CPKeyedArchiverClassKey];
576 UID = [
self._conditionalUIDs objectForKey:GUID];
581 [
self._UIDs setObject:UID forKey:GUID];
582 [
self._plistObjects replaceObjectAtIndex:UID withObject:plistObject];
586 [
self._UIDs setObject:UID = [
self._plistObjects count] forKey:GUID];
587 [
self._plistObjects addObject:plistObject];
592 return @{ _CPKeyedArchiverUIDKey: UID };