Add a few OSX 10.6 methods for NSPropertyList.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@31692 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2010-11-29 22:54:28 +00:00
parent a9face8dc8
commit 850c2fb314
3 changed files with 232 additions and 113 deletions

View file

@ -1,3 +1,8 @@
2010-11-29 Fred Kiefer <FredKiefer@gmx.de>
* Headers/Foundation/NSPropertyList.h,
* Source/NSPropertyList.m: Add a few OSX 10.6 methods.
2010-11-28 Richard Frith-Macdonald <rfm@gnu.org> 2010-11-28 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/Unicode.m: Remove unnecessary include of Foundation.h * Source/Additions/Unicode.m: Remove unnecessary include of Foundation.h

View file

@ -37,7 +37,7 @@ extern "C" {
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST) #if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
@class NSData, NSString; @class NSData, NSString, NSInputStream, NSOutputStream;
enum { enum {
NSPropertyListImmutable = 0, NSPropertyListImmutable = 0,
@ -64,6 +64,12 @@ enum {
NSPropertyListGNUstepFormat = 1000, NSPropertyListGNUstepFormat = 1000,
NSPropertyListGNUstepBinaryFormat, NSPropertyListGNUstepBinaryFormat,
}; };
#if OS_API_VERSION(100600,GS_API_LATEST)
typedef NSUInteger NSPropertyListWriteOptions;
typedef NSUInteger NSPropertyListReadOptions;
#endif
/** /**
* Specifies the serialisation format for a serialised property list. * Specifies the serialisation format for a serialised property list.
* <list> * <list>
@ -254,6 +260,26 @@ typedef NSUInteger NSPropertyListFormat;
format: (NSPropertyListFormat*)aFormat format: (NSPropertyListFormat*)aFormat
errorDescription: (NSString**)anErrorString; errorDescription: (NSString**)anErrorString;
#if OS_API_VERSION(100600,GS_API_LATEST)
+ (NSData *) dataWithPropertyList: (id)aPropertyList
format: (NSPropertyListFormat)aFormat
options: (NSPropertyListWriteOptions)anOption
error: (NSError**)error;
+ (id) propertyListWithData: (NSData*)data
options: (NSPropertyListReadOptions)anOption
format: (NSPropertyListFormat*)aFormat
error: (NSError**)error;
+ (id) propertyListWithStream: (NSInputStream*)stream
options: (NSPropertyListReadOptions)anOption
format: (NSPropertyListFormat*)aFormat
error: (NSError**)error;
+ (NSInteger) writePropertyList: (id)plist
toStream: (NSOutputStream*)stream
format: (NSPropertyListFormat)aFormat
options: (NSPropertyListWriteOptions)anOption
error: (NSError**)error;
#endif
@end @end
#endif /* GS_API_MACOSX */ #endif /* GS_API_MACOSX */

View file

@ -35,9 +35,11 @@
#import "Foundation/NSData.h" #import "Foundation/NSData.h"
#import "Foundation/NSDictionary.h" #import "Foundation/NSDictionary.h"
#import "Foundation/NSEnumerator.h" #import "Foundation/NSEnumerator.h"
#import "Foundation/NSError.h"
#import "Foundation/NSException.h" #import "Foundation/NSException.h"
#import "Foundation/NSPropertyList.h" #import "Foundation/NSPropertyList.h"
#import "Foundation/NSSerialization.h" #import "Foundation/NSSerialization.h"
#import "Foundation/NSStream.h"
#import "Foundation/NSTimeZone.h" #import "Foundation/NSTimeZone.h"
#import "Foundation/NSUserDefaults.h" #import "Foundation/NSUserDefaults.h"
#import "Foundation/NSValue.h" #import "Foundation/NSValue.h"
@ -440,7 +442,7 @@ foundIgnorableWhitespace: (NSString *)string
@end @end
@interface BinaryPLGenerator : NSObject @interface GSBinaryPLGenerator : NSObject
{ {
NSMutableData *dest; NSMutableData *dest;
NSMapTable *objectList; NSMapTable *objectList;
@ -2287,6 +2289,16 @@ OAppend(id obj, NSDictionary *loc, unsigned lev, unsigned step,
static inline NSError*
create_error(int code, NSString* desc)
{
return [NSError errorWithDomain: @"NSPropertyListSerialization"
code: code
userInfo: [NSDictionary
dictionaryWithObjectsAndKeys: desc,
NSLocalizedDescriptionKey, nil]];
}
@implementation NSPropertyListSerialization @implementation NSPropertyListSerialization
@ -2323,6 +2335,25 @@ static BOOL classInitialized = NO;
+ (NSData*) dataFromPropertyList: (id)aPropertyList + (NSData*) dataFromPropertyList: (id)aPropertyList
format: (NSPropertyListFormat)aFormat format: (NSPropertyListFormat)aFormat
errorDescription: (NSString**)anErrorString errorDescription: (NSString**)anErrorString
{
NSError *error = nil;
NSData *data = [self dataWithPropertyList: aPropertyList
format: aFormat
options: 0
error: &error];
if ((error != nil) && (anErrorString != NULL))
{
*anErrorString = [error description];
}
return data;
}
+ (NSData *) dataWithPropertyList: (id)aPropertyList
format: (NSPropertyListFormat)aFormat
options: (NSPropertyListWriteOptions)anOption
error: (NSError**)error
{ {
NSMutableData *dest; NSMutableData *dest;
NSDictionary *loc; NSDictionary *loc;
@ -2333,7 +2364,7 @@ static BOOL classInitialized = NO;
if (aFormat == NSPropertyListXMLFormat_v1_0) if (aFormat == NSPropertyListXMLFormat_v1_0)
{ {
const char *prefix = const char *prefix =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist " "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist "
"PUBLIC \"-//GNUstep//DTD plist 0.9//EN\" " "PUBLIC \"-//GNUstep//DTD plist 0.9//EN\" "
"\"http://www.gnustep.org/plist-0_9.xml\">\n" "\"http://www.gnustep.org/plist-0_9.xml\">\n"
@ -2349,7 +2380,7 @@ static BOOL classInitialized = NO;
} }
else if (aFormat == NSPropertyListBinaryFormat_v1_0) else if (aFormat == NSPropertyListBinaryFormat_v1_0)
{ {
[BinaryPLGenerator serializePropertyList: aPropertyList intoData: dest]; [GSBinaryPLGenerator serializePropertyList: aPropertyList intoData: dest];
} }
else else
{ {
@ -2454,146 +2485,165 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
mutabilityOption: (NSPropertyListMutabilityOptions)anOption mutabilityOption: (NSPropertyListMutabilityOptions)anOption
format: (NSPropertyListFormat*)aFormat format: (NSPropertyListFormat*)aFormat
errorDescription: (NSString**)anErrorString errorDescription: (NSString**)anErrorString
{
NSError *error = nil;
id prop = [self propertyListWithData: data
options: anOption
format: aFormat
error: &error];
if ((error != nil) && (anErrorString != NULL))
{
*anErrorString = [error description];
}
return prop;
}
+ (id) propertyListWithData: (NSData*)data
options: (NSPropertyListReadOptions)anOption
format: (NSPropertyListFormat*)aFormat
error: (NSError**)error
{ {
NSPropertyListFormat format = 0; NSPropertyListFormat format = 0;
NSString *error = nil; NSString *errorStr = nil;
id result = nil; id result = nil;
const unsigned char *bytes = 0; const unsigned char *bytes = 0;
unsigned int length = 0; unsigned int length = 0;
if (data == nil) if (data == nil)
{ {
error = @"nil data argument passed to method"; errorStr = @"nil data argument passed to method";
} }
else if ([data isKindOfClass: NSDataClass] == NO) else if ([data isKindOfClass: NSDataClass] == NO)
{ {
error = @"non-NSData data argument passed to method"; errorStr = @"non-NSData data argument passed to method";
} }
else if ([data length] == 0) else if ([data length] == 0)
{ {
error = @"empty data argument passed to method"; errorStr = @"empty data argument passed to method";
} }
else else
{ {
bytes = [data bytes]; bytes = [data bytes];
length = [data length]; length = [data length];
if (length >= 8 && memcmp(bytes, "bplist00", 8) == 0) if (length >= 8 && memcmp(bytes, "bplist00", 8) == 0)
{ {
format = NSPropertyListBinaryFormat_v1_0; format = NSPropertyListBinaryFormat_v1_0;
} }
else if (bytes[0] == 0 || bytes[0] == 1) else if (bytes[0] == 0 || bytes[0] == 1)
{ {
format = NSPropertyListGNUstepBinaryFormat; format = NSPropertyListGNUstepBinaryFormat;
} }
else else
{ {
unsigned int index = 0; unsigned int index = 0;
// Skip any leading white space. // Skip any leading white space.
while (index < length && GS_IS_WHITESPACE(bytes[index]) == YES) while (index < length && GS_IS_WHITESPACE(bytes[index]) == YES)
{ {
index++; index++;
} }
if (length - index > 2 if (length - index > 2
&& bytes[index] == '<' && bytes[index+1] == '?') && bytes[index] == '<' && bytes[index+1] == '?')
{ {
// It begins with '<?' so it is xml // It begins with '<?' so it is xml
format = NSPropertyListXMLFormat_v1_0; format = NSPropertyListXMLFormat_v1_0;
} }
else else
{ {
// Assume openstep format unless we find otherwise. // Assume openstep format unless we find otherwise.
format = NSPropertyListOpenStepFormat; format = NSPropertyListOpenStepFormat;
} }
} }
} }
if (error == nil) if (errorStr == nil)
{ {
switch (format) switch (format)
{ {
case NSPropertyListXMLFormat_v1_0: case NSPropertyListXMLFormat_v1_0:
{ {
GSXMLPListParser *parser; GSXMLPListParser *parser;
parser = [GSXMLPListParser alloc];
parser = AUTORELEASE([parser initWithData: data
mutability: anOption]);
if ([parser parse] == YES)
{
result = AUTORELEASE(RETAIN([parser result]));
}
else
{
errorStr = @"failed to parse as XML property list";
}
}
break;
case NSPropertyListOpenStepFormat:
{
pldata _pld;
_pld.ptr = bytes;
_pld.pos = 0;
_pld.end = length;
_pld.err = nil;
_pld.lin = 0;
_pld.opt = anOption;
_pld.key = NO;
_pld.old = YES; // OpenStep style
result = AUTORELEASE(parsePlItem(&_pld));
if (_pld.old == NO)
{
// Found some modern GNUstep extension in data.
format = NSPropertyListGNUstepFormat;
}
if (_pld.err != nil)
{
errorStr = [NSString stringWithFormat:
@"Parse failed at line %d (char %d) - %@",
_pld.lin + 1, _pld.pos + 1, _pld.err];
}
}
break;
parser = [GSXMLPListParser alloc]; case NSPropertyListGNUstepBinaryFormat:
parser = AUTORELEASE([parser initWithData: data if (anOption == NSPropertyListImmutable)
mutability: anOption]); {
if ([parser parse] == YES) result = [NSDeserializer deserializePropertyListFromData: data
{ mutableContainers: NO];
result = AUTORELEASE(RETAIN([parser result])); }
} else
else if (error == nil) {
{ result = [NSDeserializer deserializePropertyListFromData: data
error = @"failed to parse as XML property list"; mutableContainers: YES];
} }
} break;
break;
case NSPropertyListBinaryFormat_v1_0:
case NSPropertyListOpenStepFormat: {
{ GSBinaryPLParser *p = [GSBinaryPLParser alloc];
pldata _pld;
p = [p initWithData: data mutability: anOption];
_pld.ptr = bytes; result = [p rootObject];
_pld.pos = 0; RELEASE(p);
_pld.end = length; }
_pld.err = nil; break;
_pld.lin = 0;
_pld.opt = anOption; default:
_pld.key = NO; errorStr = @"format not supported";
_pld.old = YES; // OpenStep style break;
}
result = AUTORELEASE(parsePlItem(&_pld));
if (_pld.old == NO)
{
// Found some modern GNUstep extension in data.
format = NSPropertyListGNUstepFormat;
}
if (_pld.err != nil)
{
error = [NSString stringWithFormat:
@"Parse failed at line %d (char %d) - %@",
_pld.lin + 1, _pld.pos + 1, _pld.err];
}
}
break;
case NSPropertyListGNUstepBinaryFormat:
if (anOption == NSPropertyListImmutable)
{
result = [NSDeserializer deserializePropertyListFromData: data
mutableContainers: NO];
}
else
{
result = [NSDeserializer deserializePropertyListFromData: data
mutableContainers: YES];
}
break;
case NSPropertyListBinaryFormat_v1_0:
{
GSBinaryPLParser *p = [GSBinaryPLParser alloc];
p = [p initWithData: data mutability: anOption];
result = [p rootObject];
RELEASE(p);
}
break;
default:
error = @"format not supported";
break;
}
} }
/* /*
* Done ... return all values. * Done ... return all values.
*/ */
if (anErrorString != 0) if ((errorStr != nil) && (error != NULL))
{ {
*anErrorString = error; *error = create_error(0, errorStr);
} }
if (aFormat != 0) if (aFormat != 0)
{ {
@ -2602,6 +2652,31 @@ GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml,
return result; return result;
} }
+ (id) propertyListWithStream: (NSInputStream*)stream
options: (NSPropertyListReadOptions)anOption
format: (NSPropertyListFormat*)aFormat
error: (NSError**)error
{
// FIXME
return nil;
}
+ (NSInteger) writePropertyList: (id)aPropertyList
toStream: (NSOutputStream*)stream
format: (NSPropertyListFormat)aFormat
options: (NSPropertyListWriteOptions)anOption
error: (NSError**)error
{
// FIXME: The NSData operations should be implemented on top of this method,
// not the other way round,
NSData *data = [self dataWithPropertyList: aPropertyList
format: aFormat
options: 0
error: error];
return [stream write: [data bytes] maxLength: [data length]];
}
@end @end
@ -3254,14 +3329,14 @@ isEqualFunc(const void *item1, const void *item2,
return [o1 isEqual: o2]; return [o1 isEqual: o2];
} }
@implementation BinaryPLGenerator @implementation GSBinaryPLGenerator
+ (void) serializePropertyList: (id)aPropertyList + (void) serializePropertyList: (id)aPropertyList
intoData: (NSMutableData *)destination intoData: (NSMutableData *)destination
{ {
BinaryPLGenerator *gen; GSBinaryPLGenerator *gen;
gen = [[BinaryPLGenerator alloc] gen = [[GSBinaryPLGenerator alloc]
initWithPropertyList: aPropertyList intoData: destination]; initWithPropertyList: aPropertyList intoData: destination];
[gen generate]; [gen generate];
RELEASE(gen); RELEASE(gen);
@ -3525,6 +3600,19 @@ isEqualFunc(const void *item1, const void *item2,
oid = NSSwapHostShortToBig(index); oid = NSSwapHostShortToBig(index);
[dest appendBytes: &oid length: 2]; [dest appendBytes: &oid length: 2];
} }
else if (index_size == 3)
{
unsigned char buffer[index_size];
int i;
unsigned num = index;
for (i = index_size - 1; i >= 0; i--)
{
buffer[i] = num & 0xFF;
num >>= 8;
}
[dest appendBytes: buffer length: index_size];
}
else if (index_size == 4) else if (index_size == 4)
{ {
unsigned int oid; unsigned int oid;