Various improvements and bugfixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@7856 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2000-10-20 10:30:51 +00:00
parent db8f01b38e
commit b266bb9c8c
5 changed files with 428 additions and 130 deletions

View file

@ -1,3 +1,12 @@
2000-10-20 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSString.m: ([-initWithCharacters:length:]) use
([-initWithCStringNoCopy:length:freeWhenDone:]) if possible.
* Source/GSString.m: Much tidying up. Added two new concrete
classes for substrings.
* Source/NSCalendarDate.m: ([-initWithString:calendarFormat:locale:])
avoid any attempt to read beyond the supplied string.
2000-10-16 Richard Frith-Macdonald <rfm@gnu.org>
Attempts to make sure that when members of a class cluster are encoded

View file

@ -345,7 +345,8 @@ enum {
unsigned int wide: 1; // 16-bit characters in string?
unsigned int ascii: 1; // String contains only ascii?
unsigned int free: 1; // Should free memory?
unsigned int hash: 30;
unsigned int unused: 1;
unsigned int hash: 28;
} _flags;
}
@end

View file

@ -49,16 +49,48 @@
#include <base/fast.x>
#include <base/Unicode.h>
/*
* GSCString - concrete class for strings using 8-bit character sets.
*/
@interface GSCString : GSString
{
}
@end
/*
* GSCSubString - concrete subclass of GSCString, that relys on the
* data stored in a GSCString object.
*/
@interface GSCSubString : GSCString
{
@public
GSCString *_parent;
}
@end
/*
* GSUString - concrete class for strings using 16-bit character sets.
*/
@interface GSUString : GSString
{
}
@end
/*
* GSUSubString - concrete subclass of GSUString, that relys on the
* data stored in a GSUString object.
*/
@interface GSUSubString : GSUString
{
@public
GSUString *_parent;
}
@end
/*
* GSMString - concrete mutable string, capable of changing its storage
* from holding 8-bit to 16-bit character set.
*/
@interface GSMString : NSMutableString
{
union {
@ -70,7 +102,8 @@
unsigned int wide: 1;
unsigned int ascii: 1;
unsigned int free: 1;
unsigned int hash: 30;
unsigned int unused: 1;
unsigned int hash: 28;
} _flags;
NSZone *_zone;
unsigned int _capacity;
@ -126,8 +159,11 @@ typedef struct {
static Class NSDataClass = 0;
static Class NSStringClass = 0;
static Class GSStringClass = 0;
static Class GSCStringClass = 0;
static Class GSCSubStringClass = 0;
static Class GSUStringClass = 0;
static Class GSUSubStringClass = 0;
static Class GSMStringClass = 0;
static Class NXConstantStringClass = 0;
@ -140,6 +176,10 @@ static unsigned (*hashImp)(id, SEL) = 0;
static NSStringEncoding defEnc = 0;
/*
* The setup() function is called when any concrete string class is
* initialized, and cached classes and some method implementations.
*/
static void
setup()
{
@ -151,8 +191,11 @@ setup()
NSDataClass = [NSData class];
NSStringClass = [NSString class];
GSStringClass = [GSString class];
GSCStringClass = [GSCString class];
GSUStringClass = [GSUString class];
GSCSubStringClass = [GSCSubString class];
GSUSubStringClass = [GSUSubString class];
GSMStringClass = [GSMString class];
NXConstantStringClass = [NXConstantString class];
@ -168,6 +211,19 @@ setup()
}
/*
* The following inline functions are used by the concrete string classes
* to implement their core functionality.
* GSCString uses the functions with the _c suffix.
* GSCSubString and NXConstant inherit methods from GSCString.
* GSUString uses the functions with the _u suffix.
* GSUSubString inherits methods from GSUString.
* GSMString uses all the functions, selecting the _c or _u versions
* depending on whether its storage is 8-bit or 16-bit.
* In addition, GSMString uses a few functions without a suffix that are
* peculiar to its memory management (shrinking, growing, and converting).
*/
static inline BOOL
boolValue_c(ivars self)
{
@ -230,14 +286,35 @@ canBeConvertedToEncoding_c(ivars self, NSStringEncoding enc)
{
if (enc == defEnc)
return YES;
else if (self->_flags.ascii == 1)
return YES;
else
return (*convertImp)((id)self, convertSel, enc);
{
BOOL result = (*convertImp)((id)self, convertSel, enc);
if (enc == NSASCIIStringEncoding)
{
self->_flags.ascii = 1;
}
return result;
}
}
static inline BOOL
canBeConvertedToEncoding_u(ivars self, NSStringEncoding enc)
{
return (*convertImp)((id)self, convertSel, enc);
if (self->_flags.ascii == 1)
return YES;
else
{
BOOL result = (*convertImp)((id)self, convertSel, enc);
if (enc == NSASCIIStringEncoding)
{
self->_flags.ascii = 1;
}
return result;
}
}
static inline unichar
@ -270,13 +347,16 @@ compare_c(ivars self, NSString *aString, unsigned mask, NSRange aRange)
if (aString == nil)
[NSException raise: NSInvalidArgumentException format: @"compare with nil"];
if (fastIsInstance(aString) == NO)
return strCompCsNs((id)self, aString, mask, aRange);
c = fastClass(aString);
if (c == GSUStringClass
if (fastClassIsKindOfClass(c, GSUStringClass) == YES
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 1))
return strCompCsUs((id)self, aString, mask, aRange);
else if (c == GSCStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0)
|| c == NXConstantStringClass)
else if (fastClassIsKindOfClass(c, GSCStringClass) == YES
|| c == NXConstantStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0))
return strCompCsCs((id)self, aString, mask, aRange);
else
return strCompCsNs((id)self, aString, mask, aRange);
@ -289,13 +369,16 @@ compare_u(ivars self, NSString *aString, unsigned mask, NSRange aRange)
if (aString == nil)
[NSException raise: NSInvalidArgumentException format: @"compare with nil"];
if (fastIsInstance(aString) == NO)
return strCompUsNs((id)self, aString, mask, aRange);
c = fastClass(aString);
if (c == GSUStringClass
if (fastClassIsKindOfClass(c, GSUStringClass)
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 1))
return strCompUsUs((id)self, aString, mask, aRange);
else if (c == GSCStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0)
|| c == NXConstantStringClass)
else if (fastClassIsKindOfClass(c, GSCStringClass)
|| c == NXConstantStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0))
return strCompUsCs((id)self, aString, mask, aRange);
else
return strCompUsNs((id)self, aString, mask, aRange);
@ -386,11 +469,11 @@ dataUsingEncoding_c(ivars self, NSStringEncoding encoding, BOOL flag)
return [NSDataClass dataWithBytesNoCopy: buff length: t+2];
}
else if ((encoding == defEnc)
||((defEnc == NSASCIIStringEncoding)
&& ((encoding == NSISOLatin1StringEncoding)
|| (encoding == NSISOLatin2StringEncoding)
|| (encoding == NSNEXTSTEPStringEncoding)
|| (encoding == NSNonLossyASCIIStringEncoding))))
|| ((defEnc == NSASCIIStringEncoding)
&& ((encoding == NSISOLatin1StringEncoding)
|| (encoding == NSISOLatin2StringEncoding)
|| (encoding == NSNEXTSTEPStringEncoding)
|| (encoding == NSNonLossyASCIIStringEncoding))))
{
unsigned char *buff;
@ -621,16 +704,6 @@ getCString_u(ivars self, char *buffer, unsigned int maxLength,
buffer[len] = '\0';
}
static inline unsigned
hash(ivars self)
{
if (self->_flags.hash == 0)
{
self->_flags.hash = (*hashImp)((id)self, hashSel);
}
return self->_flags.hash;
}
static inline int
intValue_c(ivars self)
{
@ -668,7 +741,7 @@ intValue_u(ivars self)
}
static inline BOOL
isEqual(ivars self, id anObject)
isEqual_c(ivars self, id anObject)
{
Class c;
@ -680,8 +753,21 @@ isEqual(ivars self, id anObject)
{
return NO;
}
if (fastIsInstance(anObject) == NO)
{
return NO;
}
c = fastClassOfInstance(anObject);
if (c == GSCStringClass || c == GSUStringClass || c == GSMStringClass)
if (c == NXConstantStringClass)
{
ivars other = (ivars)anObject;
NSRange r = {0, self->_count};
if (strCompCsCs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
return NO;
}
else if (fastClassIsKindOfClass(c, GSStringClass) == YES)
{
ivars other = (ivars)anObject;
NSRange r = {0, self->_count};
@ -701,40 +787,7 @@ isEqual(ivars self, id anObject)
*/
if (other->_flags.wide == 1)
{
if (self->_flags.wide == 1)
{
if (strCompUsUs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
else
{
if (strCompCsUs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
}
else
{
if (self->_flags.wide == 1)
{
if (strCompUsCs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
else
{
if (strCompCsCs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
}
return NO;
}
else if (c == NXConstantStringClass)
{
ivars other = (ivars)anObject;
NSRange r = {0, self->_count};
if (self->_flags.wide == 1)
{
if (strCompUsCs((id)self, (id)other, 0, r) == NSOrderedSame)
if (strCompCsUs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
else
@ -744,8 +797,71 @@ isEqual(ivars self, id anObject)
}
return NO;
}
else if (c == nil)
else if (fastClassIsKindOfClass(c, NSStringClass))
{
return (*equalImp)((id)self, equalSel, anObject);
}
else
{
return NO;
}
}
static inline BOOL
isEqual_u(ivars self, id anObject)
{
Class c;
if (anObject == (id)self)
{
return YES;
}
if (anObject == nil)
{
return NO;
}
if (fastIsInstance(anObject) == NO)
{
return NO;
}
c = fastClassOfInstance(anObject);
if (c == NXConstantStringClass)
{
ivars other = (ivars)anObject;
NSRange r = {0, self->_count};
if (strCompUsCs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
return NO;
}
else if (fastClassIsKindOfClass(c, GSStringClass) == YES)
{
ivars other = (ivars)anObject;
NSRange r = {0, self->_count};
/*
* First see if the hash is the same - if not, we can't be equal.
*/
if (self->_flags.hash == 0)
self->_flags.hash = (*hashImp)((id)self, hashSel);
if (other->_flags.hash == 0)
other->_flags.hash = (*hashImp)((id)other, hashSel);
if (self->_flags.hash != other->_flags.hash)
return NO;
/*
* Do a compare depending on the type of the other string.
*/
if (other->_flags.wide == 1)
{
if (strCompUsUs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
else
{
if (strCompUsCs((id)self, (id)other, 0, r) == NSOrderedSame)
return YES;
}
return NO;
}
else if (fastClassIsKindOfClass(c, NSStringClass))
@ -925,13 +1041,16 @@ rangeOfString_c(ivars self, NSString *aString, unsigned mask, NSRange aRange)
if (aString == nil)
[NSException raise: NSInvalidArgumentException format: @"range of nil"];
if (fastIsInstance(aString) == NO)
return strRangeCsNs((id)self, aString, mask, aRange);
c = fastClass(aString);
if (c == GSUStringClass
if (fastClassIsKindOfClass(c, GSUStringClass) == YES
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 1))
return strRangeCsUs((id)self, aString, mask, aRange);
else if (c == GSCStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0)
|| c == NXConstantStringClass)
else if (fastClassIsKindOfClass(c, GSCStringClass) == YES
|| c == NXConstantStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0))
return strRangeCsCs((id)self, aString, mask, aRange);
else
return strRangeCsNs((id)self, aString, mask, aRange);
@ -944,32 +1063,21 @@ rangeOfString_u(ivars self, NSString *aString, unsigned mask, NSRange aRange)
if (aString == nil)
[NSException raise: NSInvalidArgumentException format: @"range of nil"];
if (fastIsInstance(aString) == NO)
return strRangeUsNs((id)self, aString, mask, aRange);
c = fastClass(aString);
if (c == GSUStringClass
if (fastClassIsKindOfClass(c, GSUStringClass) == YES
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 1))
return strRangeUsUs((id)self, aString, mask, aRange);
else if (c == GSCStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0)
|| c == NXConstantStringClass)
else if (fastClassIsKindOfClass(c, GSCStringClass) == YES
|| c == NXConstantStringClass
|| (c == GSMStringClass && ((ivars)aString)->_flags.wide == 0))
return strRangeUsCs((id)self, aString, mask, aRange);
else
return strRangeUsNs((id)self, aString, mask, aRange);
}
static inline NSString*
substringFromRange_c(ivars self, NSRange aRange)
{
return [GSCStringClass stringWithCString:
self->_contents.c + aRange.location length: aRange.length];
}
static inline NSString*
substringFromRange_u(ivars self, NSRange aRange)
{
return [GSUStringClass stringWithCharacters:
self->_contents.u + aRange.location length: aRange.length];
}
/*
* Function to examine the given string and see if it is one of our concrete
* string classes. Converts the mutable string (self) from 8-bit to 16-bit
@ -987,8 +1095,24 @@ transmute(ivars self, NSString *aString)
other = (ivars)aString;
transmute = YES;
/*
* Unless we are sure that the other string we are going to insert into
* this one contains only ascii characters, we clear the flag that says
* we contain only ascii.
*/
if (fastClassIsKindOfClass(c, GSStringClass) == NO
|| c == NXConstantStringClass || other->_flags.ascii == 0)
{
self->_flags.ascii = 0;
}
if (self->_flags.wide == 1)
{
/*
* This is already a unicode string, so we don't need to transmute,
* but we still need to know if the other string is a unicode
* string whose ivars we can access directly.
*/
transmute = NO;
if ((c != GSMStringClass || other->_flags.wide != 1)
&& c != GSUStringClass)
@ -1001,20 +1125,39 @@ transmute(ivars self, NSString *aString)
if (c == GSCStringClass || c == NXConstantStringClass
|| (c == GSMStringClass && other->_flags.wide == 0))
{
/*
* This is a C string, but the other string is also a C string
* so we don't need to transmute, and we can use its ivars.
*/
transmute = NO;
}
else if ([aString canBeConvertedToEncoding: defEnc] == YES)
{
/*
* This is a C string, but the other string can be converted to
* a C string, so we don't need to transmute, but we can not use
* its ivars.
*/
transmute = NO;
other = 0;
}
else if ((c == GSMStringClass && other->_flags.wide == 1)
|| c == GSUStringClass)
{
/*
* This is a C string, and the other string can not be converted
* to a C string, so we need to transmute, and will then be able
* to use its ivars.
*/
transmute = YES;
}
else
{
/*
* This is a C string, and the other string can not be converted
* to a C string, so we need to transmute, but even then we will
* not be able to use the other strings ivars.
*/
other = 0;
}
}
@ -1235,7 +1378,11 @@ transmute(ivars self, NSString *aString)
- (unsigned) hash
{
return hash((ivars)self);
if (self->_flags.hash == 0)
{
self->_flags.hash = (*hashImp)((id)self, hashSel);
}
return self->_flags.hash;
}
- (int) intValue
@ -1245,7 +1392,12 @@ transmute(ivars self, NSString *aString)
- (BOOL) isEqual: (id)anObject
{
return isEqual((ivars)self, anObject);
return isEqual_c((ivars)self, anObject);
}
- (BOOL) isEqualToString: (NSString*)anObject
{
return isEqual_c((ivars)self, anObject);
}
- (unsigned int) length
@ -1293,8 +1445,22 @@ transmute(ivars self, NSString *aString)
- (NSString*) substringFromRange: (NSRange)aRange
{
GSCSubString *sub;
GS_RANGE_CHECK(aRange, _count);
return substringFromRange_c((ivars)self, aRange);
sub = [GSCSubStringClass allocWithZone: NSDefaultMallocZone()];
sub = [sub initWithCStringNoCopy: self->_contents.c + aRange.location
length: aRange.length
freeWhenDone: NO];
if (sub != nil)
{
sub->_parent = RETAIN(self);
if (_flags.ascii == 1)
((ivars)sub)->_flags.ascii = 1;
AUTORELEASE(sub);
}
return sub;
}
// private method for Unicode level 3 implementation
@ -1307,6 +1473,16 @@ transmute(ivars self, NSString *aString)
@implementation GSCSubString
- (void) dealloc
{
RELEASE(_parent);
[super dealloc];
}
@end
@implementation GSUString
+ (id) alloc
@ -1472,7 +1648,11 @@ transmute(ivars self, NSString *aString)
- (unsigned) hash
{
return hash((ivars)self);
if (self->_flags.hash == 0)
{
self->_flags.hash = (*hashImp)((id)self, hashSel);
}
return self->_flags.hash;
}
- (int) intValue
@ -1482,7 +1662,12 @@ transmute(ivars self, NSString *aString)
- (BOOL) isEqual: (id)anObject
{
return isEqual((ivars)self, anObject);
return isEqual_u((ivars)self, anObject);
}
- (BOOL) isEqualToString: (NSString*)anObject
{
return isEqual_u((ivars)self, anObject);
}
- (unsigned int) length
@ -1530,8 +1715,22 @@ transmute(ivars self, NSString *aString)
- (NSString*) substringFromRange: (NSRange)aRange
{
GSUSubString *sub;
GS_RANGE_CHECK(aRange, _count);
return substringFromRange_u((ivars)self, aRange);
sub = [GSUStringClass allocWithZone: NSDefaultMallocZone()];
sub = [sub initWithCharactersNoCopy: self->_contents.u + aRange.location
length: aRange.length
freeWhenDone: NO];
if (sub != nil)
{
sub->_parent = RETAIN(self);
if (_flags.ascii == 1)
((ivars)sub)->_flags.ascii = 1;
AUTORELEASE(sub);
}
return sub;
}
// private method for Unicode level 3 implementation
@ -1550,6 +1749,16 @@ transmute(ivars self, NSString *aString)
@implementation GSUSubString
- (void) dealloc
{
RELEASE(_parent);
[super dealloc];
}
@end
@implementation GSMString
+ (id) alloc
@ -1783,7 +1992,11 @@ transmute(ivars self, NSString *aString)
- (unsigned) hash
{
return hash((ivars)self);
if (self->_flags.hash == 0)
{
self->_flags.hash = (*hashImp)((id)self, hashSel);
}
return self->_flags.hash;
}
- (id) init
@ -1868,7 +2081,18 @@ transmute(ivars self, NSString *aString)
- (BOOL) isEqual: (id)anObject
{
return isEqual((ivars)self, anObject);
if (_flags.wide == 1)
return isEqual_u((ivars)self, anObject);
else
return isEqual_c((ivars)self, anObject);
}
- (BOOL) isEqualToString: (NSString*)anObject
{
if (_flags.wide == 1)
return isEqual_u((ivars)self, anObject);
else
return isEqual_c((ivars)self, anObject);
}
- (unsigned int) length
@ -2071,9 +2295,15 @@ transmute(ivars self, NSString *aString)
GS_RANGE_CHECK(aRange, _count);
if (_flags.wide == 1)
return substringFromRange_u((ivars)self, aRange);
{
return [GSUStringClass stringWithCharacters:
self->_contents.u + aRange.location length: aRange.length];
}
else
return substringFromRange_c((ivars)self, aRange);
{
return [GSCStringClass stringWithCString:
self->_contents.c + aRange.location length: aRange.length];
}
}
// private method for Unicode level 3 implementation
@ -2246,9 +2476,14 @@ transmute(ivars self, NSString *aString)
{
return NO;
}
if (fastIsInstance(anObject) == NO)
{
return NO;
}
c = fastClassOfInstance(anObject);
if (c == GSCStringClass || c == NXConstantStringClass
if (fastClassIsKindOfClass(c, GSCStringClass) == YES
|| c == NXConstantStringClass
|| (c == GSMStringClass && ((ivars)anObject)->_flags.wide == 0))
{
ivars other = (ivars)anObject;
@ -2259,16 +2494,13 @@ transmute(ivars self, NSString *aString)
return NO;
return YES;
}
else if (c == GSUStringClass || c == GSMStringClass)
else if (fastClassIsKindOfClass(c, GSUStringClass) == YES
|| c == GSMStringClass)
{
if (strCompCsUs(self, anObject, 0, (NSRange){0,_count}) == NSOrderedSame)
return YES;
return NO;
}
else if (c == nil)
{
return NO;
}
else if (fastClassIsKindOfClass(c, NSStringClass))
{
return (*equalImp)(self, equalSel, anObject);
@ -2291,9 +2523,14 @@ transmute(ivars self, NSString *aString)
{
return NO;
}
if (fastIsInstance(anObject) == NO)
{
return NO;
}
c = fastClassOfInstance(anObject);
if (c == GSCStringClass || c == NXConstantStringClass
if (fastClassIsKindOfClass(c, GSCStringClass) == YES
|| c == NXConstantStringClass
|| (c == GSMStringClass && ((ivars)anObject)->_flags.wide == 0))
{
ivars other = (ivars)anObject;
@ -2304,16 +2541,13 @@ transmute(ivars self, NSString *aString)
return NO;
return YES;
}
else if (c == GSUStringClass || c == GSMStringClass)
else if (fastClassIsKindOfClass(c, GSUStringClass) == YES
|| c == GSMStringClass)
{
if (strCompCsUs(self, anObject, 0, (NSRange){0,_count}) == NSOrderedSame)
return YES;
return NO;
}
else if (c == nil)
{
return NO;
}
else if (fastClassIsKindOfClass(c, NSStringClass))
{
return (*equalImp)(self, equalSel, anObject);

View file

@ -354,12 +354,15 @@ static inline int getDigits(const char *from, char *to, int limit)
}
else
{
if (source[sourceIdx] != format[formatIdx])
if (sourceIdx < sourceLen)
{
NSLog(@"Expected literal '%c' but got '%c'",
format[formatIdx], source[sourceIdx]);
if (source[sourceIdx] != format[formatIdx])
{
NSLog(@"Expected literal '%c' but gmtt '%c'",
format[formatIdx], source[sourceIdx]);
}
sourceIdx++;
}
sourceIdx++;
}
}
else
@ -371,19 +374,28 @@ static inline int getDigits(const char *from, char *to, int limit)
{
case '%':
// skip literal %
if (source[sourceIdx] != '%')
if (sourceIdx < sourceLen)
{
NSLog(@"Expected literal '%' but got '%c'",
source[sourceIdx]);
if (source[sourceIdx] != '%')
{
NSLog(@"Expected literal '%' but got '%c'",
source[sourceIdx]);
}
sourceIdx++;
}
sourceIdx++;
break;
case 'a':
// Are Short names three chars in all locales?????
tmpStr[0] = toupper(source[sourceIdx++]);
tmpStr[1] = tolower(source[sourceIdx++]);
tmpStr[2] = tolower(source[sourceIdx++]);
tmpStr[0] = toupper(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[1] = tolower(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[2] = tolower(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[3] = '\0';
{
NSString *currDay;
@ -437,9 +449,15 @@ static inline int getDigits(const char *from, char *to, int limit)
case 'b':
// Are Short names three chars in all locales?????
tmpStr[0] = toupper(source[sourceIdx++]);
tmpStr[1] = tolower(source[sourceIdx++]);
tmpStr[2] = tolower(source[sourceIdx++]);
tmpStr[0] = toupper(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[1] = tolower(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[2] = tolower(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[3] = '\0';
{
NSString *currMonth;
@ -530,8 +548,12 @@ static inline int getDigits(const char *from, char *to, int limit)
case 'p':
// Questionable assumption that all am/pm indicators are 2
// characters and in upper case....
tmpStr[0] = toupper(source[sourceIdx++]);
tmpStr[1] = toupper(source[sourceIdx++]);
tmpStr[0] = toupper(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[1] = toupper(source[sourceIdx]);
if (sourceIdx < sourceLen)
sourceIdx++;
tmpStr[2] = '\0';
{
NSString *currAMPM;

View file

@ -343,15 +343,47 @@ handle_printf_atsign (FILE *stream,
{
if (length > 0)
{
unichar *s = NSZoneMalloc(fastZone(self), sizeof(unichar)*length);
int i;
BOOL isAscii = YES;
if (chars != 0)
if (chars == 0)
{
memcpy(s, chars, sizeof(unichar)*length);
[NSException raise: NSInvalidArgumentException
format: @"nul pointer but non-zero length"];
}
for (i = 0; i < length; i++)
{
if (chars[i] >= 128)
{
isAscii = NO;
break;
}
}
if (isAscii == YES)
{
char *s;
s = NSZoneMalloc(fastZone(self), length);
for (i = 0; i < length; i++)
{
s[i] = (unsigned char)chars[i];
}
self = [self initWithCStringNoCopy: s
length: length
freeWhenDone: YES];
}
else
{
unichar *s;
s = NSZoneMalloc(fastZone(self), sizeof(unichar)*length);
memcpy(s, chars, sizeof(unichar)*length);
self = [self initWithCharactersNoCopy: s
length: length
freeWhenDone: YES];
}
self = [self initWithCharactersNoCopy: s
length: length
freeWhenDone: YES];
}
else
{