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 98 unsigned _delegateSelectors;
113 CPPropertyListFormat _outputFormat;
127 _CPKeyedArchiverNullReference = @{ _CPKeyedArchiverUIDKey: 0 };
130 + (BOOL)allowsKeyedCoding
140 + (
CPData)archivedDataWithRootObject:(
id)anObject
145 [archiver encodeObject:anObject forKey:@"root"];
146 [archiver finishEncoding];
157 - (id)initForWritingWithMutableData:(CPMutableData)data
168 _conditionalUIDs = @{};
170 _replacementObjects = @{};
173 _plistObjects = [CPArray arrayWithObject:_CPKeyedArchiverNullString];
184 - (void)finishEncoding
186 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishEncodingSelector)
187 [_delegate archiverWillFinish:self];
190 topObject = _plistObject,
193 for (; i < _objects.length; ++i)
195 var
object = _objects[i];
200 _plistObject = _plistObjects[[_UIDs objectForKey:[object UID]]];
201 [object encodeWithCoder:self];
203 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidEncodeObjectSelector)
204 [_delegate archiver:self didEncodeObject:object];
209 [_plistObject setObject:topObject forKey:_CPKeyedArchiverTopKey];
210 [_plistObject setObject:_plistObjects forKey:_CPKeyedArchiverObjectsKey];
211 [_plistObject setObject:[
self className] forKey:_CPKeyedArchiverArchiverKey];
212 [_plistObject setObject:@"100000" forKey:_CPKeyedArchiverVersionKey];
214 [_data setPlistObject:_plistObject];
216 if (_delegate && _delegateSelectors & _CPKeyedArchiverDidFinishEncodingSelector)
217 [_delegate archiverDidFinish:self];
223 - (CPPropertyListFormat)outputFormat
225 return _outputFormat;
232 - (void)setOutputFormat:(CPPropertyListFormat)aPropertyListFormat
234 _outputFormat = aPropertyListFormat;
242 - (void)encodeBool:(BOOL)aBOOL forKey:(
CPString)aKey
244 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aBOOL, NO) forKey:aKey];
252 - (void)encodeDouble:(
double)aDouble forKey:(
CPString)aKey
254 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aDouble, NO) forKey:aKey];
262 - (void)encodeFloat:(
float)aFloat forKey:(
CPString)aKey
264 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aFloat, NO) forKey:aKey];
272 - (void)encodeInt:(
float)anInt forKey:(
CPString)aKey
274 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anInt, NO) forKey:aKey];
281 - (void)setDelegate:(
id)aDelegate
283 _delegate = aDelegate;
285 if ([_delegate respondsToSelector:
@selector(archiver:didEncodeObject:)])
286 _delegateSelectors |= _CPKeyedArchiverDidEncodeObjectSelector;
288 if ([_delegate respondsToSelector:
@selector(archiver:willEncodeObject:)])
289 _delegateSelectors |= _CPKeyedArchiverWillEncodeObjectSelector;
291 if ([_delegate respondsToSelector:
@selector(archiver:willReplaceObject:withObject:)])
292 _delegateSelectors |= _CPKeyedArchiverWillReplaceObjectWithObjectSelector;
294 if ([_delegate respondsToSelector:
@selector(archiver:didFinishEncoding:)])
295 _delegateSelectors |= _CPKeyedArchiverDidFinishEncodingSelector;
297 if ([_delegate respondsToSelector:
@selector(archiver:willFinishEncoding:)])
298 _delegateSelectors |= _CPKeyedArchiverWillFinishEncodingSelector;
315 - (void)encodePoint:(CGPoint)aPoint forKey:(
CPString)aKey
317 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CGStringFromPoint(aPoint), NO) forKey:aKey];
325 - (void)encodeRect:(CGRect)aRect forKey:(
CPString)aKey
327 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CGStringFromRect(aRect), NO) forKey:aKey];
335 - (void)encodeSize:(CGSize)aSize forKey:(
CPString)aKey
337 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, CGStringFromSize(aSize), NO) forKey:aKey];
347 - (void)encodeConditionalObject:(
id)anObject forKey:(
CPString)aKey
349 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, YES) forKey:aKey];
359 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, aNumber, NO) forKey:aKey];
367 - (void)encodeObject:(
id)anObject forKey:(
CPString)aKey
369 [_plistObject setObject:_CPKeyedArchiverEncodeObject(self, anObject, NO) forKey:aKey];
373 - (void)_encodeArrayOfObjects:(CPArray)objects forKey:(
CPString)aKey
375 var references = [objects arrayByApplyingBlock:function(object)
377 return _CPKeyedArchiverEncodeObject(self, object, NO);
380 [_plistObject setObject:references forKey:aKey];
387 keys = [aDictionary keyEnumerator],
390 while ((key = [keys nextObject]) !== nil)
391 [references setObject:_CPKeyedArchiverEncodeObject(
self, [aDictionary objectForKey:key], NO) forKey:key];
393 [_plistObject setObject:references forKey:aKey];
404 + (void)setClassName:(
CPString)aClassName forClass:(Class)aClass
409 [CPArchiverReplacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)];
424 var className = [CPArchiverReplacementClassNames objectForKey:CPStringFromClass(aClass)];
426 return className ? className : aClass.name;
436 - (void)setClassName:(
CPString)aClassName forClass:(Class)aClass
438 if (!_replacementClassNames)
439 _replacementClassNames = @{};
441 [_replacementClassNames setObject:aClassName forKey:CPStringFromClass(aClass)];
449 - (
CPString)classNameForClass:(Class)aClass
451 if (!_replacementClassNames)
454 var className = [_replacementClassNames objectForKey:CPStringFromClass(aClass)];
456 return className ? className : aClass.name;
461 var _CPKeyedArchiverEncodeObject =
function(
self, anObject, isConditional)
466 if (anObject !== nil && anObject !== undefined && !anObject.isa)
467 anObject = [_CPKeyedArchiverValue valueWithJSObject:anObject];
470 var GUID = [anObject UID],
471 object = [
self._replacementObjects objectForKey:GUID];
477 object = [anObject replacementObjectForKeyedArchiver:self];
482 if (
object !== anObject &&
self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector)
483 [
self._delegate archiver:self willReplaceObject:anObject withObject:object];
485 if (
self._delegateSelectors & _CPKeyedArchiverWillEncodeObjectSelector)
487 anObject = [
self._delegate archiver:self willEncodeObject:object];
489 if (anObject !==
object &&
self._delegateSelectors & _CPKeyedArchiverWillReplaceObjectWithObjectSelector)
490 [
self._delegate archiver:self willReplaceObject:object withObject:anObject];
496 if (
object != nil && GUID != nil)
497 [
self._replacementObjects setObject:object forKey:GUID];
504 return _CPKeyedArchiverNullReference;
507 var UID = [
self._UIDs objectForKey:GUID = [object UID]];
518 if ((UID = [
self._conditionalUIDs objectForKey:GUID]) === nil)
521 [
self._conditionalUIDs setObject:UID = [
self._plistObjects count] forKey:GUID];
522 [
self._plistObjects addObject:_CPKeyedArchiverNullString];
527 var theClass = [object classForKeyedArchiver],
530 if ((theClass === _CPKeyedArchiverStringClass) || (theClass === _CPKeyedArchiverNumberClass))
531 plistObject = object;
537 [
self._objects addObject:object];
542 className = [[
self class] classNameForClass:theClass];
545 className = theClass.name;
549 var classUID = [
self._UIDs objectForKey:className];
553 var plistClass = @{},
556 [plistClass setObject:className forKey:_CPKeyedArchiverClassNameKey];
560 [hierarchy addObject:CPStringFromClass(theClass)];
561 }
while (theClass = [theClass superclass]);
563 [plistClass setObject:hierarchy forKey:_CPKeyedArchiverClassesKey];
565 classUID = [
self._plistObjects count];
566 [
self._plistObjects addObject:plistClass];
567 [
self._UIDs setObject:classUID forKey:className];
570 [plistObject setObject:@{ _CPKeyedArchiverUIDKey: classUID } forKey:_CPKeyedArchiverClassKey];
573 UID = [
self._conditionalUIDs objectForKey:GUID];
578 [
self._UIDs setObject:UID forKey:GUID];
579 [
self._plistObjects replaceObjectAtIndex:UID withObject:plistObject];
583 [
self._UIDs setObject:UID = [
self._plistObjects count] forKey:GUID];
584 [
self._plistObjects addObject:plistObject];
589 return @{ _CPKeyedArchiverUIDKey: UID };
id initForWritingWithMutableData:(CPMutableData data)
A Cappuccino wrapper for any data type.
A mutable key-value pair collection.
A generic "value". Can be subclassed to hold specific data types.
Implements keyed archiving of object graphs (e.g. for storing data).
An immutable string (collection of characters).
Defines methods for use when archiving & restoring (enc/decoding).
CPString classNameForClass:(Class aClass)
var CPArchiverReplacementClassNames
A bridged object to native Javascript numbers.
CPData dataWithPlistObject:(id aPlistObject)
function CPClassFromString(aClassName)