Fix mutable copy of 8bit string ... hope this doesnt break anything, it passes

the testsuite and my apps saeem to run.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22920 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2006-05-12 17:46:32 +00:00
parent a9c025da57
commit 849e0b2af3
2 changed files with 173 additions and 101 deletions

View file

@ -3,6 +3,10 @@
* Source/GSString.m: validate UTF-16 data when producing a Cstring
* Source/NSCharacterSetData.h: Add code plane 16 (private use)
* Source/NSCharacterSet.m: Fix to support code plane 16
* Source/GSString.m: Attempt to fix error making a mutable copy of
an 8bit string when the external Cstring encoding is not the same as
the internal one. Use new initWithBytes... method specifying the
encoding used in those cases.
2006-05-11 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -2681,7 +2681,9 @@ transmute(GSStr self, NSString *aString)
obj = (GSMutableString*)NSAllocateObject(GSMutableStringClass, 0,
NSDefaultMallocZone());
obj = [obj initWithCString: (char*)_contents.c length: _count];
obj = [obj initWithBytes: (char*)_contents.c
length: _count
encoding: intEnc];
return obj;
}
@ -3562,6 +3564,158 @@ agree, create a new GSUnicodeInlineString otherwise.
return [self initWithCapacity: 0];
}
- (id) initWithBytes: (const void*)bytes
length: (unsigned int)length
encoding: (NSStringEncoding)encoding
{
void *chars = NSZoneMalloc(NSDefaultMallocZone(), length);
memcpy(chars, bytes, length);
return [self initWithBytesNoCopy: chars
length: length
encoding: encoding
freeWhenDone: YES];
}
- (id) initWithBytesNoCopy: (const void*)bytes
length: (unsigned int)length
encoding: (NSStringEncoding)encoding
freeWhenDone: (BOOL)flag
{
BOOL isASCII = NO;
BOOL isLatin1 = NO;
if (encoding != intEnc && GSIsByteEncoding(encoding) == YES)
{
unsigned i;
for (i = 0; i < length; i++)
{
if (((unsigned char*)bytes)[i] > 127)
{
if (encoding == NSASCIIStringEncoding)
{
RELEASE(self);
if (flag == YES && bytes != 0)
{
NSZoneFree(NSZoneFromPointer(bytes), bytes);
}
return nil; // Invalid data
}
break;
}
}
if (i == length)
{
/*
* This is actually ASCII data ... so we can just stor it as if
* in the internal 8bit encoding scheme.
*/
encoding = intEnc;
}
}
if (encoding == intEnc)
{
_count = length;
_capacity = length;
_contents.c = bytes;
_flags.wide = 0;
_flags.free = flag;
#if GS_WITH_GC
_zone = GSAtomicMallocZone();
#else
_zone = NSZoneFromPointer(bytes);
#endif
return self;
}
/*
* Any remaining encoding needs to be converted to UTF-16.
*/
if (encoding != NSUnicodeStringEncoding)
{
unichar *u = 0;
unsigned l = 0;
if (GSToUnicode(&u, &l, (unsigned char*)bytes, length, encoding,
GSObjCZone(self), 0) == NO)
{
RELEASE(self);
if (flag == YES && bytes != 0)
{
NSZoneFree(NSZoneFromPointer(bytes), bytes);
}
return nil; // Invalid data
}
if (flag == YES && bytes != 0)
{
NSZoneFree(NSZoneFromPointer(bytes), bytes);
}
bytes = u;
length = l * sizeof(unichar);
flag = YES;
}
length /= sizeof(unichar);
if (GSUnicode(bytes, length, &isASCII, &isLatin1) != length)
{
RELEASE(self);
if (flag == YES && bytes != 0)
{
NSZoneFree(NSZoneFromPointer(bytes), bytes);
}
return nil; // Invalid data
}
if (isASCII == YES
|| (intEnc == NSISOLatin1StringEncoding && isLatin1 == YES))
{
unsigned char *buf;
#if GS_WITH_GC
_zone = GSAtomicMallocZone();
#else
_zone = NSDefaultMallocZone();
#endif
buf = NSZoneMalloc(_zone, length);
_count = length;
_capacity = length;
_contents.c = buf;
_flags.wide = 0;
_flags.free = 1;
while (length-- > 0)
{
buf[length] = ((unichar*)bytes)[length];
}
if (flag == YES && bytes != 0)
{
NSZoneFree(NSZoneFromPointer(bytes), bytes);
}
}
else
{
_count = length;
_capacity = length;
_contents.u = bytes;
_flags.wide = 1;
if (flag == YES && bytes != 0)
{
#if GS_WITH_GC
_zone = GSAtomicMallocZone();
#else
_zone = NSZoneFromPointer(bytes);
#endif
_flags.free = 1;
}
else
{
_zone = 0;
}
}
return self;
}
- (id) initWithCapacity: (unsigned)capacity
{
if (capacity < 2)
@ -3585,110 +3739,20 @@ agree, create a new GSUnicodeInlineString otherwise.
length: (unsigned int)length
freeWhenDone: (BOOL)flag
{
BOOL isASCII;
BOOL isLatin1;
if (GSUnicode(chars, length, &isASCII, &isLatin1) != length)
{
RELEASE(self);
if (flag == YES && chars != 0)
{
NSZoneFree(NSZoneFromPointer(chars), chars);
}
return nil; // Invalid data
}
if (isASCII == YES
|| (intEnc == NSISOLatin1StringEncoding && isLatin1 == YES))
{
unsigned char *buf;
#if GS_WITH_GC
_zone = GSAtomicMallocZone();
#else
_zone = NSDefaultMallocZone();
#endif
buf = NSZoneMalloc(_zone, length);
_count = length;
_capacity = length;
_contents.c = buf;
_flags.wide = 0;
_flags.free = 1;
while (length-- > 0)
{
buf[length] = (unsigned char)chars[length];
}
if (flag == YES && chars != 0)
{
NSZoneFree(NSZoneFromPointer(chars), chars);
}
}
else
{
_count = length;
_capacity = length;
_contents.u = chars;
_flags.wide = 1;
if (flag == YES && chars != 0)
{
#if GS_WITH_GC
_zone = GSAtomicMallocZone();
#else
_zone = NSZoneFromPointer(chars);
#endif
_flags.free = 1;
}
else
{
_zone = 0;
}
}
return self;
return [self initWithBytesNoCopy: (void*)chars
length: length*sizeof(unichar)
encoding: NSUnicodeStringEncoding
freeWhenDone: flag];
}
- (id) initWithCStringNoCopy: (char*)chars
length: (unsigned int)length
freeWhenDone: (BOOL)flag
{
if (defEnc != intEnc)
{
unichar *u = 0;
unsigned l = 0;
if (GSToUnicode(&u, &l, (unsigned char*)chars, length, defEnc,
GSObjCZone(self), 0) == NO)
{
DESTROY(self);
}
else
{
self = [self initWithCharactersNoCopy: u length: l freeWhenDone: YES];
}
if (flag == YES && chars != 0)
{
NSZoneFree(NSZoneFromPointer(chars), chars);
}
return self;
}
if (flag == YES && chars != 0)
{
#if GS_WITH_GC
_zone = GSAtomicMallocZone();
#else
_zone = NSZoneFromPointer(chars);
#endif
_flags.free = 1;
}
else
{
_zone = 0;
}
_count = length;
_capacity = length;
_contents.c = (unsigned char*)chars;
_flags.wide = 0;
return self;
return [self initWithBytesNoCopy: (void*)chars
length: length
encoding: defEnc
freeWhenDone: flag];
}
- (id) initWithFormat: (NSString*)format
@ -3795,7 +3859,9 @@ agree, create a new GSUnicodeInlineString otherwise.
if (_flags.wide == 1)
obj = [obj initWithCharacters: _contents.u length: _count];
else
obj = [obj initWithCString: (char*)_contents.c length: _count];
obj = [obj initWithBytes: (char*)_contents.c
length: _count
encoding: intEnc];
return obj;
}
@ -3808,7 +3874,9 @@ agree, create a new GSUnicodeInlineString otherwise.
if (_flags.wide == 1)
obj = [obj initWithCharacters: _contents.u length: _count];
else
obj = [obj initWithCString: (char*)_contents.c length: _count];
obj = [obj initWithBytes: (char*)_contents.c
length: _count
encoding: intEnc];
return obj;
}