mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-25 01:31:08 +00:00
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:
parent
7c4b85e3e2
commit
9bbcb2bec2
2 changed files with 516 additions and 0 deletions
12
ChangeLog
12
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue