2004-02-02 12:26:59 +00:00
|
|
|
/** Implementation for NSKeyedUnarchiver for GNUstep
|
2004-01-22 09:37:07 +00:00
|
|
|
Copyright (C) 2004 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
|
|
|
Date: January 2004
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2004-01-22 09:37:07 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2019-12-09 23:36:00 +00:00
|
|
|
Lesser General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2004-01-22 09:37:07 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2024-11-07 13:37:59 +00:00
|
|
|
Software Foundation, Inc., 31 Milk Street #960789 Boston, MA 02196 USA.
|
2004-01-22 09:37:07 +00:00
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
*/
|
2004-01-22 09:37:07 +00:00
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
#import "common.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
#define EXPOSE_NSKeyedUnarchiver_IVARS 1
|
2007-11-29 20:53:26 +00:00
|
|
|
#import "Foundation/NSAutoreleasePool.h"
|
|
|
|
#import "Foundation/NSData.h"
|
|
|
|
#import "Foundation/NSDictionary.h"
|
|
|
|
#import "Foundation/NSException.h"
|
|
|
|
#import "Foundation/NSMapTable.h"
|
|
|
|
#import "Foundation/NSNull.h"
|
|
|
|
#import "Foundation/NSValue.h"
|
|
|
|
|
|
|
|
#import "GSPrivate.h"
|
2004-01-25 18:39:20 +00:00
|
|
|
|
2004-01-22 20:38:24 +00:00
|
|
|
/*
|
|
|
|
* Setup for inline operation of arrays.
|
|
|
|
*/
|
2009-03-09 15:11:51 +00:00
|
|
|
#define GSI_ARRAY_RETAIN(A, X) [(X).obj retain]
|
|
|
|
#define GSI_ARRAY_RELEASE(A, X) [(X).obj release]
|
2004-02-07 06:30:52 +00:00
|
|
|
#define GSI_ARRAY_TYPES GSUNION_OBJ
|
2004-01-22 20:38:24 +00:00
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
|
2004-04-06 10:45:22 +00:00
|
|
|
#include "GNUstepBase/GSIArray.h"
|
2004-01-22 09:37:07 +00:00
|
|
|
|
|
|
|
#define _IN_NSKEYEDUNARCHIVER_M 1
|
2010-02-17 11:47:06 +00:00
|
|
|
#import "Foundation/NSKeyedArchiver.h"
|
2004-01-22 09:37:07 +00:00
|
|
|
#undef _IN_NSKEYEDUNARCHIVER_M
|
|
|
|
|
2006-04-28 07:43:09 +00:00
|
|
|
@interface NilMarker: NSObject
|
|
|
|
@end
|
|
|
|
@implementation NilMarker
|
|
|
|
@end
|
|
|
|
|
2009-03-16 10:54:59 +00:00
|
|
|
static NSMapTable *globalClassMap = 0;
|
2004-01-22 20:38:24 +00:00
|
|
|
|
|
|
|
#define GETVAL \
|
|
|
|
id o; \
|
|
|
|
\
|
|
|
|
if ([aKey isKindOfClass: [NSString class]] == NO) \
|
|
|
|
{ \
|
|
|
|
[NSException raise: NSInvalidArgumentException \
|
|
|
|
format: @"%@, bad key '%@' in %@", \
|
|
|
|
NSStringFromClass([self class]), aKey, NSStringFromSelector(_cmd)]; \
|
|
|
|
} \
|
|
|
|
if ([aKey hasPrefix: @"$"] == YES) \
|
|
|
|
{ \
|
|
|
|
aKey = [@"$" stringByAppendingString: aKey]; \
|
|
|
|
} \
|
|
|
|
o = [_keyMap objectForKey: aKey];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@interface NSKeyedUnarchiver (Private)
|
|
|
|
- (id) _decodeObject: (unsigned)index;
|
|
|
|
@end
|
|
|
|
|
2004-01-27 11:31:41 +00:00
|
|
|
@implementation NSKeyedUnarchiver (Internal)
|
2004-01-25 18:39:20 +00:00
|
|
|
/**
|
|
|
|
* Internal method used to decode an array relatively efficiently.<br />
|
|
|
|
* Some MacOS-X library classes seem to use this.
|
|
|
|
*/
|
|
|
|
- (id) _decodeArrayOfObjectsForKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
id o = [_keyMap objectForKey: aKey];
|
|
|
|
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSArray class]] == YES)
|
|
|
|
{
|
|
|
|
unsigned c = [o count];
|
|
|
|
NSMutableArray *m = [NSMutableArray arrayWithCapacity: c];
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for (i = 0; i < c; i++)
|
|
|
|
{
|
|
|
|
unsigned ref;
|
|
|
|
id val;
|
|
|
|
|
|
|
|
ref = [[[o objectAtIndex: i] objectForKey: @"CF$UID"]
|
|
|
|
unsignedIntValue];
|
|
|
|
val = [self _decodeObject: ref];
|
|
|
|
if (val == nil)
|
|
|
|
{
|
|
|
|
[NSException raise:
|
|
|
|
NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: decoded nil in array",
|
|
|
|
NSStringFromClass([self class]),
|
|
|
|
NSStringFromSelector(_cmd)];
|
|
|
|
}
|
|
|
|
[m addObject: val];
|
|
|
|
}
|
|
|
|
o = m;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
o = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return o;
|
|
|
|
}
|
2004-01-28 07:33:20 +00:00
|
|
|
|
|
|
|
- (id) _decodePropertyListForKey: (NSString*)aKey
|
|
|
|
{
|
|
|
|
id o = [_keyMap objectForKey: aKey];
|
|
|
|
|
|
|
|
return o;
|
|
|
|
}
|
2013-05-13 20:55:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method is used to replace oldObj with newObj
|
|
|
|
* in the map that is maintained in NSKeyedUnarchiver.
|
|
|
|
*/
|
|
|
|
- (BOOL) replaceObject: (id)oldObj withObject: (id)newObj
|
|
|
|
{
|
|
|
|
unsigned int i = 0;
|
|
|
|
unsigned int count = GSIArrayCount(_objMap);
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
id obj = GSIArrayItemAtIndex(_objMap, i).obj;
|
|
|
|
if (obj == oldObj)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i < count)
|
|
|
|
{
|
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)newObj, i);
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NO;
|
|
|
|
}
|
2004-01-27 11:31:41 +00:00
|
|
|
@end
|
2004-01-25 18:39:20 +00:00
|
|
|
|
2004-01-27 11:31:41 +00:00
|
|
|
@implementation NSKeyedUnarchiver (Private)
|
2004-01-22 20:38:24 +00:00
|
|
|
- (id) _decodeObject: (unsigned)index
|
|
|
|
{
|
|
|
|
id o;
|
|
|
|
id obj;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the referenced object is already in _objMap
|
|
|
|
* we simply return it (the object at index 0 maps to nil)
|
|
|
|
*/
|
|
|
|
obj = GSIArrayItemAtIndex(_objMap, index).obj;
|
|
|
|
if (obj != nil)
|
|
|
|
{
|
|
|
|
if (obj == GSIArrayItemAtIndex(_objMap, 0).obj)
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No mapped object, so we decode from the property list
|
|
|
|
* in _objects
|
|
|
|
*/
|
|
|
|
obj = [_objects objectAtIndex: index];
|
|
|
|
if ([obj isKindOfClass: [NSDictionary class]] == YES)
|
|
|
|
{
|
|
|
|
NSString *classname;
|
|
|
|
NSArray *classes;
|
|
|
|
Class c;
|
|
|
|
id r;
|
|
|
|
NSDictionary *savedKeyMap;
|
|
|
|
unsigned savedCursor;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fetch the class information from the table.
|
|
|
|
*/
|
|
|
|
o = [obj objectForKey: @"$class"];
|
|
|
|
o = [o objectForKey: @"CF$UID"];
|
|
|
|
o = [_objects objectAtIndex: [o intValue]];
|
|
|
|
classname = [o objectForKey: @"$classname"];
|
|
|
|
classes = [o objectForKey: @"$classes"];
|
|
|
|
c = [self classForClassName: classname];
|
|
|
|
if (c == nil)
|
|
|
|
{
|
|
|
|
c = [[self class] classForClassName: classname];
|
|
|
|
if (c == nil)
|
|
|
|
{
|
|
|
|
c = NSClassFromString(classname);
|
|
|
|
if (c == nil)
|
|
|
|
{
|
|
|
|
c = [_delegate unarchiver: self
|
|
|
|
cannotDecodeObjectOfClassName: classname
|
|
|
|
originalClasses: classes];
|
|
|
|
if (c == nil)
|
|
|
|
{
|
|
|
|
[NSException raise:
|
|
|
|
NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: no class for name '%@'",
|
|
|
|
NSStringFromClass([self class]),
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
classname];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
savedCursor = _cursor;
|
|
|
|
savedKeyMap = _keyMap;
|
|
|
|
|
|
|
|
_cursor = 0; // Starting object decode
|
|
|
|
_keyMap = obj; // Dictionary describing object
|
|
|
|
|
|
|
|
o = [c allocWithZone: _zone]; // Create instance.
|
2004-02-07 06:30:52 +00:00
|
|
|
// Store object in map so that decoding of it can be self referential.
|
2004-01-28 06:21:33 +00:00
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)o, index);
|
2004-01-22 20:38:24 +00:00
|
|
|
r = [o initWithCoder: self];
|
|
|
|
if (r != o)
|
|
|
|
{
|
|
|
|
[_delegate unarchiver: self
|
|
|
|
willReplaceObject: o
|
|
|
|
withObject: r];
|
|
|
|
o = r;
|
2004-01-28 06:21:33 +00:00
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)o, index);
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
|
|
|
r = [o awakeAfterUsingCoder: self];
|
|
|
|
if (r != o)
|
|
|
|
{
|
|
|
|
[_delegate unarchiver: self
|
|
|
|
willReplaceObject: o
|
|
|
|
withObject: r];
|
|
|
|
o = r;
|
2004-01-28 06:21:33 +00:00
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)o, index);
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_delegate != nil)
|
|
|
|
{
|
|
|
|
r = [_delegate unarchiver: self didDecodeObject: o];
|
2024-06-19 14:28:48 +00:00
|
|
|
/* Apple documentation says that the delegate may return nil to
|
|
|
|
* indicate that the decoded objects should not be changed.
|
|
|
|
*/
|
|
|
|
if (r != nil && r != o)
|
2004-01-22 20:38:24 +00:00
|
|
|
{
|
|
|
|
[_delegate unarchiver: self
|
|
|
|
willReplaceObject: o
|
|
|
|
withObject: r];
|
2024-06-19 14:28:48 +00:00
|
|
|
o = RETAIN(r);
|
2004-01-28 06:21:33 +00:00
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)o, index);
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
2004-02-07 06:30:52 +00:00
|
|
|
RELEASE(o); // Retained in array
|
|
|
|
obj = o;
|
2004-01-22 20:38:24 +00:00
|
|
|
_keyMap = savedKeyMap;
|
|
|
|
_cursor = savedCursor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-02-07 06:30:52 +00:00
|
|
|
// Use the decoded object directly
|
2004-01-28 06:21:33 +00:00
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)obj, index);
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
|
|
|
|
2011-10-03 19:48:30 +00:00
|
|
|
if ((obj == nil) || [@"$null" isEqual: obj])
|
2004-02-07 06:30:52 +00:00
|
|
|
{
|
2006-04-28 07:43:09 +00:00
|
|
|
// Record NilMarker for decoded object.
|
2004-02-07 06:30:52 +00:00
|
|
|
o = GSIArrayItemAtIndex(_objMap, 0).obj;
|
|
|
|
GSIArraySetItemAtIndex(_objMap, (GSIArrayItem)o, index);
|
2011-10-03 19:48:30 +00:00
|
|
|
obj = nil;
|
2004-02-07 06:30:52 +00:00
|
|
|
}
|
|
|
|
|
2004-01-22 20:38:24 +00:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
@implementation NSKeyedUnarchiver
|
|
|
|
|
|
|
|
+ (Class) classForClassName: (NSString*)aString
|
|
|
|
{
|
|
|
|
return (Class)NSMapGet(globalClassMap, (void*)aString);
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (globalClassMap == 0)
|
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
globalClassMap =
|
2004-01-22 09:37:07 +00:00
|
|
|
NSCreateMapTable(NSObjectMapKeyCallBacks,
|
|
|
|
NSNonOwnedPointerMapValueCallBacks, 0);
|
2013-08-22 15:44:54 +00:00
|
|
|
[[NSObject leakAt: &globalClassMap] release];
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) setClass: (Class)aClass forClassName: (NSString*)aString
|
|
|
|
{
|
|
|
|
if (aClass == nil)
|
|
|
|
{
|
|
|
|
NSMapRemove(globalClassMap, (void*)aString);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSMapInsert(globalClassMap, (void*)aString, aClass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When I tried this on MacOS 10.3 it encoded the object with the key 'root',
|
|
|
|
* so this implementation does the same.
|
|
|
|
*/
|
|
|
|
+ (id) unarchiveObjectWithData: (NSData*)data
|
|
|
|
{
|
|
|
|
NSKeyedUnarchiver *u = nil;
|
|
|
|
id o = nil;
|
|
|
|
|
|
|
|
NS_DURING
|
|
|
|
{
|
|
|
|
u = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];
|
|
|
|
o = RETAIN([u decodeObjectForKey: @"root"]);
|
|
|
|
[u finishDecoding];
|
|
|
|
DESTROY(u);
|
|
|
|
}
|
|
|
|
NS_HANDLER
|
|
|
|
{
|
|
|
|
DESTROY(u);
|
2006-08-13 11:25:13 +00:00
|
|
|
DESTROY(o);
|
2004-01-22 09:37:07 +00:00
|
|
|
[localException raise];
|
|
|
|
}
|
|
|
|
NS_ENDHANDLER
|
|
|
|
return AUTORELEASE(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (id) unarchiveObjectWithFile: (NSString*)aPath
|
|
|
|
{
|
|
|
|
NSData *d;
|
|
|
|
id o;
|
|
|
|
|
|
|
|
d = [NSData dataWithContentsOfFile: aPath];
|
|
|
|
o = [self unarchiveObjectWithData: d];
|
2006-08-13 11:25:13 +00:00
|
|
|
return o;
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
|
2023-05-05 11:04:30 +00:00
|
|
|
+ (id) unarchivedObjectOfClass: (Class)cls
|
|
|
|
fromData: (NSData*)data
|
|
|
|
error: (NSError**)error
|
|
|
|
{
|
|
|
|
return [self unarchivedObjectOfClasses: [NSSet setWithObject:cls]
|
|
|
|
fromData: data
|
|
|
|
error: error];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (id) unarchivedObjectOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)classes
|
|
|
|
fromData: (NSData*)data
|
|
|
|
error: (NSError**)error
|
|
|
|
{
|
|
|
|
/* FIXME: implement proper secure coding support */
|
|
|
|
return [self unarchiveObjectWithData: data];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray*) unarchivedArrayOfObjectsOfClass: (Class)cls
|
|
|
|
fromData: (NSData*)data
|
|
|
|
error: (NSError**)error
|
|
|
|
{
|
|
|
|
return [self unarchivedArrayOfObjectsOfClasses: [NSSet setWithObject:cls]
|
|
|
|
fromData: data
|
|
|
|
error: error];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray*) unarchivedArrayOfObjectsOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)classes
|
|
|
|
fromData: (NSData*)data
|
|
|
|
error: (NSError**)error
|
|
|
|
{
|
|
|
|
/* FIXME: implement proper secure coding support */
|
|
|
|
return [self unarchiveObjectWithData: data];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSDictionary*) unarchivedDictionaryWithKeysOfClass: (Class)keyCls
|
|
|
|
objectsOfClass: (Class)valueCls
|
|
|
|
fromData: (NSData*)data
|
|
|
|
error: (NSError**)error
|
|
|
|
{
|
|
|
|
return [self unarchivedDictionaryWithKeysOfClasses: [NSSet setWithObject:keyCls]
|
|
|
|
objectsOfClasses: [NSSet setWithObject:valueCls]
|
|
|
|
fromData: data
|
|
|
|
error: error];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSDictionary*) unarchivedDictionaryWithKeysOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)keyClasses
|
|
|
|
objectsOfClasses: (GS_GENERIC_CLASS(NSSet,Class)*)valueClasses
|
|
|
|
fromData: (NSData*)data
|
|
|
|
error: (NSError**)error
|
|
|
|
{
|
|
|
|
/* FIXME: implement proper secure coding support */
|
|
|
|
return [self unarchiveObjectWithData: data];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-01-22 20:43:34 +00:00
|
|
|
- (BOOL) allowsKeyedCoding
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2017-06-24 20:35:23 +00:00
|
|
|
- (BOOL)requiresSecureCoding
|
|
|
|
{
|
2020-05-15 14:06:39 +00:00
|
|
|
return _requiresSecureCoding;
|
2017-06-24 20:35:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setRequiresSecureCoding: (BOOL)secure
|
|
|
|
{
|
2020-05-15 14:06:39 +00:00
|
|
|
_requiresSecureCoding = secure;
|
2017-06-24 20:35:23 +00:00
|
|
|
}
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
- (Class) classForClassName: (NSString*)aString
|
|
|
|
{
|
2010-03-12 09:14:39 +00:00
|
|
|
return _clsMap == 0 ? Nil : (Class)NSMapGet(_clsMap, (void*)aString);
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) containsValueForKey: (NSString*)aKey
|
|
|
|
{
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2004-01-22 20:38:24 +00:00
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
DESTROY(_archive);
|
|
|
|
if (_clsMap != 0)
|
|
|
|
{
|
|
|
|
NSFreeMapTable(_clsMap);
|
|
|
|
_clsMap = 0;
|
|
|
|
}
|
|
|
|
if (_objMap != 0)
|
|
|
|
{
|
|
|
|
NSZone *z = _objMap->zone;
|
|
|
|
|
2006-07-25 15:30:40 +00:00
|
|
|
GSIArrayEmpty(_objMap);
|
2004-01-22 20:38:24 +00:00
|
|
|
NSZoneFree(z, (void*)_objMap);
|
|
|
|
}
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2004-01-25 18:39:20 +00:00
|
|
|
- (void) decodeArrayOfObjCType: (const char*)type
|
2010-09-16 02:55:24 +00:00
|
|
|
count: (NSUInteger)expected
|
2004-01-25 18:39:20 +00:00
|
|
|
at: (void*)buf
|
|
|
|
{
|
2011-05-12 16:03:08 +00:00
|
|
|
id o = [self decodeObject];
|
|
|
|
NSUInteger size;
|
2004-01-25 18:39:20 +00:00
|
|
|
|
|
|
|
if ([o isKindOfClass: [_NSKeyedCoderOldStyleArray class]] == NO)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value is '%@'",
|
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), o];
|
|
|
|
}
|
|
|
|
if (strcmp([o type], type) != 0)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
2016-05-18 06:11:00 +00:00
|
|
|
format: @"[%@ +%@]: type mismatch for %@",
|
2004-01-25 18:39:20 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), o];
|
|
|
|
}
|
|
|
|
if ([o count] != expected)
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
2016-05-18 06:11:00 +00:00
|
|
|
format: @"[%@ +%@]: count mismatch for %@",
|
2004-01-25 18:39:20 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), o];
|
|
|
|
}
|
2021-11-02 09:17:53 +00:00
|
|
|
NSGetSizeAndAlignment(type, &size, NULL);
|
2011-05-12 16:03:08 +00:00
|
|
|
memcpy(buf, [o bytes], expected * size);
|
2004-01-25 18:39:20 +00:00
|
|
|
}
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
- (BOOL) decodeBoolForKey: (NSString*)aKey
|
|
|
|
{
|
2004-01-25 18:39:20 +00:00
|
|
|
NSString *oldKey = aKey;
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSNumber class]] == YES)
|
|
|
|
{
|
|
|
|
return [o boolValue];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
oldKey, o];
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (const uint8_t*) decodeBytesForKey: (NSString*)aKey
|
2009-02-23 20:42:32 +00:00
|
|
|
returnedLength: (NSUInteger*)length
|
2004-01-22 09:37:07 +00:00
|
|
|
{
|
2004-01-25 18:39:20 +00:00
|
|
|
NSString *oldKey = aKey;
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSData class]] == YES)
|
|
|
|
{
|
|
|
|
*length = [o length];
|
|
|
|
return [o bytes];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
oldKey, o];
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
*length = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (double) decodeDoubleForKey: (NSString*)aKey
|
|
|
|
{
|
2004-01-25 18:39:20 +00:00
|
|
|
NSString *oldKey = aKey;
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSNumber class]] == YES)
|
|
|
|
{
|
|
|
|
return [o doubleValue];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
oldKey, o];
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (float) decodeFloatForKey: (NSString*)aKey
|
|
|
|
{
|
2004-01-25 18:39:20 +00:00
|
|
|
NSString *oldKey = aKey;
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSNumber class]] == YES)
|
|
|
|
{
|
|
|
|
return [o floatValue];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
oldKey, o];
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) decodeIntForKey: (NSString*)aKey
|
|
|
|
{
|
2010-06-25 11:53:21 +00:00
|
|
|
int64_t i = [self decodeInt64ForKey: aKey];
|
|
|
|
|
|
|
|
#if (INT_MAX < INT64_MAX)
|
|
|
|
if (i > INT_MAX || i < INT_MIN)
|
2004-01-22 20:38:24 +00:00
|
|
|
{
|
2010-06-25 11:53:21 +00:00
|
|
|
[NSException raise: NSRangeException
|
2012-01-09 08:28:27 +00:00
|
|
|
format: @"[%@ +%@]: value %"PRIu64" for key(%@) is out of range",
|
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), i, aKey];
|
2010-06-25 11:53:21 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (int)i;
|
|
|
|
}
|
2004-01-22 20:38:24 +00:00
|
|
|
|
2010-09-16 02:55:24 +00:00
|
|
|
- (NSInteger) decodeIntegerForKey: (NSString*)aKey
|
2010-06-25 11:53:21 +00:00
|
|
|
{
|
|
|
|
int64_t i = [self decodeInt64ForKey: aKey];
|
|
|
|
|
2010-06-29 07:02:27 +00:00
|
|
|
/* Older Solaris systems define INTPTR_MAX incorrectly ... so we use the
|
|
|
|
* void pointer size we determined at configure time to decide whether
|
|
|
|
* we need to check for overflow.
|
|
|
|
*/
|
|
|
|
#if (GS_SIZEOF_VOIDP < 8)
|
|
|
|
if (i > INT32_MAX || i < INT32_MIN)
|
2010-06-25 11:53:21 +00:00
|
|
|
{
|
|
|
|
[NSException raise: NSRangeException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is out of range",
|
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), aKey];
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
2010-06-25 11:53:21 +00:00
|
|
|
#endif
|
|
|
|
return (NSInteger)i;
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int32_t) decodeInt32ForKey: (NSString*)aKey
|
|
|
|
{
|
2010-06-25 11:53:21 +00:00
|
|
|
int64_t i = [self decodeInt64ForKey: aKey];
|
2004-01-22 20:38:24 +00:00
|
|
|
|
2010-06-25 11:53:21 +00:00
|
|
|
if (i > INT32_MAX || i < INT32_MIN)
|
|
|
|
{
|
|
|
|
[NSException raise: NSRangeException
|
2012-01-09 08:28:27 +00:00
|
|
|
format: @"[%@ +%@]: value %"PRIu64" for key(%@) is out of range",
|
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), i, aKey];
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
2010-06-25 11:53:21 +00:00
|
|
|
return (int32_t)i;
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int64_t) decodeInt64ForKey: (NSString*)aKey
|
|
|
|
{
|
2004-01-25 18:39:20 +00:00
|
|
|
NSString *oldKey = aKey;
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSNumber class]] == YES)
|
|
|
|
{
|
|
|
|
long long l = [o longLongValue];
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
oldKey, o];
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-01-22 20:38:24 +00:00
|
|
|
- (id) decodeObject
|
|
|
|
{
|
|
|
|
NSString *key = [NSString stringWithFormat: @"$%d", _cursor++];
|
|
|
|
NSNumber *pos;
|
|
|
|
id o = [_keyMap objectForKey: key];
|
|
|
|
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
if ([o isKindOfClass: [NSDictionary class]] == YES
|
|
|
|
&& (pos = [o objectForKey: @"CF$UID"]) != nil)
|
|
|
|
{
|
|
|
|
int index = [pos intValue];
|
|
|
|
|
|
|
|
return [self _decodeObject: index];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
key, o];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
- (id) decodeObjectForKey: (NSString*)aKey
|
|
|
|
{
|
2004-01-25 18:39:20 +00:00
|
|
|
NSString *oldKey = aKey;
|
2004-01-22 20:38:24 +00:00
|
|
|
GETVAL
|
|
|
|
if (o != nil)
|
|
|
|
{
|
|
|
|
NSNumber *pos;
|
|
|
|
|
|
|
|
if ([o isKindOfClass: [NSDictionary class]] == YES
|
|
|
|
&& (pos = [o objectForKey: @"CF$UID"]) != nil)
|
|
|
|
{
|
|
|
|
int index = [pos intValue];
|
|
|
|
|
|
|
|
return [self _decodeObject: index];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSException raise: NSInvalidUnarchiveOperationException
|
|
|
|
format: @"[%@ +%@]: value for key(%@) is '%@'",
|
2005-02-22 11:22:44 +00:00
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd),
|
2004-01-22 20:38:24 +00:00
|
|
|
oldKey, o];
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2017-06-24 20:35:23 +00:00
|
|
|
- (id) decodeObjectOfClasses: (NSSet *)classes forKey: (NSString *)key
|
|
|
|
{
|
|
|
|
return [self decodeObjectForKey: key];
|
|
|
|
}
|
|
|
|
|
2004-01-24 06:39:21 +00:00
|
|
|
- (NSPoint) decodePoint
|
|
|
|
{
|
|
|
|
NSPoint p;
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &p.x];
|
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &p.y];
|
2004-01-24 06:39:21 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect) decodeRect
|
|
|
|
{
|
|
|
|
NSRect r;
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &r.origin.x];
|
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &r.origin.y];
|
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &r.size.width];
|
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &r.size.height];
|
2004-01-24 06:39:21 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSSize) decodeSize
|
|
|
|
{
|
|
|
|
NSSize s;
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &s.width];
|
|
|
|
[self decodeValueOfObjCType: @encode(CGFloat) at: &s.height];
|
2004-01-24 06:39:21 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2004-01-24 07:18:24 +00:00
|
|
|
- (void) decodeValueOfObjCType: (const char*)type
|
|
|
|
at: (void*)address
|
|
|
|
{
|
|
|
|
NSString *aKey;
|
|
|
|
id o;
|
|
|
|
|
|
|
|
if (*type == _C_ID || *type == _C_CLASS
|
|
|
|
|| *type == _C_SEL || *type == _C_CHARPTR)
|
|
|
|
{
|
|
|
|
o = [self decodeObject];
|
|
|
|
if (*type == _C_ID || *type == _C_CLASS)
|
|
|
|
{
|
|
|
|
*(id*)address = RETAIN(o);
|
|
|
|
}
|
|
|
|
else if (*type == _C_SEL)
|
|
|
|
{
|
|
|
|
*(SEL*)address = NSSelectorFromString(o);
|
|
|
|
}
|
|
|
|
else if (*type == _C_CHARPTR)
|
|
|
|
{
|
|
|
|
*(const char**)address = [o cString];
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aKey = [NSString stringWithFormat: @"$%u", _cursor++];
|
|
|
|
o = [_keyMap objectForKey: aKey];
|
|
|
|
|
|
|
|
switch (*type)
|
|
|
|
{
|
|
|
|
case _C_CHR:
|
|
|
|
*(char*)address = [o charValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_UCHR:
|
|
|
|
*(unsigned char*)address = [o unsignedCharValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_SHT:
|
|
|
|
*(short*)address = [o shortValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_USHT:
|
|
|
|
*(unsigned short*)address = [o unsignedShortValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_INT:
|
|
|
|
*(int*)address = [o intValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_UINT:
|
|
|
|
*(unsigned int*)address = [o unsignedIntValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_LNG:
|
|
|
|
*(long int*)address = [o longValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_ULNG:
|
|
|
|
*(unsigned long int*)address = [o unsignedLongValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_LNG_LNG:
|
|
|
|
*(long long int*)address = [o longLongValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_ULNG_LNG:
|
|
|
|
*(unsigned long long int*)address = [o unsignedLongLongValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_FLT:
|
|
|
|
*(float*)address = [o floatValue];
|
|
|
|
return;
|
|
|
|
|
|
|
|
case _C_DBL:
|
|
|
|
*(double*)address = [o doubleValue];
|
|
|
|
return;
|
|
|
|
|
2021-08-07 14:37:52 +00:00
|
|
|
#if defined(_C_BOOL) && (!defined(__GNUC__) || __GNUC__ > 2)
|
2015-09-22 09:46:10 +00:00
|
|
|
case _C_BOOL:
|
|
|
|
*(_Bool*)address = (_Bool)[o unsignedCharValue];
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2004-01-24 07:18:24 +00:00
|
|
|
case _C_STRUCT_B:
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"-[%@ %@]: this archiver cannote decode structs",
|
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
|
|
|
|
return;
|
|
|
|
|
2007-06-26 19:12:45 +00:00
|
|
|
case _C_ARY_B:
|
|
|
|
{
|
|
|
|
int count = atoi(++type);
|
|
|
|
|
|
|
|
while (isdigit(*type))
|
|
|
|
{
|
|
|
|
type++;
|
|
|
|
}
|
|
|
|
[self decodeArrayOfObjCType: type count: count at: address];
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
2004-01-24 07:18:24 +00:00
|
|
|
default:
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"-[%@ %@]: unknown type encoding ('%c')",
|
|
|
|
NSStringFromClass([self class]), NSStringFromSelector(_cmd), *type];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
- (id) delegate
|
|
|
|
{
|
|
|
|
return _delegate;
|
|
|
|
}
|
|
|
|
|
2010-03-08 21:44:38 +00:00
|
|
|
- (NSString*) description
|
|
|
|
{
|
|
|
|
if (_archive == nil)
|
|
|
|
{
|
|
|
|
// For consistency with OSX
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"method sent to uninitialised unarchiver"];
|
|
|
|
}
|
|
|
|
return [super description];
|
|
|
|
}
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
- (void) finishDecoding
|
|
|
|
{
|
2004-01-22 20:38:24 +00:00
|
|
|
[_delegate unarchiverWillFinish: self];
|
|
|
|
DESTROY(_archive);
|
|
|
|
[_delegate unarchiverDidFinish: self];
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
|
2007-06-26 19:12:45 +00:00
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
Class c = [self class];
|
2010-02-25 18:49:31 +00:00
|
|
|
DESTROY(self);
|
2007-06-26 19:12:45 +00:00
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
format: @"-[%@ init]: cannot use -init for initialisation",
|
|
|
|
NSStringFromClass(c)];
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2004-01-22 09:37:07 +00:00
|
|
|
- (id) initForReadingWithData: (NSData*)data
|
|
|
|
{
|
2004-01-22 20:38:24 +00:00
|
|
|
self = [super init];
|
|
|
|
if (self)
|
|
|
|
{
|
|
|
|
NSPropertyListFormat format;
|
|
|
|
NSString *error;
|
|
|
|
|
|
|
|
_zone = [self zone];
|
|
|
|
_archive = [NSPropertyListSerialization propertyListFromData: data
|
|
|
|
mutabilityOption: NSPropertyListImmutable
|
|
|
|
format: &format
|
|
|
|
errorDescription: &error];
|
|
|
|
if (_archive == nil)
|
|
|
|
{
|
|
|
|
DESTROY(self);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned count;
|
|
|
|
unsigned i;
|
|
|
|
|
2022-02-17 10:08:18 +00:00
|
|
|
IF_NO_ARC(RETAIN(_archive);)
|
2004-01-22 20:38:24 +00:00
|
|
|
_archiverClass = [_archive objectForKey: @"$archiver"];
|
|
|
|
_version = [_archive objectForKey: @"$version"];
|
|
|
|
|
|
|
|
_objects = [_archive objectForKey: @"$objects"];
|
|
|
|
_keyMap = [_archive objectForKey: @"$top"];
|
|
|
|
_objMap = NSZoneMalloc(_zone, sizeof(GSIArray_t));
|
|
|
|
count = [_objects count];
|
2008-10-31 23:12:05 +00:00
|
|
|
GSIArrayInitWithZoneAndCapacity(_objMap, _zone, count);
|
2004-01-22 20:38:24 +00:00
|
|
|
// Add marker for nil object
|
2006-04-28 07:43:09 +00:00
|
|
|
GSIArrayAddItem(_objMap, (GSIArrayItem)((id)[NilMarker class]));
|
2004-01-22 20:38:24 +00:00
|
|
|
// Add markers for unencoded objects.
|
|
|
|
for (i = 1; i < count; i++)
|
|
|
|
{
|
2021-11-11 15:56:23 +00:00
|
|
|
GSIArrayAddItem(_objMap, (GSIArrayItem)(id)nil);
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setClass: (Class)aClass forClassName: (NSString*)aString
|
|
|
|
{
|
2004-01-22 20:38:24 +00:00
|
|
|
if (aString == nil)
|
|
|
|
{
|
2010-03-12 09:14:39 +00:00
|
|
|
if (_clsMap != 0)
|
|
|
|
{
|
|
|
|
NSMapRemove(_clsMap, (void*)aString);
|
|
|
|
}
|
2004-01-22 20:38:24 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-12 09:14:39 +00:00
|
|
|
if (_clsMap == 0)
|
|
|
|
{
|
|
|
|
_clsMap = NSCreateMapTable(NSObjectMapKeyCallBacks,
|
|
|
|
NSNonOwnedPointerMapValueCallBacks, 0);
|
|
|
|
}
|
2004-01-22 20:38:24 +00:00
|
|
|
NSMapInsert(_clsMap, (void*)aString, (void*)aClass);
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setDelegate: (id)delegate
|
|
|
|
{
|
|
|
|
_delegate = delegate; // Not retained.
|
|
|
|
}
|
|
|
|
|
2008-12-08 09:08:05 +00:00
|
|
|
- (NSInteger) versionForClassName: (NSString*)className
|
|
|
|
{
|
|
|
|
return 0; // Not used for keyed unarchiving.
|
|
|
|
}
|
2004-01-22 09:37:07 +00:00
|
|
|
@end
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
@implementation NSObject (NSKeyedUnarchiverDelegate)
|
2005-11-28 15:41:35 +00:00
|
|
|
/** <override-dummy />
|
|
|
|
*/
|
2004-01-22 09:37:07 +00:00
|
|
|
- (Class) unarchiver: (NSKeyedUnarchiver*)anUnarchiver
|
|
|
|
cannotDecodeObjectOfClassName: (NSString*)aName
|
|
|
|
originalClasses: (NSArray*)classNames
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
/** <override-dummy />
|
|
|
|
*/
|
2004-01-22 09:37:07 +00:00
|
|
|
- (id) unarchiver: (NSKeyedUnarchiver*)anUnarchiver
|
|
|
|
didDecodeObject: (id)anObject
|
|
|
|
{
|
|
|
|
return anObject;
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
/** <override-dummy />
|
|
|
|
*/
|
2004-01-22 09:37:07 +00:00
|
|
|
- (void) unarchiverDidFinish: (NSKeyedUnarchiver*)anUnarchiver
|
|
|
|
{
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
/** <override-dummy />
|
|
|
|
*/
|
2004-01-22 09:37:07 +00:00
|
|
|
- (void) unarchiverWillFinish: (NSKeyedUnarchiver*)anUnarchiver
|
|
|
|
{
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
/** <override-dummy />
|
|
|
|
*/
|
2004-01-22 09:37:07 +00:00
|
|
|
- (void) unarchiver: (NSKeyedUnarchiver*)anUnarchiver
|
|
|
|
willReplaceObject: (id)anObject
|
|
|
|
withObject: (id)newObject
|
|
|
|
{
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
@implementation NSObject (NSKeyedUnarchiverObjectSubstitution)
|
2004-01-22 09:37:07 +00:00
|
|
|
+ (Class) classForKeyedUnarchiver
|
|
|
|
{
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|