mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
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:
parent
72e48ac96c
commit
3034011636
6 changed files with 920 additions and 937 deletions
|
@ -4,11 +4,13 @@
|
||||||
implemented to return NSUnicodeStringEncoding. Use new string
|
implemented to return NSUnicodeStringEncoding. Use new string
|
||||||
classes more effectively - let GSString turn itsself into either
|
classes more effectively - let GSString turn itsself into either
|
||||||
GSCString or GSUstring when initialised.
|
GSCString or GSUstring when initialised.
|
||||||
|
Merged in code from propList.h
|
||||||
* Source/GSString.m: ([-dataUsingEncoding:allowLossyConversion:])
|
* Source/GSString.m: ([-dataUsingEncoding:allowLossyConversion:])
|
||||||
bugfixes for cString reported by Freed Kiefer
|
bugfixes for cString reported by Freed Kiefer
|
||||||
Removed 'ascii' flag - more trouble than a minor optimisation is
|
Removed 'ascii' flag - more trouble than a minor optimisation is
|
||||||
worth.
|
worth.
|
||||||
Fixed transmute() to be careful about freeing old string.
|
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>
|
2000-10-21 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
|
|
@ -389,7 +389,12 @@ cString_u(ivars self)
|
||||||
|
|
||||||
if (self->_count > 0)
|
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';
|
r[self->_count] = '\0';
|
||||||
|
|
||||||
|
@ -412,7 +417,12 @@ cStringLength_u(ivars self)
|
||||||
char *r;
|
char *r;
|
||||||
|
|
||||||
r = (char*)NSZoneMalloc(NSDefaultMallocZone(), self->_count+1);
|
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';
|
r[self->_count] = '\0';
|
||||||
c = strlen(r);
|
c = strlen(r);
|
||||||
NSZoneFree(NSDefaultMallocZone(), r);
|
NSZoneFree(NSDefaultMallocZone(), r);
|
||||||
|
@ -452,10 +462,12 @@ dataUsingEncoding_c(ivars self, NSStringEncoding encoding, BOOL flag)
|
||||||
int t;
|
int t;
|
||||||
unichar *buff;
|
unichar *buff;
|
||||||
|
|
||||||
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), 2*len+2);
|
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(),
|
||||||
|
sizeof(unichar)*(len+1));
|
||||||
buff[0] = 0xFEFF;
|
buff[0] = 0xFEFF;
|
||||||
t = encode_strtoustr(buff+1, self->_contents.c, len, defEnc);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -463,16 +475,16 @@ dataUsingEncoding_c(ivars self, NSStringEncoding encoding, BOOL flag)
|
||||||
unichar *ubuff;
|
unichar *ubuff;
|
||||||
unsigned char *buff;
|
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);
|
t = encode_strtoustr(ubuff, self->_contents.c, len, defEnc);
|
||||||
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), t+1);
|
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), t);
|
||||||
if (flag)
|
if (flag)
|
||||||
t = encode_ustrtostr(buff, ubuff, t, encoding);
|
t = encode_ustrtostr(buff, ubuff, t, encoding);
|
||||||
else
|
else
|
||||||
t = encode_ustrtostr_strict(buff, ubuff, t, encoding);
|
t = encode_ustrtostr_strict(buff, ubuff, t, encoding);
|
||||||
buff[t] = '\0';
|
|
||||||
NSZoneFree(NSDefaultMallocZone(), ubuff);
|
NSZoneFree(NSDefaultMallocZone(), ubuff);
|
||||||
if (t != len)
|
if (t == 0)
|
||||||
{
|
{
|
||||||
NSZoneFree(NSDefaultMallocZone(), buff);
|
NSZoneFree(NSDefaultMallocZone(), buff);
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -495,22 +507,23 @@ dataUsingEncoding_u(ivars self, NSStringEncoding encoding, BOOL flag)
|
||||||
{
|
{
|
||||||
unichar *buff;
|
unichar *buff;
|
||||||
|
|
||||||
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(), 2*len+2);
|
buff = (unichar*)NSZoneMalloc(NSDefaultMallocZone(),
|
||||||
|
sizeof(unichar)*(len+1));
|
||||||
buff[0] = 0xFEFF;
|
buff[0] = 0xFEFF;
|
||||||
memcpy(buff+1, self->_contents.u, 2*len);
|
memcpy(buff+1, self->_contents.u, sizeof(unichar)*len);
|
||||||
return [NSData dataWithBytesNoCopy: buff length: 2*len+2];
|
return [NSData dataWithBytesNoCopy: buff
|
||||||
|
length: sizeof(unichar)*(len+1)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
unsigned char *buff;
|
unsigned char *buff;
|
||||||
|
|
||||||
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), len+1);
|
buff = (unsigned char*)NSZoneMalloc(NSDefaultMallocZone(), len);
|
||||||
if (flag == YES)
|
if (flag == YES)
|
||||||
t = encode_ustrtostr(buff, self->_contents.u, len, encoding);
|
t = encode_ustrtostr(buff, self->_contents.u, len, encoding);
|
||||||
else
|
else
|
||||||
t = encode_ustrtostr_strict(buff, self->_contents.u, len, encoding);
|
t = encode_ustrtostr_strict(buff, self->_contents.u, len, encoding);
|
||||||
buff[t] = '\0';
|
|
||||||
if (!t)
|
if (!t)
|
||||||
{
|
{
|
||||||
NSZoneFree(NSDefaultMallocZone(), buff);
|
NSZoneFree(NSDefaultMallocZone(), buff);
|
||||||
|
|
|
@ -231,12 +231,11 @@ $(GNUSTEP_OBJ_DIR)/NSSerializer.o \
|
||||||
#
|
#
|
||||||
# Files that include fast.x will need a rebuild if it is changed.
|
# 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)/NSArchiver.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSArray.o \
|
$(GNUSTEP_OBJ_DIR)/NSArray.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSData.o \
|
$(GNUSTEP_OBJ_DIR)/NSData.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSGCString.o \
|
|
||||||
$(GNUSTEP_OBJ_DIR)/NSGDictionary.o \
|
$(GNUSTEP_OBJ_DIR)/NSGDictionary.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSGString.o \
|
|
||||||
$(GNUSTEP_OBJ_DIR)/NSInvocation.o \
|
$(GNUSTEP_OBJ_DIR)/NSInvocation.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSObjCRuntime.o \
|
$(GNUSTEP_OBJ_DIR)/NSObjCRuntime.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSObject.o \
|
$(GNUSTEP_OBJ_DIR)/NSObject.o \
|
||||||
|
@ -245,20 +244,11 @@ $(GNUSTEP_OBJ_DIR)/NSString.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSUnarchiver.o \
|
$(GNUSTEP_OBJ_DIR)/NSUnarchiver.o \
|
||||||
: $(HEADER_DIR)/fast.x
|
: $(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.
|
# Files that include GSeq.h will need a rebuild if it is changed.
|
||||||
#
|
#
|
||||||
$(GNUSTEP_OBJ_DIR)/NSString.o \
|
$(GNUSTEP_OBJ_DIR)/NSString.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSGString.o \
|
$(GNUSTEP_OBJ_DIR)/GSString.o \
|
||||||
$(GNUSTEP_OBJ_DIR)/NSGCString.o \
|
|
||||||
: GSeq.h
|
: GSeq.h
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -339,13 +339,14 @@ iconv_strtoustr(unichar *u2, int size2, const char *s1, int size1, NSStringEncod
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
iconv_t conv;
|
||||||
int usize = sizeof(unichar)*size1;
|
int usize = sizeof(unichar)*size1;
|
||||||
char *s1 = s2;
|
char *s1 = s2;
|
||||||
const char *u2 = (const char*)u1;
|
const char *u2 = (const char*)u1;
|
||||||
int ret_val;
|
int ret_val;
|
||||||
|
|
||||||
conv = iconv_open(iconv_stringforencoding(enc), UNICODE_ENC);
|
conv = iconv_open(iconv_stringforencoding(enc), UNICODE_ENC);
|
||||||
if (conv == (iconv_t)-1)
|
if (conv == (iconv_t)-1)
|
||||||
|
@ -867,7 +868,7 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
if (u < 128)
|
if (u < 128)
|
||||||
s2[count] = (char)u;
|
s2[count] = (char)u;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
@ -878,7 +879,7 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
if (u < 128)
|
if (u < 128)
|
||||||
s2[count] = (char)u;
|
s2[count] = (char)u;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
@ -890,7 +891,7 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
if (u < 256)
|
if (u < 256)
|
||||||
s2[count] = (char)u;
|
s2[count] = (char)u;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
@ -906,11 +907,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (((res = u - Next_uni_to_char_table[i++].from) > 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)
|
if (!res)
|
||||||
s2[count] = Next_uni_to_char_table[--i].to;
|
s2[count] = Next_uni_to_char_table[--i].to;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -927,11 +928,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (((res = u - Cyrillic_uni_to_char_table[i++].from) > 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)
|
if (!res)
|
||||||
s2[count] = Cyrillic_uni_to_char_table[--i].to;
|
s2[count] = Cyrillic_uni_to_char_table[--i].to;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -948,11 +949,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (((res = u - Latin2_uni_to_char_table[i++].from) > 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)
|
if (!res)
|
||||||
s2[count] = Latin2_uni_to_char_table[--i].to;
|
s2[count] = Latin2_uni_to_char_table[--i].to;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -970,11 +971,11 @@ encode_ustrtostr_strict(char *s2, unichar *u1, int size, NSStringEncoding enc)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while (((res = u - Symbol_uni_to_char_table[i++].from) > 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)
|
if (!res)
|
||||||
s2[count] = Symbol_uni_to_char_table[--i].to;
|
s2[count] = Symbol_uni_to_char_table[--i].to;
|
||||||
else
|
else
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue