iProperty list and encoding fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@7888 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2000-10-23 11:44:34 +00:00
parent 38b8d11f24
commit 9cf69df9a9
6 changed files with 920 additions and 937 deletions

View file

@ -4,11 +4,13 @@
implemented to return NSUnicodeStringEncoding. Use new string
classes more effectively - let GSString turn itsself into either
GSCString or GSUstring when initialised.
Merged in code from propList.h
* Source/GSString.m: ([-dataUsingEncoding:allowLossyConversion:])
bugfixes for cString reported by Freed Kiefer
Removed 'ascii' flag - more trouble than a minor optimisation is
worth.
Fixed transmute() to be careful about freeing old string.
* Source/Unicode.m: encode_ustrtostr_strict() return 0 on failure.
2000-10-21 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -389,7 +389,12 @@ cString_u(ivars self)
if (self->_count > 0)
{
encode_ustrtostr_strict(r, self->_contents.u, self->_count, defEnc);
if (encode_ustrtostr_strict(r, self->_contents.u, self->_count, defEnc)
== 0)
{
[NSException raise: NSCharacterConversionException
format: @"Can't get cString from Unicode string."];
}
}
r[self->_count] = '\0';
@ -412,7 +417,12 @@ cStringLength_u(ivars self)
char *r;
r = (char*)NSZoneMalloc(NSDefaultMallocZone(), self->_count+1);
encode_ustrtostr(r, self->_contents.u, self->_count, defEnc);
if (encode_ustrtostr(r, self->_contents.u, self->_count, defEnc) == 0)
{
NSZoneFree(NSDefaultMallocZone(), r);
[NSException raise: NSCharacterConversionException
format: @"Can't get cStringLength from Unicode string."];
}
r[self->_count] = '\0';
c = strlen(r);
NSZoneFree(NSDefaultMallocZone(), r);
@ -452,10 +462,12 @@ dataUsingEncoding_c(ivars self, NSStringEncoding encoding, BOOL flag)
int t;
unichar *buff;
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), 2*len+2);
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(),
sizeof(unichar)*(len+1));
buff[0] = 0xFEFF;
t = encode_strtoustr(buff+1, self->_contents.c, len, defEnc);
return [NSDataClass dataWithBytesNoCopy: buff length: t+2];
return [NSDataClass dataWithBytesNoCopy: buff
length: sizeof(unichar)*(t+1)];
}
else
{
@ -463,16 +475,16 @@ dataUsingEncoding_c(ivars self, NSStringEncoding encoding, BOOL flag)
unichar *ubuff;
unsigned char *buff;
ubuff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), 2*len);
ubuff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(),
sizeof(unichar)*len);
t = encode_strtoustr(ubuff, self->_contents.c, len, defEnc);
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), t+1);
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), t);
if (flag)
t = encode_ustrtostr(buff, ubuff, t, encoding);
else
t = encode_ustrtostr_strict(buff, ubuff, t, encoding);
buff[t] = '\0';
NSZoneFree(NSDefaultMallocZone(), ubuff);
if (t != len)
if (t == 0)
{
NSZoneFree(NSDefaultMallocZone(), buff);
return nil;
@ -495,22 +507,23 @@ dataUsingEncoding_u(ivars self, NSStringEncoding encoding, BOOL flag)
{
unichar *buff;
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), 2*len+2);
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(),
sizeof(unichar)*(len+1));
buff[0] = 0xFEFF;
memcpy(buff+1, self->_contents.u, 2*len);
return [NSData dataWithBytesNoCopy: buff length: 2*len+2];
memcpy(buff+1, self->_contents.u, sizeof(unichar)*len);
return [NSData dataWithBytesNoCopy: buff
length: sizeof(unichar)*(len+1)];
}
else
{
int t;
unsigned char *buff;
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), len+1);
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), len);
if (flag == YES)
t = encode_ustrtostr(buff, self->_contents.u, len, encoding);
else
t = encode_ustrtostr_strict(buff, self->_contents.u, len, encoding);
buff[t] = '\0';
if (!t)
{
NSZoneFree(NSDefaultMallocZone(), buff);

View file

@ -231,12 +231,11 @@ $(GNUSTEP_OBJ_DIR)/NSSerializer.o \
#
# Files that include fast.x will need a rebuild if it is changed.
#
$(GNUSTEP_OBJ_DIR)/GSString.o \
$(GNUSTEP_OBJ_DIR)/NSArchiver.o \
$(GNUSTEP_OBJ_DIR)/NSArray.o \
$(GNUSTEP_OBJ_DIR)/NSData.o \
$(GNUSTEP_OBJ_DIR)/NSGCString.o \
$(GNUSTEP_OBJ_DIR)/NSGDictionary.o \
$(GNUSTEP_OBJ_DIR)/NSGString.o \
$(GNUSTEP_OBJ_DIR)/NSInvocation.o \
$(GNUSTEP_OBJ_DIR)/NSObjCRuntime.o \
$(GNUSTEP_OBJ_DIR)/NSObject.o \
@ -245,20 +244,11 @@ $(GNUSTEP_OBJ_DIR)/NSString.o \
$(GNUSTEP_OBJ_DIR)/NSUnarchiver.o \
: $(HEADER_DIR)/fast.x
#
# Files that include propList.h will need a rebuild if it is changed.
#
$(GNUSTEP_OBJ_DIR)/NSString.o \
$(GNUSTEP_OBJ_DIR)/NSGString.o \
$(GNUSTEP_OBJ_DIR)/NSGCString.o \
: propList.h
#
# Files that include GSeq.h will need a rebuild if it is changed.
#
$(GNUSTEP_OBJ_DIR)/NSString.o \
$(GNUSTEP_OBJ_DIR)/NSGString.o \
$(GNUSTEP_OBJ_DIR)/NSGCString.o \
$(GNUSTEP_OBJ_DIR)/GSString.o \
: GSeq.h
#

File diff suppressed because it is too large Load diff

View file

@ -339,13 +339,14 @@ iconv_strtoustr(unichar *u2, int size2, const char *s1, int size1, NSStringEncod
}
int
iconv_ustrtostr(char *s2, int size2, unichar *u1, int size1, NSStringEncoding enc)
iconv_ustrtostr(char *s2, int size2, unichar *u1, int size1,
NSStringEncoding enc)
{
iconv_t conv;
int usize = sizeof(unichar)*size1;
char *s1 = s2;
const char *u2 = (const char*)u1;
int ret_val;
iconv_t conv;
int usize = sizeof(unichar)*size1;
char *s1 = s2;
const char *u2 = (const char*)u1;
int ret_val;
conv = iconv_open(iconv_stringforencoding(enc), UNICODE_ENC);
if (conv == (iconv_t)-1)
@ -867,7 +868,7 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
if (u < 128)
s2[count] = (char)u;
else
break;
return 0;
}
return count;
@ -878,7 +879,7 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
if (u < 128)
s2[count] = (char)u;
else
break;
return 0;
}
return count;
@ -890,7 +891,7 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
if (u < 256)
s2[count] = (char)u;
else
break;
return 0;
}
return count;
@ -906,11 +907,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
int i = 0;
while (((res = u - Next_uni_to_char_table[i++].from) > 0)
&& (i < Next_uni_to_char_table_size));
&& (i < Next_uni_to_char_table_size));
if (!res)
s2[count] = Next_uni_to_char_table[--i].to;
else
break;
return 0;
}
}
return count;
@ -927,11 +928,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
int i = 0;
while (((res = u - Cyrillic_uni_to_char_table[i++].from) > 0)
&& (i < Cyrillic_uni_to_char_table_size));
&& (i < Cyrillic_uni_to_char_table_size));
if (!res)
s2[count] = Cyrillic_uni_to_char_table[--i].to;
else
break;
return 0;
}
}
return count;
@ -948,11 +949,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
int i = 0;
while (((res = u - Latin2_uni_to_char_table[i++].from) > 0)
&& (i < Latin2_uni_to_char_table_size));
&& (i < Latin2_uni_to_char_table_size));
if (!res)
s2[count] = Latin2_uni_to_char_table[--i].to;
else
break;
return 0;
}
}
return count;
@ -970,11 +971,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
int i = 0;
while (((res = u - Symbol_uni_to_char_table[i++].from) > 0)
&& (i < Symbol_uni_to_char_table_size));
&& (i < Symbol_uni_to_char_table_size));
if (!res)
s2[count] = Symbol_uni_to_char_table[--i].to;
else
break;
return 0;
}
}
return count;

View file

@ -1,828 +0,0 @@
/* Text Property-List parsing code for NSString.m and NSGCString.m
Copyright (C) 1998,2000 Free Software Foundation, Inc.
Written by Richard Frith-Macdonald <richard@brainstorm.co.uk>
Date: October 1998
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/
#if HAVE_LIBXML
#include <Foundation/GSXML.h>
static void
decodeBase64Unit(const char* ptr, unsigned char *out)
{
out[0] = (ptr[0] << 2) | ((ptr[1] & 0x30) >> 4);
out[1] = ((ptr[1] & 0x0F) << 4) | ((ptr[2] & 0x3C) >> 2);
out[2] = ((ptr[2] & 0x03) << 6) | (ptr[3] & 0x3F);
out[3] = 0;
}
static NSData*
decodeBase64(const char *source)
{
int length = strlen(source);
char *sourceBuffer = objc_malloc(length+1);
NSMutableData *data = [NSMutableData dataWithCapacity:0];
int i, j;
unsigned char tmp[4];
strcpy(sourceBuffer, source);
j = 0;
for (i = 0; i < length; i++)
{
if (!isspace(source[i]))
{
sourceBuffer[j++] = source[i];
}
}
sourceBuffer[j] = '\0';
length = strlen(sourceBuffer);
while (length > 0 && sourceBuffer[length-1] == '=')
{
sourceBuffer[--length] = '\0';
}
for (i = 0; i < length; i += 4)
{
decodeBase64Unit(&sourceBuffer[i], tmp);
[data appendBytes: tmp length: strlen(tmp)];
}
objc_free(sourceBuffer);
return data;
}
#endif
/*
* Cache some commonly used character sets along with methods to
* check membership.
*/
static SEL cMemberSel = @selector(characterIsMember:);
static NSCharacterSet *hexdigits = nil;
static BOOL (*hexdigitsImp)(id, SEL, unichar) = 0;
static void setupHexdigits()
{
if (hexdigits == nil)
{
hexdigits = [NSCharacterSet characterSetWithCharactersInString:
@"0123456789abcdefABCDEF"];
IF_NO_GC(RETAIN(hexdigits));
hexdigitsImp =
(BOOL(*)(id,SEL,unichar)) [hexdigits methodForSelector: cMemberSel];
}
}
static NSCharacterSet *quotables = nil;
static BOOL (*quotablesImp)(id, SEL, unichar) = 0;
static void setupQuotables()
{
if (quotables == nil)
{
NSMutableCharacterSet *s;
s = [[NSCharacterSet characterSetWithCharactersInString:
@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$./_"]
mutableCopy];
[s invert];
quotables = [s copy];
RELEASE(s);
quotablesImp =
(BOOL(*)(id,SEL,unichar)) [quotables methodForSelector: cMemberSel];
}
}
static NSCharacterSet *whitespce = nil;
static BOOL (*whitespceImp)(id, SEL, unichar) = 0;
static void setupWhitespce()
{
if (whitespce == nil)
{
whitespce = [NSCharacterSet characterSetWithCharactersInString:
@" \t\r\n\f\b"];
IF_NO_GC(RETAIN(whitespce));
whitespceImp =
(BOOL(*)(id,SEL,unichar)) [whitespce methodForSelector: cMemberSel];
}
}
@class NSGMutableArray;
@class NSGMutableDictionary;
static Class plCls;
static Class plArray;
static id (*plAdd)(id, SEL, id);
static Class plDictionary;
static id (*plSet)(id, SEL, id, id);
static id (*plInit)(id, SEL, void*, unsigned) = 0;
static id (*plAlloc)(Class, SEL, NSZone*);
#if GSPLUNI
static SEL plSel = @selector(initWithCharacters:length:);
#else
static SEL plSel = @selector(initWithCString:length:);
#endif
static void setupPl(Class c)
{
if (plInit == 0)
{
plCls = c;
plAlloc = (id (*)(id, SEL, NSZone*))
[c methodForSelector: @selector(allocWithZone:)];
plInit = (id (*)(id, SEL, void*, unsigned))
[c instanceMethodForSelector: plSel];
plArray = [NSGMutableArray class];
plAdd = (id (*)(id, SEL, id))
[plArray instanceMethodForSelector: @selector(addObject:)];
plDictionary = [NSGMutableDictionary class];
plSet = (id (*)(id, SEL, id, id))
[plDictionary instanceMethodForSelector: @selector(setObject:forKey:)];
}
setupHexdigits();
setupQuotables();
setupWhitespce();
}
#define inrange(ch,min,max) ((ch)>=(min) && (ch)<=(max))
#define char2num(ch) \
inrange(ch,'0','9') \
? ((ch)-0x30) \
: (inrange(ch,'a','f') \
? ((ch)-0x57) : ((ch)-0x37))
typedef struct {
#if GSPLUNI
const unichar *ptr;
#else
const char *ptr;
#endif
unsigned end;
unsigned pos;
unsigned lin;
NSString *err;
} pldata;
/*
* Property list parsing - skip whitespace keeping count of lines and
* regarding objective-c style comments as whitespace.
* Returns YES if there is any non-whitespace text remaining.
*/
static BOOL skipSpace(pldata *pld)
{
unichar c;
while (pld->pos < pld->end)
{
c = (unichar)pld->ptr[pld->pos];
if ((*whitespceImp)(whitespce, cMemberSel, c) == NO)
{
if (c == '/' && pld->pos < pld->end - 1)
{
/*
* Check for comments beginning '/' followed by '/' or '*'
*/
if (pld->ptr[pld->pos + 1] == '/')
{
pld->pos += 2;
while (pld->pos < pld->end)
{
c = pld->ptr[pld->pos];
if (c == '\n')
break;
pld->pos++;
}
if (pld->pos >= pld->end)
{
pld->err = @"reached end of string in comment";
return NO;
}
}
else if (pld->ptr[pld->pos + 1] == '*')
{
pld->pos += 2;
while (pld->pos < pld->end)
{
c = pld->ptr[pld->pos];
if (c == '\n')
pld->lin++;
else if (c == '*' && pld->pos < pld->end - 1
&& pld->ptr[pld->pos+1] == '/')
{
pld->pos++; /* Skip past '*' */
break;
}
pld->pos++;
}
if (pld->pos >= pld->end)
{
pld->err = @"reached end of string in comment";
return NO;
}
}
else
return YES;
}
else
return YES;
}
if (c == '\n')
pld->lin++;
pld->pos++;
}
pld->err = @"reached end of string";
return NO;
}
static inline id parseQuotedString(pldata* pld)
{
unsigned start = ++pld->pos;
unsigned escaped = 0;
unsigned shrink = 0;
BOOL hex = NO;
NSString *obj;
while (pld->pos < pld->end)
{
unichar c = (unichar)pld->ptr[pld->pos];
if (escaped)
{
if (escaped == 1 && c == '0')
{
escaped = 2;
hex = NO;
}
else if (escaped > 1)
{
if (escaped == 2 && c == 'x')
{
hex = YES;
shrink++;
escaped++;
}
else if (hex && (*hexdigitsImp)(hexdigits, cMemberSel, c))
{
shrink++;
escaped++;
}
else if (c >= '0' && c <= '7')
{
shrink++;
escaped++;
}
else
{
pld->pos--;
escaped = 0;
}
}
else
{
escaped = 0;
}
}
else
{
if (c == '\\')
{
escaped = 1;
shrink++;
}
else if (c == '"')
{
break;
}
}
if (c == '\n')
pld->lin++;
pld->pos++;
}
if (pld->pos >= pld->end)
{
pld->err = @"reached end of string while parsing quoted string";
return nil;
}
if (pld->pos - start - shrink == 0)
{
obj = @"";
}
else
{
#if GSPLUNI
unichar chars[pld->pos - start - shrink];
#else
char chars[pld->pos - start - shrink];
#endif
unsigned j;
unsigned k;
escaped = 0;
hex = NO;
for (j = start, k = 0; j < pld->pos; j++)
{
unichar c = (unichar)pld->ptr[j];
if (escaped)
{
if (escaped == 1 && c == '0')
{
chars[k] = 0;
hex = NO;
escaped++;
}
else if (escaped > 1)
{
if (escaped == 2 && c == 'x')
{
hex = YES;
escaped++;
}
else if (hex && (*hexdigitsImp)(hexdigits, cMemberSel, c))
{
chars[k] <<= 4;
chars[k] |= char2num(c);
escaped++;
}
else if (c >= '0' && c <= '7')
{
chars[k] <<= 3;
chars[k] |= (c - '0');
escaped++;
}
else
{
escaped = 0;
j--;
k++;
}
}
else
{
escaped = 0;
switch (c)
{
case 'a' : chars[k] = '\a'; break;
case 'b' : chars[k] = '\b'; break;
case 't' : chars[k] = '\t'; break;
case 'r' : chars[k] = '\r'; break;
case 'n' : chars[k] = '\n'; break;
case 'v' : chars[k] = '\v'; break;
case 'f' : chars[k] = '\f'; break;
default : chars[k] = c; break;
}
k++;
}
}
else
{
chars[k] = c;
if (c == '\\')
{
escaped = 1;
}
else
{
k++;
}
}
}
obj = (*plAlloc)(plCls, @selector(allocWithZone:), NSDefaultMallocZone());
obj = (*plInit)(obj, plSel, (void*)chars, pld->pos - start - shrink);
}
pld->pos++;
return obj;
}
static inline id parseUnquotedString(pldata *pld)
{
unsigned start = pld->pos;
id obj;
while (pld->pos < pld->end)
{
if ((*quotablesImp)(quotables, cMemberSel,
(unichar)pld->ptr[pld->pos]) == YES)
break;
pld->pos++;
}
obj = (*plAlloc)(plCls, @selector(allocWithZone:), NSDefaultMallocZone());
obj = (*plInit)(obj, plSel, (void*)&pld->ptr[start], pld->pos-start);
return obj;
}
static id parsePlItem(pldata* pld)
{
if (skipSpace(pld) == NO)
return nil;
switch (pld->ptr[pld->pos])
{
case '{':
{
NSMutableDictionary *dict;
dict = [[plDictionary allocWithZone: NSDefaultMallocZone()]
initWithCapacity: 0];
pld->pos++;
while (skipSpace(pld) == YES && pld->ptr[pld->pos] != '}')
{
id key;
id val;
key = parsePlItem(pld);
if (key == nil)
return nil;
if (skipSpace(pld) == NO)
{
RELEASE(key);
return nil;
}
if (pld->ptr[pld->pos] != '=')
{
pld->err = @"unexpected character (wanted '=')";
RELEASE(key);
return nil;
}
pld->pos++;
val = parsePlItem(pld);
if (val == nil)
{
RELEASE(key);
return nil;
}
if (skipSpace(pld) == NO)
{
RELEASE(key);
RELEASE(val);
return nil;
}
if (pld->ptr[pld->pos] == ';')
{
pld->pos++;
}
else if (pld->ptr[pld->pos] != '}')
{
pld->err = @"unexpected character (wanted ';' or '}')";
RELEASE(key);
RELEASE(val);
return nil;
}
(*plSet)(dict, @selector(setObject:forKey:), val, key);
RELEASE(key);
RELEASE(val);
}
if (pld->pos >= pld->end)
{
pld->err = @"unexpected end of string when parsing dictionary";
RELEASE(dict);
return nil;
}
pld->pos++;
return dict;
}
case '(':
{
NSMutableArray *array;
array = [[plArray allocWithZone: NSDefaultMallocZone()]
initWithCapacity: 0];
pld->pos++;
while (skipSpace(pld) == YES && pld->ptr[pld->pos] != ')')
{
id val;
val = parsePlItem(pld);
if (val == nil)
{
return nil;
}
if (skipSpace(pld) == NO)
{
RELEASE(val);
return nil;
}
if (pld->ptr[pld->pos] == ',')
{
pld->pos++;
}
else if (pld->ptr[pld->pos] != ')')
{
pld->err = @"unexpected character (wanted ',' or ')')";
RELEASE(val);
return nil;
}
(*plAdd)(array, @selector(addObject:), val);
RELEASE(val);
}
if (pld->pos >= pld->end)
{
pld->err = @"unexpected end of string when parsing array";
RELEASE(array);
return nil;
}
pld->pos++;
return array;
}
case '<':
{
NSMutableData *data;
unsigned max = pld->end - 1;
unsigned char buf[BUFSIZ];
unsigned len = 0;
data = [[NSMutableData alloc] initWithCapacity: 0];
pld->pos++;
while (skipSpace(pld) == YES && pld->ptr[pld->pos] != '>')
{
while (pld->pos < max
&& (*hexdigitsImp)(hexdigits, cMemberSel,
(unichar)pld->ptr[pld->pos])
&& (*hexdigitsImp)(hexdigits, cMemberSel,
(unichar)pld->ptr[pld->pos+1]))
{
unsigned char byte;
byte = (char2num(pld->ptr[pld->pos])) << 4;
pld->pos++;
byte |= char2num(pld->ptr[pld->pos]);
pld->pos++;
buf[len++] = byte;
if (len == sizeof(buf))
{
[data appendBytes: buf length: len];
len = 0;
}
}
}
if (pld->pos >= pld->end)
{
pld->err = @"unexpected end of string when parsing data";
RELEASE(data);
return nil;
}
if (pld->ptr[pld->pos] != '>')
{
pld->err = @"unexpected character in string";
RELEASE(data);
return nil;
}
if (len > 0)
{
[data appendBytes: buf length: len];
}
pld->pos++;
return data;
}
case '"':
return parseQuotedString(pld);
default:
return parseUnquotedString(pld);
}
}
#if HAVE_LIBXML
static GSXMLNode*
elementNode(GSXMLNode* node)
{
while (node != nil)
{
if ([node type] == XML_ELEMENT_NODE)
{
break;
}
node = [node next];
}
return node;
}
static id
nodeToObject(GSXMLNode* node)
{
NSString *name;
NSString *content;
GSXMLNode *children;
node = elementNode(node);
if (node == nil)
{
return nil;
}
name = [node name];
children = [node children];
content = [children content];
children = elementNode(children);
if ([name isEqualToString: @"string"])
{
return content;
}
else if ([name isEqualToString: @"key"])
{
return content;
}
else if ([name isEqualToString: @"true"])
{
return [NSNumber numberWithBool: YES];
}
else if ([name isEqualToString: @"false"])
{
return [NSNumber numberWithBool: NO];
}
else if ([name isEqualToString: @"integer"])
{
return [NSNumber numberWithInt: [content intValue]];
}
else if ([name isEqualToString: @"real"])
{
return [NSNumber numberWithDouble: [content doubleValue]];
}
else if ([name isEqualToString: @"date"])
{
return [NSCalendarDate dateWithString: content
calendarFormat: @"%Y-%m-%d %H:%M:%S %z"];
}
else if ([name isEqualToString: @"data"])
{
return decodeBase64([content cString]);
}
// container class
else if ([name isEqualToString: @"array"])
{
NSMutableArray *container = [NSMutableArray array];
while (children != nil)
{
id val;
val = nodeToObject(children);
[container addObject: val];
children = elementNode([children next]);
}
return container;
}
else if ([name isEqualToString: @"dict"])
{
NSMutableDictionary *container = [NSMutableDictionary dictionary];
while (children != nil)
{
NSString *key;
id val;
key = nodeToObject(children);
children = elementNode([children next]);
val = nodeToObject(children);
children = elementNode([children next]);
[container setObject: val forKey: key];
}
return container;
}
else
{
return nil;
}
}
#endif
static id parsePl(pldata* pld)
{
#if HAVE_LIBXML
while (pld->pos < pld->end && isspace(pld->ptr[pld->pos]))
{
pld->pos++;
}
/*
* A string beginning with a '<?' must be an XML file
*/
if (pld->pos + 1 < pld->end && pld->ptr[pld->pos] == '<'
&& pld->ptr[pld->pos+1] == '?')
{
NSData *data;
GSXMLParser *parser;
char *buf = NSZoneMalloc(NSDefaultMallocZone(), pld->end);
memcpy(buf, pld->ptr, pld->end);
data = [NSData dataWithBytesNoCopy: buf length: pld->end];
parser = [GSXMLParser parserWithData: data];
[parser substituteEntities: NO];
if ([parser parse] == YES)
{
if (![[[[parser doc] root] name] isEqualToString: @"plist"])
{
NSLog(@"not a property list - because name node is %@",
[[[parser doc] root] name]);
return nil;
}
return RETAIN(nodeToObject([[[parser doc] root] children]));
}
else
{
NSLog(@"not a property list - failed to parse as XML");
return nil;
}
}
#endif
return parsePlItem(pld);
}
static id parseSfItem(pldata* pld)
{
NSMutableDictionary *dict;
dict = [[plDictionary allocWithZone: NSDefaultMallocZone()]
initWithCapacity: 0];
while (skipSpace(pld) == YES)
{
id key;
id val;
if (pld->ptr[pld->pos] == '"')
key = parseQuotedString(pld);
else
key = parseUnquotedString(pld);
if (key == nil)
return nil;
if (skipSpace(pld) == NO)
{
pld->err = @"incomplete final entry (no semicolon?)";
RELEASE(key);
return nil;
}
if (pld->ptr[pld->pos] == ';')
{
pld->pos++;
(*plSet)(dict, @selector(setObject:forKey:), @"", key);
RELEASE(key);
}
else if (pld->ptr[pld->pos] == '=')
{
pld->pos++;
if (skipSpace(pld) == NO)
{
RELEASE(key);
return nil;
}
if (pld->ptr[pld->pos] == '"')
val = parseQuotedString(pld);
else
val = parseUnquotedString(pld);
if (val == nil)
{
RELEASE(key);
return nil;
}
if (skipSpace(pld) == NO)
{
pld->err = @"missing final semicolon";
RELEASE(key);
RELEASE(val);
return nil;
}
(*plSet)(dict, @selector(setObject:forKey:), val, key);
RELEASE(key);
RELEASE(val);
if (pld->ptr[pld->pos] == ';')
pld->pos++;
else
{
pld->err = @"unexpected character (wanted ';')";
RELEASE(dict);
return nil;
}
}
else
{
RELEASE(key);
RELEASE(dict);
pld->err = @"unexpected character (wanted '=' or ';')";
return nil;
}
}
return dict;
}