mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-11 08:40:44 +00:00
Property list updates.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14966 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
22bed19361
commit
15210c5f59
8 changed files with 641 additions and 682 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2002-11-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Headers/gnustep/base/NSObject.h: Removed GNUstep plist extensions.
|
||||||
|
* Source/NSObject.m: ditto.
|
||||||
|
* Source/GSCompatibility.m: Implement new plist generator.
|
||||||
|
* Source/NSArray.m: Use new plist code
|
||||||
|
* Source/NSData.m: ditto
|
||||||
|
* Source/NSDictionary.m: ditto
|
||||||
|
* Source/NSString.m: ditto
|
||||||
|
Remove GNUstep property list extensions from the api ... make more
|
||||||
|
like MacOS and OpenStep spec by having a central mechanism for
|
||||||
|
generating property lists rather than spreading the code across the
|
||||||
|
plist classes.
|
||||||
|
|
||||||
2002-11-09 Richard Frith-Macdonald <rfm@gnu.org>
|
2002-11-09 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSObject.m: use NSString implementation of
|
* Source/NSObject.m: use NSString implementation of
|
||||||
|
|
|
@ -252,40 +252,8 @@ enum {NSNotFound = 0x7fffffff};
|
||||||
creating the potential for deadlock. */
|
creating the potential for deadlock. */
|
||||||
GS_EXPORT NSRecursiveLock *gnustep_global_lock;
|
GS_EXPORT NSRecursiveLock *gnustep_global_lock;
|
||||||
|
|
||||||
/*
|
|
||||||
* The GNUDescriptionDestination protocol declares methods used to
|
|
||||||
* append a property-list description string to some output destination
|
|
||||||
* so that property-lists can be converted to strings in a stream avoiding
|
|
||||||
* the use of ridiculous amounts of memory for deeply nested data structures.
|
|
||||||
*/
|
|
||||||
@protocol GNUDescriptionDestination
|
|
||||||
- (void) appendFormat: (NSString*)str, ...;
|
|
||||||
- (void) appendString: (NSString*)str;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSObject (GNU)
|
@interface NSObject (GNU)
|
||||||
- (NSComparisonResult) compare: (id)anObject;
|
- (NSComparisonResult) compare: (id)anObject;
|
||||||
/*
|
|
||||||
* Default description methods -
|
|
||||||
* [descriptionWithLocale:] calls [description]
|
|
||||||
* [descriptionWithLocale:indent:] calls [descriptionWithLocale:]
|
|
||||||
* [descriptionWithLocale:indent:to:] calls [descriptionWithLocale:indent:]
|
|
||||||
* So - to have working descriptions, it is only necessary to implement the
|
|
||||||
* [description] method, and to have efficient property-list generation, it
|
|
||||||
* is necessary to override [descriptionWithLocale:indent:to:]
|
|
||||||
*/
|
|
||||||
- (NSString*) descriptionWithLocale: (NSDictionary*)aLocale;
|
|
||||||
+ (NSString*) descriptionWithLocale: (NSDictionary*)aLocale;
|
|
||||||
- (NSString*) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned)level;
|
|
||||||
+ (NSString*) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned)level;
|
|
||||||
- (void) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned)level
|
|
||||||
to: (id<GNUDescriptionDestination>)output;
|
|
||||||
+ (void) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned)level
|
|
||||||
to: (id<GNUDescriptionDestination>)output;
|
|
||||||
- (id) makeImmutableCopyOnFail: (BOOL)force;
|
- (id) makeImmutableCopyOnFail: (BOOL)force;
|
||||||
- (Class) transmuteClassTo: (Class)aClassObject;
|
- (Class) transmuteClassTo: (Class)aClassObject;
|
||||||
- (id) subclassResponsibility: (SEL)aSel;
|
- (id) subclassResponsibility: (SEL)aSel;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include "GSPrivate.h"
|
#include "GSPrivate.h"
|
||||||
|
|
||||||
|
@class GSMutableString;
|
||||||
|
|
||||||
#ifndef HAVE_RINT
|
#ifndef HAVE_RINT
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
static double rint(double a)
|
static double rint(double a)
|
||||||
|
@ -112,28 +114,144 @@ encodeBase64(NSData *source)
|
||||||
initWithCStringNoCopy: dBuf length: destlen-1 freeWhenDone: YES];
|
initWithCStringNoCopy: dBuf length: destlen-1 freeWhenDone: YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSCharacterSet *quotables = nil;
|
static NSCharacterSet *xmlQuotables = nil;
|
||||||
|
static NSCharacterSet *plQuotables = nil;
|
||||||
|
static NSCharacterSet *oldPlQuotables = nil;
|
||||||
|
static unsigned const char *plQuotablesBitmapRep = NULL;
|
||||||
|
#define GS_IS_QUOTABLE(X) IS_BIT_SET(plQuotablesBitmapRep[(X)/8], (X) % 8)
|
||||||
|
|
||||||
static void setupQuotables(void)
|
static inline void Append(NSString *src, GSMutableString *dst)
|
||||||
{
|
{
|
||||||
if (quotables == nil)
|
[(NSMutableString*)dst appendString: src];
|
||||||
{
|
}
|
||||||
NSMutableCharacterSet *s;
|
|
||||||
|
|
||||||
s = [[NSCharacterSet characterSetWithCharactersInString:
|
static void
|
||||||
@"&<>'\\\""] mutableCopy];
|
PString(NSString *obj, GSMutableString *output)
|
||||||
[s addCharactersInRange: NSMakeRange(0x0001, 0x001f)];
|
{
|
||||||
[s removeCharactersInRange: NSMakeRange(0x0009, 0x0002)];
|
unsigned length;
|
||||||
[s removeCharactersInRange: NSMakeRange(0x000D, 0x0001)];
|
|
||||||
[s addCharactersInRange: NSMakeRange(0xD800, 0x07FF)];
|
if ((length = [obj length]) == 0)
|
||||||
[s addCharactersInRange: NSMakeRange(0xFFFE, 0x0002)];
|
{
|
||||||
quotables = [s copy];
|
Append(@"\"\"", output);
|
||||||
RELEASE(s);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([obj rangeOfCharacterFromSet: oldPlQuotables].length > 0
|
||||||
|
|| [obj characterAtIndex: 0] == '/')
|
||||||
|
{
|
||||||
|
unichar tmp[length <= 1024 ? length : 0];
|
||||||
|
unichar *ustring;
|
||||||
|
unichar *from;
|
||||||
|
unichar *end;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
if (length <= 1024)
|
||||||
|
{
|
||||||
|
ustring = tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ustring = NSZoneMalloc(NSDefaultMallocZone(), length*sizeof(unichar));
|
||||||
|
}
|
||||||
|
end = &ustring[length];
|
||||||
|
[obj getCharacters: ustring];
|
||||||
|
for (from = ustring; from < end; from++)
|
||||||
|
{
|
||||||
|
switch (*from)
|
||||||
|
{
|
||||||
|
case '\a':
|
||||||
|
case '\b':
|
||||||
|
case '\t':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\v':
|
||||||
|
case '\f':
|
||||||
|
case '\\':
|
||||||
|
case '\'' :
|
||||||
|
case '"' :
|
||||||
|
len += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (*from < 128)
|
||||||
|
{
|
||||||
|
if (isprint(*from) || *from == ' ')
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len += 6;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buf[len+3];
|
||||||
|
char *ptr = buf;
|
||||||
|
|
||||||
|
*ptr++ = '"';
|
||||||
|
for (from = ustring; from < end; from++)
|
||||||
|
{
|
||||||
|
switch (*from)
|
||||||
|
{
|
||||||
|
case '\a': *ptr++ = '\\'; *ptr++ = 'a'; break;
|
||||||
|
case '\b': *ptr++ = '\\'; *ptr++ = 'b'; break;
|
||||||
|
case '\t': *ptr++ = '\\'; *ptr++ = 't'; break;
|
||||||
|
case '\r': *ptr++ = '\\'; *ptr++ = 'r'; break;
|
||||||
|
case '\n': *ptr++ = '\\'; *ptr++ = 'n'; break;
|
||||||
|
case '\v': *ptr++ = '\\'; *ptr++ = 'v'; break;
|
||||||
|
case '\f': *ptr++ = '\\'; *ptr++ = 'f'; break;
|
||||||
|
case '\\': *ptr++ = '\\'; *ptr++ = '\\'; break;
|
||||||
|
case '\'': *ptr++ = '\\'; *ptr++ = '\''; break;
|
||||||
|
case '"' : *ptr++ = '\\'; *ptr++ = '"'; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (*from < 128)
|
||||||
|
{
|
||||||
|
if (isprint(*from) || *from == ' ')
|
||||||
|
{
|
||||||
|
*ptr++ = *from;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(ptr, "\\%03o", *(unsigned char*)from);
|
||||||
|
ptr = &ptr[4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(ptr, "\\u%04x", *from);
|
||||||
|
ptr = &ptr[6];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ptr++ = '"';
|
||||||
|
*ptr = '\0';
|
||||||
|
obj = [[NSString alloc] initWithCString: buf];
|
||||||
|
Append(obj, output);
|
||||||
|
RELEASE(obj);
|
||||||
|
}
|
||||||
|
if (length > 1024)
|
||||||
|
{
|
||||||
|
NSZoneFree(NSDefaultMallocZone(), ustring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(obj, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString*
|
static void
|
||||||
XMLString(NSString* obj)
|
XString(NSString* obj, GSMutableString *output)
|
||||||
{
|
{
|
||||||
static char *hexdigits = "0123456789ABCDEF";
|
static char *hexdigits = "0123456789ABCDEF";
|
||||||
unsigned end;
|
unsigned end;
|
||||||
|
@ -141,15 +259,10 @@ XMLString(NSString* obj)
|
||||||
end = [obj length];
|
end = [obj length];
|
||||||
if (end == 0)
|
if (end == 0)
|
||||||
{
|
{
|
||||||
return obj;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quotables == nil)
|
if ([obj rangeOfCharacterFromSet: xmlQuotables].length > 0)
|
||||||
{
|
|
||||||
setupQuotables();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([obj rangeOfCharacterFromSet: quotables].length > 0)
|
|
||||||
{
|
{
|
||||||
unichar *base;
|
unichar *base;
|
||||||
unichar *map;
|
unichar *map;
|
||||||
|
@ -294,43 +407,68 @@ XMLString(NSString* obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NSZoneFree(NSDefaultMallocZone(), base);
|
NSZoneFree(NSDefaultMallocZone(), base);
|
||||||
return [NSString stringWithCharacters: map length: len];
|
obj = [[NSString alloc] initWithCharacters: map length: len];
|
||||||
|
Append(obj, output);
|
||||||
|
RELEASE(obj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return obj;
|
Append(obj, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString *indentStrings[] = {
|
static NSString *indentStrings[] = {
|
||||||
@"",
|
@"",
|
||||||
|
@" ",
|
||||||
@" ",
|
@" ",
|
||||||
|
@" ",
|
||||||
@"\t",
|
@"\t",
|
||||||
|
@"\t ",
|
||||||
@"\t ",
|
@"\t ",
|
||||||
|
@"\t ",
|
||||||
@"\t\t",
|
@"\t\t",
|
||||||
|
@"\t\t ",
|
||||||
@"\t\t ",
|
@"\t\t ",
|
||||||
|
@"\t\t ",
|
||||||
@"\t\t\t",
|
@"\t\t\t",
|
||||||
|
@"\t\t\t ",
|
||||||
@"\t\t\t ",
|
@"\t\t\t ",
|
||||||
|
@"\t\t\t ",
|
||||||
@"\t\t\t\t",
|
@"\t\t\t\t",
|
||||||
|
@"\t\t\t\t ",
|
||||||
@"\t\t\t\t ",
|
@"\t\t\t\t ",
|
||||||
|
@"\t\t\t\t ",
|
||||||
@"\t\t\t\t\t",
|
@"\t\t\t\t\t",
|
||||||
|
@"\t\t\t\t\t ",
|
||||||
@"\t\t\t\t\t ",
|
@"\t\t\t\t\t ",
|
||||||
|
@"\t\t\t\t\t ",
|
||||||
@"\t\t\t\t\t\t"
|
@"\t\t\t\t\t\t"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* obj is the object to be written out<br />
|
||||||
|
* loc is the locale for formatting (or nil to indicate no formatting)<br />
|
||||||
|
* lev is the level of indentation to use<br />
|
||||||
|
* step is the indentation step (0 == 0, 1 = 2, 2 = 4, 3 = 8)<br />
|
||||||
|
* x is a flag to indicate xml property list format<br />
|
||||||
|
* dest is the output buffer.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
XMLPlObject(NSMutableString *dest, id obj, NSDictionary *loc, unsigned lev)
|
OAppend(id obj, NSDictionary *loc, unsigned lev, unsigned step,
|
||||||
|
BOOL x, GSMutableString *dest)
|
||||||
{
|
{
|
||||||
if (lev >= sizeof(indentStrings) / sizeof(*indentStrings))
|
|
||||||
lev = sizeof(indentStrings) / sizeof(*indentStrings) - 1;
|
|
||||||
|
|
||||||
[dest appendString: indentStrings[lev]];
|
|
||||||
|
|
||||||
if ([obj isKindOfClass: [NSString class]])
|
if ([obj isKindOfClass: [NSString class]])
|
||||||
{
|
{
|
||||||
[dest appendString: @"<string>"];
|
if (x == YES)
|
||||||
[dest appendString: XMLString(obj)];
|
{
|
||||||
[dest appendString: @"</string>\n"];
|
Append(@"<string>", dest);
|
||||||
|
XString(obj, dest);
|
||||||
|
Append(@"</string>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PString(obj, dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([obj isKindOfClass: [NSNumber class]])
|
else if ([obj isKindOfClass: [NSNumber class]])
|
||||||
{
|
{
|
||||||
|
@ -338,98 +476,463 @@ XMLPlObject(NSMutableString *dest, id obj, NSDictionary *loc, unsigned lev)
|
||||||
|
|
||||||
if (val == 1.0)
|
if (val == 1.0)
|
||||||
{
|
{
|
||||||
[dest appendString: @"<true/>\n"];
|
if (x)
|
||||||
|
{
|
||||||
|
Append(@"<true/>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(@"YES", dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (val == 0.0)
|
else if (val == 0.0)
|
||||||
{
|
{
|
||||||
[dest appendString: @"<false/>\n"];
|
if (x)
|
||||||
|
{
|
||||||
|
Append(@"<false/>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(@"NO", dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (rint(val) == val)
|
else if (rint(val) == val)
|
||||||
{
|
{
|
||||||
[dest appendString: @"<integer>"];
|
if (x == YES)
|
||||||
[dest appendString: [obj stringValue]];
|
{
|
||||||
[dest appendString: @"</integer>\n"];
|
Append(@"<integer>", dest);
|
||||||
|
XString([obj stringValue], dest);
|
||||||
|
Append(@"</integer>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PString([obj stringValue], dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[dest appendString: @"<real>"];
|
if (x == YES)
|
||||||
[dest appendString: [obj stringValue]];
|
{
|
||||||
[dest appendString: @"</real>\n"];
|
Append(@"<real>", dest);
|
||||||
|
XString([obj stringValue], dest);
|
||||||
|
Append(@"</real>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PString([obj stringValue], dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ([obj isKindOfClass: [NSData class]])
|
else if ([obj isKindOfClass: [NSData class]])
|
||||||
{
|
{
|
||||||
[dest appendString: @"<data>"];
|
if (x == YES)
|
||||||
[dest appendString: encodeBase64(obj)];
|
{
|
||||||
[dest appendString: @"</data>\n"];
|
Append(@"<data>", dest);
|
||||||
|
Append(encodeBase64(obj), dest);
|
||||||
|
Append(@"</data>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString *str;
|
||||||
|
const char *src;
|
||||||
|
char *dst;
|
||||||
|
int length;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
NSZone *z = NSDefaultMallocZone();
|
||||||
|
|
||||||
|
src = [obj bytes];
|
||||||
|
length = [obj length];
|
||||||
|
#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57))
|
||||||
|
|
||||||
|
dst = (char*) NSZoneMalloc(z, 2*length+length/4+3);
|
||||||
|
dst[0] = '<';
|
||||||
|
for (i = 0, j = 1; i < length; i++, j++)
|
||||||
|
{
|
||||||
|
dst[j++] = num2char((src[i]>>4) & 0x0f);
|
||||||
|
dst[j] = num2char(src[i] & 0x0f);
|
||||||
|
if ((i&0x3) == 3 && i != length-1)
|
||||||
|
{
|
||||||
|
/* if we've just finished a 32-bit int, print a space */
|
||||||
|
dst[++j] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst[j++] = '>';
|
||||||
|
dst[j] = '\0';
|
||||||
|
str = [[NSString allocWithZone: z] initWithCStringNoCopy: dst
|
||||||
|
length: j
|
||||||
|
freeWhenDone: YES];
|
||||||
|
Append(str, dest);
|
||||||
|
RELEASE(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([obj isKindOfClass: [NSDate class]])
|
else if ([obj isKindOfClass: [NSDate class]])
|
||||||
{
|
{
|
||||||
[dest appendString: @"<date>"];
|
if (x == YES)
|
||||||
[dest appendString:
|
{
|
||||||
[obj descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"]];
|
Append(@"<date>", dest);
|
||||||
[dest appendString: @"</date>\n"];
|
Append([obj descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"],
|
||||||
|
dest);
|
||||||
|
Append(@"</date>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PString([obj descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %z"],
|
||||||
|
dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([obj isKindOfClass: [NSArray class]])
|
else if ([obj isKindOfClass: [NSArray class]])
|
||||||
{
|
{
|
||||||
NSEnumerator *e;
|
NSString *iBaseString;
|
||||||
|
NSString *iSizeString;
|
||||||
|
unsigned level = lev;
|
||||||
|
|
||||||
[dest appendString: @"<array>\n"];
|
if (level*step < sizeof(indentStrings)/sizeof(id))
|
||||||
e = [obj objectEnumerator];
|
{
|
||||||
while ((obj = [e nextObject]))
|
iBaseString = indentStrings[level*step];
|
||||||
{
|
}
|
||||||
XMLPlObject(dest, obj, loc, lev + 1);
|
else
|
||||||
}
|
{
|
||||||
[dest appendString: indentStrings[lev]];
|
iBaseString
|
||||||
[dest appendString: @"</array>\n"];
|
= indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
||||||
|
}
|
||||||
|
level++;
|
||||||
|
if (level*step < sizeof(indentStrings)/sizeof(id))
|
||||||
|
{
|
||||||
|
iSizeString = indentStrings[level*step];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iSizeString
|
||||||
|
= indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == YES)
|
||||||
|
{
|
||||||
|
NSEnumerator *e;
|
||||||
|
|
||||||
|
Append(@"<array>", dest);
|
||||||
|
e = [obj objectEnumerator];
|
||||||
|
while ((obj = [e nextObject]))
|
||||||
|
{
|
||||||
|
Append(iSizeString, dest);
|
||||||
|
OAppend(obj, loc, level, step, YES, dest);
|
||||||
|
}
|
||||||
|
Append(iBaseString, dest);
|
||||||
|
Append(@"</array>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned count = [obj count];
|
||||||
|
unsigned last = count - 1;
|
||||||
|
NSString *plists[count];
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
[obj getObjects: plists];
|
||||||
|
|
||||||
|
if (loc == nil)
|
||||||
|
{
|
||||||
|
Append(@"(", dest);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
id item = plists[i];
|
||||||
|
|
||||||
|
OAppend(item, nil, 0, step, NO, dest);
|
||||||
|
if (i != last)
|
||||||
|
{
|
||||||
|
Append(@", ", dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Append(@")", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(@"(\n", dest);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
id item = plists[i];
|
||||||
|
|
||||||
|
Append(iSizeString, dest);
|
||||||
|
OAppend(item, loc, level, step, NO, dest);
|
||||||
|
if (i == last)
|
||||||
|
{
|
||||||
|
Append(@"\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(@",\n", dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Append(iBaseString, dest);
|
||||||
|
Append(@")", dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ([obj isKindOfClass: [NSDictionary class]])
|
else if ([obj isKindOfClass: [NSDictionary class]])
|
||||||
{
|
{
|
||||||
NSEnumerator *e;
|
NSString *iBaseString;
|
||||||
id key;
|
NSString *iSizeString;
|
||||||
unsigned nxt = lev + 1;
|
unsigned level = lev;
|
||||||
|
|
||||||
if (lev >= sizeof(indentStrings) / sizeof(*indentStrings))
|
if (level*step < sizeof(indentStrings)/sizeof(id))
|
||||||
lev = sizeof(indentStrings) / sizeof(*indentStrings) - 1;
|
{
|
||||||
|
iBaseString = indentStrings[level*step];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iBaseString
|
||||||
|
= indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
||||||
|
}
|
||||||
|
level++;
|
||||||
|
if (level*step < sizeof(indentStrings)/sizeof(id))
|
||||||
|
{
|
||||||
|
iSizeString = indentStrings[level*step];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iSizeString
|
||||||
|
= indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
||||||
|
}
|
||||||
|
|
||||||
[dest appendString: @"<dict>\n"];
|
if (x == YES)
|
||||||
e = [obj keyEnumerator];
|
{
|
||||||
while ((key = [e nextObject]))
|
NSEnumerator *e;
|
||||||
{
|
id key;
|
||||||
id val;
|
|
||||||
|
|
||||||
val = [obj objectForKey: key];
|
Append(@"<dict>\n", dest);
|
||||||
[dest appendString: indentStrings[nxt]];
|
e = [obj keyEnumerator];
|
||||||
[dest appendString: @"<key>"];
|
while ((key = [e nextObject]))
|
||||||
[dest appendString: XMLString(key)];
|
{
|
||||||
[dest appendString: @"</key>\n"];
|
id val;
|
||||||
XMLPlObject(dest, val, loc, nxt);
|
|
||||||
}
|
val = [obj objectForKey: key];
|
||||||
[dest appendString: indentStrings[lev]];
|
Append(iSizeString, dest);
|
||||||
[dest appendString: @"</dict>\n"];
|
Append(@"<key>", dest);
|
||||||
|
XString(key, dest);
|
||||||
|
Append(@"</key>\n", dest);
|
||||||
|
OAppend(val, loc, level, step, YES, dest);
|
||||||
|
}
|
||||||
|
Append(iBaseString, dest);
|
||||||
|
Append(@"</dict>\n", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SEL objSel = @selector(objectForKey:);
|
||||||
|
IMP myObj = [obj methodForSelector: objSel];
|
||||||
|
unsigned i;
|
||||||
|
NSArray *keyArray = [obj allKeys];
|
||||||
|
unsigned numKeys = [keyArray count];
|
||||||
|
NSString *plists[numKeys];
|
||||||
|
NSString *keys[numKeys];
|
||||||
|
|
||||||
|
[keyArray getObjects: keys];
|
||||||
|
|
||||||
|
if (loc == nil)
|
||||||
|
{
|
||||||
|
for (i = 0; i < numKeys; i++)
|
||||||
|
{
|
||||||
|
plists[i] = (*myObj)(obj, objSel, keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Append(@"{", dest);
|
||||||
|
for (i = 0; i < numKeys; i++)
|
||||||
|
{
|
||||||
|
OAppend(keys[i], nil, 0, step, NO, dest);
|
||||||
|
Append(@" = ", dest);
|
||||||
|
OAppend(plists[i], nil, 0, step, NO, dest);
|
||||||
|
Append(@"; ", dest);
|
||||||
|
}
|
||||||
|
Append(@"}", dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOL canCompare = YES;
|
||||||
|
Class lastClass = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < numKeys; i++)
|
||||||
|
{
|
||||||
|
if (GSObjCClass(keys[i]) == lastClass)
|
||||||
|
continue;
|
||||||
|
if ([keys[i] respondsToSelector: @selector(compare:)] == NO)
|
||||||
|
{
|
||||||
|
canCompare = NO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastClass = GSObjCClass(keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canCompare == YES)
|
||||||
|
{
|
||||||
|
#define STRIDE_FACTOR 3
|
||||||
|
unsigned c,d, stride;
|
||||||
|
BOOL found;
|
||||||
|
NSComparisonResult (*comp)(id, SEL, id) = 0;
|
||||||
|
int count = numKeys;
|
||||||
|
#ifdef GSWARN
|
||||||
|
BOOL badComparison = NO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
stride = 1;
|
||||||
|
while (stride <= count)
|
||||||
|
{
|
||||||
|
stride = stride * STRIDE_FACTOR + 1;
|
||||||
|
}
|
||||||
|
lastClass = 0;
|
||||||
|
while (stride > (STRIDE_FACTOR - 1))
|
||||||
|
{
|
||||||
|
// loop to sort for each value of stride
|
||||||
|
stride = stride / STRIDE_FACTOR;
|
||||||
|
for (c = stride; c < count; c++)
|
||||||
|
{
|
||||||
|
found = NO;
|
||||||
|
if (stride > c)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
d = c - stride;
|
||||||
|
while (!found)
|
||||||
|
{
|
||||||
|
id a = keys[d + stride];
|
||||||
|
id b = keys[d];
|
||||||
|
Class x;
|
||||||
|
NSComparisonResult r;
|
||||||
|
|
||||||
|
x = GSObjCClass(a);
|
||||||
|
if (x != lastClass)
|
||||||
|
{
|
||||||
|
lastClass = x;
|
||||||
|
comp = (NSComparisonResult (*)(id, SEL, id))
|
||||||
|
[a methodForSelector: @selector(compare:)];
|
||||||
|
}
|
||||||
|
r = (*comp)(a, @selector(compare:), b);
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
#ifdef GSWARN
|
||||||
|
if (r != NSOrderedAscending)
|
||||||
|
{
|
||||||
|
badComparison = YES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
keys[d + stride] = b;
|
||||||
|
keys[d] = a;
|
||||||
|
if (stride > d)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
d -= stride;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef GSWARN
|
||||||
|
if (r != NSOrderedDescending
|
||||||
|
&& r != NSOrderedSame)
|
||||||
|
{
|
||||||
|
badComparison = YES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
found = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef GSWARN
|
||||||
|
if (badComparison == YES)
|
||||||
|
{
|
||||||
|
NSWarnFLog(@"Detected bad return value from comparison");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numKeys; i++)
|
||||||
|
{
|
||||||
|
plists[i] = (*myObj)(obj, objSel, keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Append(@"{\n", dest);
|
||||||
|
for (i = 0; i < numKeys; i++)
|
||||||
|
{
|
||||||
|
Append(iSizeString, dest);
|
||||||
|
OAppend(keys[i], loc, level, step, NO, dest);
|
||||||
|
Append(@" = ", dest);
|
||||||
|
OAppend(plists[i], loc, level, step, NO, dest);
|
||||||
|
Append(@";\n", dest);
|
||||||
|
}
|
||||||
|
Append(iBaseString, dest);
|
||||||
|
Append(@"}", dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSLog(@"Non-property-list class encoded as string");
|
NSLog(@"Non-property-list class encoded as string");
|
||||||
[dest appendString: @"<string>"];
|
Append(@"<string>", dest);
|
||||||
[dest appendString: [obj description]];
|
Append([obj description], dest);
|
||||||
[dest appendString: @"</string>\n"];
|
Append(@"</string>\n", dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString*
|
void
|
||||||
GSXMLPlMake(id obj, NSDictionary *loc)
|
GSPropertyListMake(id obj, NSDictionary *loc, BOOL xml, unsigned step, id *str)
|
||||||
{
|
{
|
||||||
NSMutableString *dest;
|
GSMutableString *dest;
|
||||||
|
|
||||||
dest = [NSMutableString stringWithCString:
|
if (plQuotablesBitmapRep == NULL)
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist "
|
{
|
||||||
"PUBLIC \"-//GNUstep//DTD plist 0.9//EN\" "
|
NSMutableCharacterSet *s;
|
||||||
"\"http://www.gnustep.org/plist-0_9.xml\">\n"
|
NSData *bitmap;
|
||||||
"<plist version=\"0.9\">\n"];
|
|
||||||
|
|
||||||
XMLPlObject(dest, obj, loc, 0);
|
s = [[NSCharacterSet characterSetWithCharactersInString:
|
||||||
[dest appendString: @"</plist>"];
|
@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
return dest;
|
@"abcdefghijklmnopqrstuvwxyz!#$%&*+-./:?@|~_^"]
|
||||||
|
mutableCopy];
|
||||||
|
[s invert];
|
||||||
|
plQuotables = [s copy];
|
||||||
|
RELEASE(s);
|
||||||
|
bitmap = RETAIN([plQuotables bitmapRepresentation]);
|
||||||
|
plQuotablesBitmapRep = [bitmap bytes];
|
||||||
|
s = [[NSCharacterSet characterSetWithCharactersInString:
|
||||||
|
@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
@"abcdefghijklmnopqrstuvwxyz$./_"]
|
||||||
|
mutableCopy];
|
||||||
|
[s invert];
|
||||||
|
oldPlQuotables = [s copy];
|
||||||
|
RELEASE(s);
|
||||||
|
|
||||||
|
s = [[NSCharacterSet characterSetWithCharactersInString:
|
||||||
|
@"&<>'\\\""] mutableCopy];
|
||||||
|
[s addCharactersInRange: NSMakeRange(0x0001, 0x001f)];
|
||||||
|
[s removeCharactersInRange: NSMakeRange(0x0009, 0x0002)];
|
||||||
|
[s removeCharactersInRange: NSMakeRange(0x000D, 0x0001)];
|
||||||
|
[s addCharactersInRange: NSMakeRange(0xD800, 0x07FF)];
|
||||||
|
[s addCharactersInRange: NSMakeRange(0xFFFE, 0x0002)];
|
||||||
|
xmlQuotables = [s copy];
|
||||||
|
RELEASE(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*str == nil)
|
||||||
|
{
|
||||||
|
*str = AUTORELEASE([GSMutableString new]);
|
||||||
|
}
|
||||||
|
else if (GSObjCClass(*str) != [GSMutableString class])
|
||||||
|
{
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"Illegal object (%@) at argument 0", *str];
|
||||||
|
}
|
||||||
|
dest = *str;
|
||||||
|
|
||||||
|
if (xml == YES)
|
||||||
|
{
|
||||||
|
Append([NSMutableString stringWithCString:
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist "
|
||||||
|
"PUBLIC \"-//GNUstep//DTD plist 0.9//EN\" "
|
||||||
|
"\"http://www.gnustep.org/plist-0_9.xml\">\n"
|
||||||
|
"<plist version=\"0.9\">\n"], dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
OAppend(obj, loc, 0, step > 3 ? 3 : step, xml, dest);
|
||||||
|
if (xml == YES)
|
||||||
|
{
|
||||||
|
Append(@"</plist>", dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
138
Source/NSArray.m
138
Source/NSArray.m
|
@ -47,6 +47,7 @@
|
||||||
#include "GSPrivate.h"
|
#include "GSPrivate.h"
|
||||||
|
|
||||||
extern BOOL GSMacOSXCompatiblePropertyLists(void);
|
extern BOOL GSMacOSXCompatiblePropertyLists(void);
|
||||||
|
extern void GSPropertyListMake(id, NSDictionary*, BOOL, unsigned, id*);
|
||||||
|
|
||||||
@class NSArrayEnumerator;
|
@class NSArrayEnumerator;
|
||||||
@class NSArrayEnumeratorReverse;
|
@class NSArrayEnumeratorReverse;
|
||||||
|
@ -977,106 +978,13 @@ static int compare(id elem1, id elem2, void* context)
|
||||||
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
|
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
|
||||||
indent: (unsigned int)level
|
indent: (unsigned int)level
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
NSString *result = nil;
|
||||||
|
|
||||||
|
GSPropertyListMake(self, locale, NO, level == 1 ? 3 : 2, &result);
|
||||||
|
|
||||||
result = [[NSMutableString alloc] initWithCapacity: 20*[self count]];
|
|
||||||
result = AUTORELEASE(result);
|
|
||||||
[self descriptionWithLocale: locale
|
|
||||||
indent: level
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString *indentStrings[] = {
|
|
||||||
@"",
|
|
||||||
@" ",
|
|
||||||
@"\t",
|
|
||||||
@"\t ",
|
|
||||||
@"\t\t",
|
|
||||||
@"\t\t ",
|
|
||||||
@"\t\t\t",
|
|
||||||
@"\t\t\t ",
|
|
||||||
@"\t\t\t\t",
|
|
||||||
@"\t\t\t\t ",
|
|
||||||
@"\t\t\t\t\t",
|
|
||||||
@"\t\t\t\t\t ",
|
|
||||||
@"\t\t\t\t\t\t"
|
|
||||||
};
|
|
||||||
|
|
||||||
- (void) descriptionWithLocale: (NSDictionary*)locale
|
|
||||||
indent: (unsigned int)level
|
|
||||||
to: (id<GNUDescriptionDestination>)result
|
|
||||||
{
|
|
||||||
unsigned count = [self count];
|
|
||||||
unsigned last = count - 1;
|
|
||||||
NSString *plists[count];
|
|
||||||
unsigned i;
|
|
||||||
IMP appImp;
|
|
||||||
|
|
||||||
appImp = [(NSObject*)result methodForSelector: appSel];
|
|
||||||
|
|
||||||
[self getObjects: plists];
|
|
||||||
|
|
||||||
if (locale == nil)
|
|
||||||
{
|
|
||||||
(*appImp)(result, appSel, @"(");
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
id item = plists[i];
|
|
||||||
|
|
||||||
[item descriptionWithLocale: nil indent: 0 to: result];
|
|
||||||
if (i != last)
|
|
||||||
{
|
|
||||||
(*appImp)(result, appSel, @", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*appImp)(result, appSel, @")");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSString *iBaseString;
|
|
||||||
NSString *iSizeString;
|
|
||||||
|
|
||||||
if (level < sizeof(indentStrings)/sizeof(id))
|
|
||||||
{
|
|
||||||
iBaseString = indentStrings[level];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iBaseString = indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
|
||||||
}
|
|
||||||
level++;
|
|
||||||
if (level < sizeof(indentStrings)/sizeof(id))
|
|
||||||
{
|
|
||||||
iSizeString = indentStrings[level];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iSizeString = indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
(*appImp)(result, appSel, @"(\n");
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
id item = plists[i];
|
|
||||||
|
|
||||||
(*appImp)(result, appSel, iSizeString);
|
|
||||||
|
|
||||||
[item descriptionWithLocale: locale indent: level to: result];
|
|
||||||
if (i == last)
|
|
||||||
{
|
|
||||||
(*appImp)(result, appSel, @"\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(*appImp)(result, appSel, @",\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*appImp)(result, appSel, iBaseString);
|
|
||||||
(*appImp)(result, appSel, @")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Writes the contents of the array to the file specified by path.
|
* <p>Writes the contents of the array to the file specified by path.
|
||||||
* The file contents will be in property-list format ... under GNUstep
|
* The file contents will be in property-list format ... under GNUstep
|
||||||
|
@ -1102,27 +1010,16 @@ static NSString *indentStrings[] = {
|
||||||
*/
|
*/
|
||||||
- (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile
|
- (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile
|
||||||
{
|
{
|
||||||
NSDictionary *loc;
|
NSDictionary *loc = GSUserDefaultsDictionaryRepresentation();
|
||||||
NSString *desc;
|
NSString *desc = nil;
|
||||||
|
|
||||||
loc = GSUserDefaultsDictionaryRepresentation();
|
|
||||||
|
|
||||||
if (GSMacOSXCompatiblePropertyLists() == YES)
|
if (GSMacOSXCompatiblePropertyLists() == YES)
|
||||||
{
|
{
|
||||||
extern NSString *GSXMLPlMake(id obj, NSDictionary *loc);
|
GSPropertyListMake(self, loc, YES, 2, &desc);
|
||||||
|
|
||||||
desc = GSXMLPlMake(self, loc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
GSPropertyListMake(self, loc, NO, 2, &desc);
|
||||||
|
|
||||||
result = [[NSMutableString alloc] initWithCapacity: 20*[self count]];
|
|
||||||
result = AUTORELEASE(result);
|
|
||||||
[self descriptionWithLocale: loc
|
|
||||||
indent: 0
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
desc = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
||||||
|
@ -1137,27 +1034,16 @@ static NSString *indentStrings[] = {
|
||||||
*/
|
*/
|
||||||
- (BOOL) writeToURL: (NSURL *)url atomically: (BOOL)useAuxiliaryFile
|
- (BOOL) writeToURL: (NSURL *)url atomically: (BOOL)useAuxiliaryFile
|
||||||
{
|
{
|
||||||
NSDictionary *loc;
|
NSDictionary *loc = GSUserDefaultsDictionaryRepresentation();
|
||||||
NSString *desc;
|
NSString *desc = nil;
|
||||||
|
|
||||||
loc = GSUserDefaultsDictionaryRepresentation();
|
|
||||||
|
|
||||||
if (GSMacOSXCompatiblePropertyLists() == YES)
|
if (GSMacOSXCompatiblePropertyLists() == YES)
|
||||||
{
|
{
|
||||||
extern NSString *GSXMLPlMake(id obj, NSDictionary *loc);
|
GSPropertyListMake(self, loc, YES, 2, &desc);
|
||||||
|
|
||||||
desc = GSXMLPlMake(self, loc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
GSPropertyListMake(self, loc, NO, 2, &desc);
|
||||||
|
|
||||||
result = [[NSMutableString alloc] initWithCapacity: 20*[self count]];
|
|
||||||
result = AUTORELEASE(result);
|
|
||||||
[self descriptionWithLocale: loc
|
|
||||||
indent: 0
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
desc = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
||||||
|
|
|
@ -678,47 +678,11 @@ failure:
|
||||||
|
|
||||||
- (NSString*) description
|
- (NSString*) description
|
||||||
{
|
{
|
||||||
NSString *str;
|
extern void GSPropertyListMake(id, NSDictionary*, BOOL, unsigned, id*);
|
||||||
const char *src;
|
NSMutableString *result = nil;
|
||||||
char *dest;
|
|
||||||
int length;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
NSZone *z;
|
|
||||||
|
|
||||||
src = [self bytes];
|
GSPropertyListMake(self, nil, NO, 0, &result);
|
||||||
length = [self length];
|
return result;
|
||||||
z = [self zone];
|
|
||||||
#define num2char(num) ((num) < 0xa ? ((num)+'0') : ((num)+0x57))
|
|
||||||
|
|
||||||
/* we can just build a cString and convert it to an NSString */
|
|
||||||
#if GS_WITH_GC
|
|
||||||
dest = (char*) NSZoneMalloc(GSAtomicMallocZone(), 2*length+length/4+3);
|
|
||||||
#else
|
|
||||||
dest = (char*) NSZoneMalloc(z, 2*length+length/4+3);
|
|
||||||
#endif
|
|
||||||
if (dest == 0)
|
|
||||||
{
|
|
||||||
[NSException raise: NSMallocException
|
|
||||||
format: @"No memory for description of NSData object"];
|
|
||||||
}
|
|
||||||
dest[0] = '<';
|
|
||||||
for (i = 0, j = 1; i < length; i++, j++)
|
|
||||||
{
|
|
||||||
dest[j++] = num2char((src[i]>>4) & 0x0f);
|
|
||||||
dest[j] = num2char(src[i] & 0x0f);
|
|
||||||
if ((i&0x3) == 3 && i != length-1)
|
|
||||||
{
|
|
||||||
/* if we've just finished a 32-bit int, print a space */
|
|
||||||
dest[++j] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dest[j++] = '>';
|
|
||||||
dest[j] = '\0';
|
|
||||||
str = [[NSString allocWithZone: z] initWithCStringNoCopy: dest
|
|
||||||
length: j
|
|
||||||
freeWhenDone: YES];
|
|
||||||
return AUTORELEASE(str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,6 +47,8 @@
|
||||||
@class GSMutableDictionary;
|
@class GSMutableDictionary;
|
||||||
|
|
||||||
extern BOOL GSMacOSXCompatiblePropertyLists(void);
|
extern BOOL GSMacOSXCompatiblePropertyLists(void);
|
||||||
|
extern void GSPropertyListMake(id, NSDictionary*, BOOL, unsigned, id*);
|
||||||
|
|
||||||
|
|
||||||
static Class NSArray_class;
|
static Class NSArray_class;
|
||||||
static Class NSDictionaryClass;
|
static Class NSDictionaryClass;
|
||||||
|
@ -740,27 +742,16 @@ compareIt(id o1, id o2, void* context)
|
||||||
*/
|
*/
|
||||||
- (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile
|
- (BOOL) writeToFile: (NSString *)path atomically: (BOOL)useAuxiliaryFile
|
||||||
{
|
{
|
||||||
NSDictionary *loc;
|
NSDictionary *loc = GSUserDefaultsDictionaryRepresentation();
|
||||||
NSString *desc;
|
NSString *desc = nil;
|
||||||
|
|
||||||
loc = GSUserDefaultsDictionaryRepresentation();
|
|
||||||
|
|
||||||
if (GSMacOSXCompatiblePropertyLists() == YES)
|
if (GSMacOSXCompatiblePropertyLists() == YES)
|
||||||
{
|
{
|
||||||
extern NSString *GSXMLPlMake(id obj, NSDictionary *loc);
|
GSPropertyListMake(self, loc, YES, 2, &desc);
|
||||||
|
|
||||||
desc = GSXMLPlMake(self, loc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
GSPropertyListMake(self, loc, NO, 2, &desc);
|
||||||
|
|
||||||
result = AUTORELEASE([[NSMutableString alloc] initWithCapacity:
|
|
||||||
20*[self count]]);
|
|
||||||
[self descriptionWithLocale: loc
|
|
||||||
indent: 0
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
desc = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
||||||
|
@ -775,27 +766,16 @@ compareIt(id o1, id o2, void* context)
|
||||||
*/
|
*/
|
||||||
- (BOOL) writeToURL: (NSURL *)url atomically: (BOOL)useAuxiliaryFile
|
- (BOOL) writeToURL: (NSURL *)url atomically: (BOOL)useAuxiliaryFile
|
||||||
{
|
{
|
||||||
NSDictionary *loc;
|
NSDictionary *loc = GSUserDefaultsDictionaryRepresentation();
|
||||||
NSString *desc;
|
NSString *desc = nil;
|
||||||
|
|
||||||
loc = GSUserDefaultsDictionaryRepresentation();
|
|
||||||
|
|
||||||
if (GSMacOSXCompatiblePropertyLists() == YES)
|
if (GSMacOSXCompatiblePropertyLists() == YES)
|
||||||
{
|
{
|
||||||
extern NSString *GSXMLPlMake(id obj, NSDictionary *loc);
|
GSPropertyListMake(self, loc, YES, 2, &desc);
|
||||||
|
|
||||||
desc = GSXMLPlMake(self, loc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
GSPropertyListMake(self, loc, NO, 2, &desc);
|
||||||
|
|
||||||
result = AUTORELEASE([[NSMutableString alloc] initWithCapacity:
|
|
||||||
20*[self count]]);
|
|
||||||
[self descriptionWithLocale: loc
|
|
||||||
indent: 0
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
desc = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
return [[desc dataUsingEncoding: NSUTF8StringEncoding]
|
||||||
|
@ -809,30 +789,23 @@ compareIt(id o1, id o2, void* context)
|
||||||
|
|
||||||
- (NSString*) descriptionInStringsFileFormat
|
- (NSString*) descriptionInStringsFileFormat
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
NSMutableString *result = nil;
|
||||||
NSEnumerator *enumerator = [self keyEnumerator];
|
NSEnumerator *enumerator = [self keyEnumerator];
|
||||||
IMP nxtObj = [enumerator methodForSelector: nxtSel];
|
IMP nxtObj = [enumerator methodForSelector: nxtSel];
|
||||||
IMP myObj = [self methodForSelector: objSel];
|
IMP myObj = [self methodForSelector: objSel];
|
||||||
IMP appImp;
|
|
||||||
id key;
|
id key;
|
||||||
|
|
||||||
result = AUTORELEASE([[NSMutableString alloc] initWithCapacity: 1024]);
|
|
||||||
appImp = [(NSObject*)result methodForSelector: appSel];
|
|
||||||
while ((key = (*nxtObj)(enumerator, nxtSel)) != nil)
|
while ((key = (*nxtObj)(enumerator, nxtSel)) != nil)
|
||||||
{
|
{
|
||||||
id val = (*myObj)(self, objSel, key);
|
id val = (*myObj)(self, objSel, key);
|
||||||
|
|
||||||
[key descriptionWithLocale: nil
|
GSPropertyListMake(key, nil, NO, 0, &result);
|
||||||
indent: 0
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
if (val != nil && [val isEqualToString: @""] == NO)
|
if (val != nil && [val isEqualToString: @""] == NO)
|
||||||
{
|
{
|
||||||
(*appImp)(result, appSel, @" = ");
|
[result appendString: @" = "];
|
||||||
[val descriptionWithLocale: nil
|
GSPropertyListMake(val, nil, NO, 0, &result);
|
||||||
indent: 0
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
}
|
}
|
||||||
(*appImp)(result, appSel, @";\n");
|
[result appendString: @";\n"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -846,211 +819,12 @@ compareIt(id o1, id o2, void* context)
|
||||||
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
|
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
|
||||||
indent: (unsigned int)level
|
indent: (unsigned int)level
|
||||||
{
|
{
|
||||||
NSMutableString *result;
|
NSMutableString *result = nil;
|
||||||
|
|
||||||
result = AUTORELEASE([[NSMutableString alloc] initWithCapacity:
|
GSPropertyListMake(self, locale, NO, level == 1 ? 3 : 2, &result);
|
||||||
20*[self count]]);
|
|
||||||
[self descriptionWithLocale: locale
|
|
||||||
indent: level
|
|
||||||
to: (id<GNUDescriptionDestination>)result];
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NSString *indentStrings[] = {
|
|
||||||
@"",
|
|
||||||
@" ",
|
|
||||||
@"\t",
|
|
||||||
@"\t ",
|
|
||||||
@"\t\t",
|
|
||||||
@"\t\t ",
|
|
||||||
@"\t\t\t",
|
|
||||||
@"\t\t\t ",
|
|
||||||
@"\t\t\t\t",
|
|
||||||
@"\t\t\t\t ",
|
|
||||||
@"\t\t\t\t\t",
|
|
||||||
@"\t\t\t\t\t ",
|
|
||||||
@"\t\t\t\t\t\t"
|
|
||||||
};
|
|
||||||
|
|
||||||
- (void) descriptionWithLocale: (NSDictionary*)locale
|
|
||||||
indent: (unsigned int)level
|
|
||||||
to: (id<GNUDescriptionDestination>)result
|
|
||||||
{
|
|
||||||
IMP myObj = [self methodForSelector: objSel];
|
|
||||||
unsigned i;
|
|
||||||
NSArray *keyArray = [self allKeys];
|
|
||||||
unsigned numKeys = [keyArray count];
|
|
||||||
NSString *plists[numKeys];
|
|
||||||
NSString *keys[numKeys];
|
|
||||||
IMP appImp;
|
|
||||||
|
|
||||||
appImp = [(NSObject*)result methodForSelector: appSel];
|
|
||||||
|
|
||||||
[keyArray getObjects: keys];
|
|
||||||
|
|
||||||
if (locale == nil)
|
|
||||||
{
|
|
||||||
for (i = 0; i < numKeys; i++)
|
|
||||||
{
|
|
||||||
plists[i] = (*myObj)(self, objSel, keys[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*appImp)(result, appSel, @"{");
|
|
||||||
for (i = 0; i < numKeys; i++)
|
|
||||||
{
|
|
||||||
id o = plists[i];
|
|
||||||
|
|
||||||
[keys[i] descriptionWithLocale: nil indent: 0 to: result];
|
|
||||||
(*appImp)(result, appSel, @" = ");
|
|
||||||
[o descriptionWithLocale: nil indent: 0 to: result];
|
|
||||||
(*appImp)(result, appSel, @"; ");
|
|
||||||
}
|
|
||||||
(*appImp)(result, appSel, @"}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSString *iBaseString;
|
|
||||||
NSString *iSizeString;
|
|
||||||
BOOL canCompare = YES;
|
|
||||||
Class lastClass = 0;
|
|
||||||
|
|
||||||
if (level < sizeof(indentStrings)/sizeof(id))
|
|
||||||
{
|
|
||||||
iBaseString = indentStrings[level];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iBaseString = indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
|
||||||
}
|
|
||||||
level++;
|
|
||||||
if (level < sizeof(indentStrings)/sizeof(id))
|
|
||||||
{
|
|
||||||
iSizeString = indentStrings[level];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iSizeString = indentStrings[sizeof(indentStrings)/sizeof(id)-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numKeys; i++)
|
|
||||||
{
|
|
||||||
if (GSObjCClass(keys[i]) == lastClass)
|
|
||||||
continue;
|
|
||||||
if ([keys[i] respondsToSelector: @selector(compare:)] == NO)
|
|
||||||
{
|
|
||||||
canCompare = NO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastClass = GSObjCClass(keys[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canCompare == YES)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Shell sort algorithm taken from SortingInAction - a NeXT example
|
|
||||||
* good value for stride factor is not well-understood
|
|
||||||
* 3 is a fairly good choice (Sedgewick)
|
|
||||||
*/
|
|
||||||
#define STRIDE_FACTOR 3
|
|
||||||
unsigned c,d, stride;
|
|
||||||
BOOL found;
|
|
||||||
NSComparisonResult (*comp)(id, SEL, id) = 0;
|
|
||||||
int count = numKeys;
|
|
||||||
#ifdef GSWARN
|
|
||||||
BOOL badComparison = NO;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stride = 1;
|
|
||||||
while (stride <= count)
|
|
||||||
{
|
|
||||||
stride = stride * STRIDE_FACTOR + 1;
|
|
||||||
}
|
|
||||||
lastClass = 0;
|
|
||||||
while (stride > (STRIDE_FACTOR - 1))
|
|
||||||
{
|
|
||||||
// loop to sort for each value of stride
|
|
||||||
stride = stride / STRIDE_FACTOR;
|
|
||||||
for (c = stride; c < count; c++)
|
|
||||||
{
|
|
||||||
found = NO;
|
|
||||||
if (stride > c)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
d = c - stride;
|
|
||||||
while (!found) // move to left until correct place
|
|
||||||
{
|
|
||||||
id a = keys[d + stride];
|
|
||||||
id b = keys[d];
|
|
||||||
Class x;
|
|
||||||
NSComparisonResult r;
|
|
||||||
|
|
||||||
x = GSObjCClass(a);
|
|
||||||
if (x != lastClass)
|
|
||||||
{
|
|
||||||
lastClass = x;
|
|
||||||
comp = (NSComparisonResult (*)(id, SEL, id))
|
|
||||||
[a methodForSelector: @selector(compare:)];
|
|
||||||
}
|
|
||||||
r = (*comp)(a, @selector(compare:), b);
|
|
||||||
if (r < 0)
|
|
||||||
{
|
|
||||||
#ifdef GSWARN
|
|
||||||
if (r != NSOrderedAscending)
|
|
||||||
{
|
|
||||||
badComparison = YES;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
keys[d + stride] = b;
|
|
||||||
keys[d] = a;
|
|
||||||
if (stride > d)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
d -= stride; // jump by stride factor
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef GSWARN
|
|
||||||
if (r != NSOrderedDescending && r != NSOrderedSame)
|
|
||||||
{
|
|
||||||
badComparison = YES;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
found = YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef GSWARN
|
|
||||||
if (badComparison == YES)
|
|
||||||
{
|
|
||||||
NSWarnMLog(@"Detected bad return value from comparison");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < numKeys; i++)
|
|
||||||
{
|
|
||||||
plists[i] = (*myObj)(self, objSel, keys[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*appImp)(result, appSel, @"{\n");
|
|
||||||
for (i = 0; i < numKeys; i++)
|
|
||||||
{
|
|
||||||
id o = plists[i];
|
|
||||||
|
|
||||||
(*appImp)(result, appSel, iSizeString);
|
|
||||||
[keys[i] descriptionWithLocale: nil indent: 0 to: result];
|
|
||||||
(*appImp)(result, appSel, @" = ");
|
|
||||||
[o descriptionWithLocale: locale indent: level to: result];
|
|
||||||
(*appImp)(result, appSel, @";\n");
|
|
||||||
}
|
|
||||||
(*appImp)(result, appSel, iBaseString);
|
|
||||||
(*appImp)(result, appSel, @"}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation for this class is to return the value stored in
|
* Default implementation for this class is to return the value stored in
|
||||||
* the dictionary under the specified key, or nil if there is no value.
|
* the dictionary under the specified key, or nil if there is no value.
|
||||||
|
|
|
@ -2017,27 +2017,6 @@ static BOOL double_release_check_enabled = NO;
|
||||||
return [self descriptionWithLocale: aLocale];
|
return [self descriptionWithLocale: aLocale];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the [NSString] implementation.
|
|
||||||
*/
|
|
||||||
- (void) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned)level
|
|
||||||
to: (id<GNUDescriptionDestination>)output
|
|
||||||
{
|
|
||||||
NSString *tmp = [(id)self descriptionWithLocale: aLocale];
|
|
||||||
|
|
||||||
[tmp descriptionWithLocale: aLocale indent: level to: output];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned)level
|
|
||||||
to: (id<GNUDescriptionDestination>)output
|
|
||||||
{
|
|
||||||
NSString *tmp = [(id)self descriptionWithLocale: aLocale];
|
|
||||||
|
|
||||||
[tmp descriptionWithLocale: aLocale indent: level to: output];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) _dealloc
|
- (BOOL) _dealloc
|
||||||
{
|
{
|
||||||
return YES;
|
return YES;
|
||||||
|
|
|
@ -3742,135 +3742,6 @@ handle_printf_atsign (FILE *stream,
|
||||||
return [d writeToURL: anURL atomically: atomically];
|
return [d writeToURL: anURL atomically: atomically];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) descriptionWithLocale: (NSDictionary*)aLocale
|
|
||||||
indent: (unsigned int)level
|
|
||||||
to: (id<GNUDescriptionDestination>)output
|
|
||||||
{
|
|
||||||
unsigned length;
|
|
||||||
|
|
||||||
if ((length = [self length]) == 0)
|
|
||||||
{
|
|
||||||
[output appendString: @"\"\""];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (quotablesBitmapRep == NULL)
|
|
||||||
{
|
|
||||||
setupQuotables();
|
|
||||||
}
|
|
||||||
if ([self rangeOfCharacterFromSet: oldQuotables].length > 0
|
|
||||||
|| [self characterAtIndex: 0] == '/')
|
|
||||||
{
|
|
||||||
unichar tmp[length <= 1024 ? length : 0];
|
|
||||||
unichar *ustring;
|
|
||||||
unichar *from;
|
|
||||||
unichar *end;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
if (length <= 1024)
|
|
||||||
{
|
|
||||||
ustring = tmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ustring = NSZoneMalloc(NSDefaultMallocZone(), length*sizeof(unichar));
|
|
||||||
}
|
|
||||||
end = &ustring[length];
|
|
||||||
[self getCharacters: ustring];
|
|
||||||
for (from = ustring; from < end; from++)
|
|
||||||
{
|
|
||||||
switch (*from)
|
|
||||||
{
|
|
||||||
case '\a':
|
|
||||||
case '\b':
|
|
||||||
case '\t':
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case '\v':
|
|
||||||
case '\f':
|
|
||||||
case '\\':
|
|
||||||
case '\'' :
|
|
||||||
case '"' :
|
|
||||||
len += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (*from < 128)
|
|
||||||
{
|
|
||||||
if (isprint(*from) || *from == ' ')
|
|
||||||
{
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
len += 6;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
char buf[len+3];
|
|
||||||
char *ptr = buf;
|
|
||||||
|
|
||||||
*ptr++ = '"';
|
|
||||||
for (from = ustring; from < end; from++)
|
|
||||||
{
|
|
||||||
switch (*from)
|
|
||||||
{
|
|
||||||
case '\a': *ptr++ = '\\'; *ptr++ = 'a'; break;
|
|
||||||
case '\b': *ptr++ = '\\'; *ptr++ = 'b'; break;
|
|
||||||
case '\t': *ptr++ = '\\'; *ptr++ = 't'; break;
|
|
||||||
case '\r': *ptr++ = '\\'; *ptr++ = 'r'; break;
|
|
||||||
case '\n': *ptr++ = '\\'; *ptr++ = 'n'; break;
|
|
||||||
case '\v': *ptr++ = '\\'; *ptr++ = 'v'; break;
|
|
||||||
case '\f': *ptr++ = '\\'; *ptr++ = 'f'; break;
|
|
||||||
case '\\': *ptr++ = '\\'; *ptr++ = '\\'; break;
|
|
||||||
case '\'': *ptr++ = '\\'; *ptr++ = '\''; break;
|
|
||||||
case '"' : *ptr++ = '\\'; *ptr++ = '"'; break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (*from < 128)
|
|
||||||
{
|
|
||||||
if (isprint(*from) || *from == ' ')
|
|
||||||
{
|
|
||||||
*ptr++ = *from;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(ptr, "\\%03o", *(unsigned char*)from);
|
|
||||||
ptr = &ptr[4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(ptr, "\\u%04x", *from);
|
|
||||||
ptr = &ptr[6];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*ptr++ = '"';
|
|
||||||
*ptr = '\0';
|
|
||||||
[output appendString: [NSStringClass stringWithCString: buf]];
|
|
||||||
}
|
|
||||||
if (length > 1024)
|
|
||||||
{
|
|
||||||
NSZoneFree(NSDefaultMallocZone(), ustring);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[output appendString: self];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* NSCopying Protocol */
|
/* NSCopying Protocol */
|
||||||
|
|
||||||
- (id) copyWithZone: (NSZone*)zone
|
- (id) copyWithZone: (NSZone*)zone
|
||||||
|
|
Loading…
Reference in a new issue