Partial implementation of decoding mac binary format property lists.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18532 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2004-02-03 21:27:10 +00:00
parent 7c4b85e3e2
commit 9bbcb2bec2
2 changed files with 516 additions and 0 deletions

View file

@ -1,3 +1,15 @@
2004-02-02 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSPropertyList.m: Added class by Fred Kiefer to decode
MacOS-X binary property lists ... heavily modified to try to handle
object references and dates (guessed) and to support mutability
options. Current code does not get called by the deserialisation
method as I need to figure out how to tell which format the property
list is in, and for that I need to loook at example archives, which
I haven't had time to do yet. Code comitted mainly so it's saved
somewhere and so that Fred can have a look and see if I've messed
stuff up.
2004-02-02 Roland Schwingel <roland.schwingel@onevision.de>
* Source/NSString.m: ([stringByAbbreviatingWithTildeInPath]) fix bug

View file

@ -2,6 +2,7 @@
Copyright (C) 2003,2004 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
Fred Kiefer <FredKiefer@gmx.de>
This file is part of the GNUstep Base Library.
@ -28,6 +29,7 @@
#include "Foundation/NSArray.h"
#include "Foundation/NSAutoreleasePool.h"
#include "Foundation/NSByteOrder.h"
#include "Foundation/NSCalendarDate.h"
#include "Foundation/NSCharacterSet.h"
#include "Foundation/NSData.h"
@ -47,6 +49,24 @@ extern BOOL GSScanDouble(unichar*, unsigned, double*);
@class GSMutableArray;
@class GSMutableDictionary;
@interface GSBinaryPLParser : NSObject
{
NSPropertyListMutabilityOptions mutability;
const unsigned char *_bytes;
NSData *data;
unsigned size; // Number of bytes per table entry
unsigned table_start; // Start address of object table
unsigned table_len; // Length of object table
NSMutableArray *_objects; // All decoded objects.
}
- (id) initWithData: (NSData*)plData
mutability: (NSPropertyListMutabilityOptions)m;
- (id) rootObject;
- (id) objectAtIndex: (unsigned)index;
@end
/*
* Cache classes and method implementations for speed.
@ -2238,3 +2258,487 @@ OAppend(id obj, NSDictionary *loc, unsigned lev, unsigned step,
return AUTORELEASE(string);
}
@end
@implementation GSBinaryPLParser
- (void) dealloc
{
DESTROY(data);
DESTROY(_objects);
[super dealloc];
}
- (id) initWithData: (NSData*)plData
mutability: (NSPropertyListMutabilityOptions)m;
{
unsigned length;
length = [plData length];
if (length < 32)
{
DESTROY(self);
}
else
{
unsigned char postfix[32];
// FIXME: Get more of the details
[data getBytes: postfix range: NSMakeRange(length-32, 32)];
size = postfix[6];
if (size < 1 || size > 2)
{
DESTROY(self); // Bad format
}
else if ((table_start = 256*postfix[30] + postfix[31]) > length - 32)
{
DESTROY(self); // Bad format
}
else
{
table_len = length - table_start - 32;
_objects = [NSMutableArray new];
ASSIGN(data, plData);
_bytes = (const unsigned char*)[data bytes];
mutability = m;
}
}
return self;
}
- (unsigned) offsetForIndex: (unsigned)index
{
if (index > table_len)
{
[NSException raise: NSRangeException
format: @"Object table index out of bounds %d.", index];
}
if (size == 1)
{
unsigned char offset;
[data getBytes: &offset range: NSMakeRange(table_start + index, 1)];
return offset;
}
else if (size == 2)
{
unsigned short offset;
[data getBytes: &offset range: NSMakeRange(table_start + 2*index, 2)];
return NSSwapBigShortToHost(offset);
}
else
{
[NSException raise: NSGenericException
format: @"Unknown table size %d", size];
}
return 0;
}
- (unsigned) readObjectIndexAt: (unsigned*)counter
{
if (size == 1)
{
unsigned char oid;
[data getBytes: &oid range: NSMakeRange(*counter,1)];
*counter += 1;
return oid;
}
else if (size == 2)
{
unsigned short oid;
[data getBytes: &oid range: NSMakeRange(*counter,sizeof(short))];
*counter += sizeof(short);
return NSSwapBigShortToHost(oid);
}
else
{
[NSException raise: NSGenericException
format: @"Unkown table size %d", size];
}
return 0;
}
- (unsigned) readCountAt: (unsigned*) counter
{
unsigned char c;
[data getBytes: &c range: NSMakeRange(*counter,1)];
*counter += 1;
if (c == 0x10)
{
unsigned char count;
[data getBytes: &count range: NSMakeRange(*counter,1)];
*counter += 1;
return count;
}
else if (c == 0x11)
{
unsigned short count;
[data getBytes: &count range: NSMakeRange(*counter,2)];
*counter += 2;
return NSSwapBigShortToHost(count);
}
else
{
//FIXME
[NSException raise: NSGenericException
format: @"Unkown coutn type %d", c];
}
return 0;
}
- (id) rootObject
{
return [self objectAtIndex: 0];
}
- (id) objectAtIndex: (unsigned)index
{
unsigned char next;
unsigned counter = [self offsetForIndex: index];
id result = nil;
[data getBytes: &next range: NSMakeRange(counter,1)];
//NSLog(@"read object %d at index %d type %d", index, counter, next);
counter += 1;
if (next == 0x08)
{
// NO
result = [NSNumber numberWithBool: NO];
}
else if (next == 0x09)
{
// YES
result = [NSNumber numberWithBool: YES];
}
else if ((next >= 0x10) && (next < 0x1F))
{
// integer number
unsigned len = next - 0x10 + 1;
int num = 0;
unsigned i;
unsigned char buffer[16];
[data getBytes: buffer range: NSMakeRange(counter, len)];
for (i = 0; i < len; i++)
{
num = num*256 + buffer[counter + i];
}
result = [NSNumber numberWithInt: num];
}
else if (next == 0x22)
{
// float number
float in;
[data getBytes: &in range: NSMakeRange(counter, sizeof(float))];
result = [NSNumber numberWithFloat: NSSwapBigFloatToHost(in)];
}
else if (next == 0x23)
{
// double number
double in;
[data getBytes: &in range: NSMakeRange(counter, sizeof(double))];
result = [NSNumber numberWithFloat: NSSwapBigDoubleToHost(in)];
}
else if (next == 0x33)
{
double in;
// Date
NSDate *date;
[data getBytes: &in range: NSMakeRange(counter, sizeof(double))];
date = [NSDate dateWithTimeIntervalSinceReferenceDate:
NSSwapBigDoubleToHost(in)];
result = date;
}
else if ((next >= 0x40) && (next < 0x4F))
{
// short data
unsigned len = next - 0x40;
if (mutability == NSPropertyListMutableContainersAndLeaves)
{
result = [NSMutableData dataWithBytes: _bytes + counter
length: len];
}
else
{
result = [data subdataWithRange: NSMakeRange(counter, len)];
}
}
else if (next == 0x4F)
{
// long data
unsigned len;
len = [self readCountAt: &counter];
if (mutability == NSPropertyListMutableContainersAndLeaves)
{
result = [NSMutableData dataWithBytes: _bytes + counter
length: len];
}
else
{
result = [data subdataWithRange: NSMakeRange(counter, len)];
}
}
else if ((next >= 0x50) && (next < 0x5F))
{
// Short string
unsigned len = next - 0x50;
unsigned char buffer[len];
[data getBytes: buffer range: NSMakeRange(counter, len)];
if (mutability == NSPropertyListMutableContainersAndLeaves)
{
result = [NSMutableString stringWithCString: buffer length: len];
}
else
{
result = [NSString stringWithCString: buffer length: len];
}
}
else if (next == 0x5F)
{
// long string
unsigned len;
char *buffer;
len = [self readCountAt: &counter];
buffer = malloc(len+1);
[data getBytes: buffer range: NSMakeRange(counter, len)];
buffer[len] = '\0';
if (mutability == NSPropertyListMutableContainersAndLeaves)
{
result = [NSMutableString stringWithUTF8String: buffer];
}
else
{
result = [NSString stringWithUTF8String: buffer];
}
free(buffer);
}
else if ((next >= 0x60) && (next < 0x6F))
{
// Short unicode string
unsigned len = next - 0x60;
unsigned i;
unichar buffer[len];
[data getBytes: buffer
range: NSMakeRange(counter, sizeof(unichar)*len)];
for (i = 0; i < len; i++)
{
buffer[i] = NSSwapBigShortToHost(buffer[i]);
}
if (mutability == NSPropertyListMutableContainersAndLeaves)
{
result = [NSMutableString stringWithCharacters: buffer length: len];
}
else
{
result = [NSString stringWithCharacters: buffer length: len];
}
}
else if (next == 0x6F)
{
// long unicode string
unsigned len;
unsigned i;
unichar *buffer;
len = [self readCountAt: &counter];
buffer = malloc(sizeof(unichar)*len);
[data getBytes: buffer range: NSMakeRange(counter, sizeof(unichar)*len)];
for (i = 0; i < len; i++)
{
buffer[i] = NSSwapBigShortToHost(buffer[i]);
}
if (mutability == NSPropertyListMutableContainersAndLeaves)
{
result = [NSMutableString stringWithCharacters: buffer length: len];
}
else
{
result = [NSString stringWithCharacters: buffer length: len];
}
free(buffer);
}
else if (next == 0x80)
{
unsigned char index;
[data getBytes: &index range: NSMakeRange(counter,1)];
result = [_objects objectAtIndex: index];
}
else if (next == 0x81)
{
unsigned short index;
[data getBytes: &index range: NSMakeRange(counter,2)];
index = NSSwapBigShortToHost(index);
result = [_objects objectAtIndex: index];
}
else if ((next >= 0xA0) && (next < 0xAF))
{
// short array
unsigned len = next - 0xA0;
unsigned i;
id objects[len];
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
objects[i] = [self objectAtIndex: oid];
}
if (mutability == NSPropertyListMutableContainersAndLeaves
|| mutability == NSPropertyListMutableContainers)
{
result = [NSMutableArray arrayWithObjects: objects count: len];
}
else
{
result = [NSArray arrayWithObjects: objects count: len];
}
}
else if (next == 0xAF)
{
// big array
unsigned len;
unsigned i;
id *objects;
len = [self readCountAt: &counter];
objects = malloc(sizeof(id) * len);
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
objects[i] = [self objectAtIndex: oid];
}
if (mutability == NSPropertyListMutableContainersAndLeaves
|| mutability == NSPropertyListMutableContainers)
{
result =[NSMutableArray arrayWithObjects: objects count: len];
}
else
{
result =[NSArray arrayWithObjects: objects count: len];
}
free(objects);
}
else if ((next >= 0xD0) && (next < 0xDF))
{
// dictionary
unsigned len = next - 0xD0;
unsigned i;
id keys[len];
id values[len];
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
keys[i] = [self objectAtIndex: oid];
}
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
values[i] = [self objectAtIndex: oid];
}
if (mutability == NSPropertyListMutableContainersAndLeaves
|| mutability == NSPropertyListMutableContainers)
{
result = [NSMutableDictionary dictionaryWithObjects: values
forKeys: keys
count: len];
}
else
{
result = [NSDictionary dictionaryWithObjects: values
forKeys: keys
count: len];
}
}
else if (next == 0xDF)
{
// big dictionary
unsigned len;
unsigned i;
id *keys;
id *values;
len = [self readCountAt: &counter];
keys = malloc(sizeof(id)*len);
values = malloc(sizeof(id)*len);
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
keys[i] = [self objectAtIndex: oid];
}
for (i = 0; i < len; i++)
{
int oid = [self readObjectIndexAt: &counter];
values[i] = [self objectAtIndex: oid];
}
if (mutability == NSPropertyListMutableContainersAndLeaves
|| mutability == NSPropertyListMutableContainers)
{
result = [NSMutableDictionary dictionaryWithObjects: values
forKeys: keys
count: len];
}
else
{
result = [NSDictionary dictionaryWithObjects: values
forKeys: keys
count: len];
}
free(values);
free(keys);
}
else
{
[NSException raise: NSGenericException
format: @"Unknown control byte = %d", next];
}
[_objects addObject: result];
return result;
}
@end