Reorganize GSString class hierarchy. Update users.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@18050 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
alexm 2003-11-05 02:11:49 +00:00
parent b75764eba4
commit f97029e9b2
4 changed files with 315 additions and 228 deletions

View file

@ -1,3 +1,18 @@
2003-11-05 03:10 Alexander Malmberg <alexander@malmberg.org>
* Source/GSString.m: Reorganize class heirarchy. Remove unused
GSCEmptyString class. Add new concrete leaf classes GSCBufferString
and GSCUnicodeString. Make GSString, GSCString, and GSUnicodeString
abstract and move the real memory management code to the two new
classes. Update the other concrete leaf classes. Update callers.
* Source/GSPrivate.h: Update comment about the semantics of the free
flag in GSString.
* Source/NSSerializer.m: Clarify comments about the cached classes.
Use GSCBufferString and GSUnicodeBufferString instead of GSCString
and GSUnicodeString when creating string instances.
Mon Nov 03 12:30:00 2003 Richard Frith-Macdonald <rfm@gnu.org> Mon Nov 03 12:30:00 2003 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSNotificationCenter.m: Use locking at all times until * Source/NSNotificationCenter.m: Use locking at all times until

View file

@ -76,7 +76,8 @@ GS_EXPORT BOOL GSIsByteEncoding(NSStringEncoding encoding);
unsigned int _count; unsigned int _count;
struct { struct {
unsigned int wide: 1; // 16-bit characters in string? unsigned int wide: 1; // 16-bit characters in string?
unsigned int free: 1; // Should free memory? unsigned int free: 1; // Set if the instance owns the
// _contents buffer
unsigned int unused: 2; unsigned int unused: 2;
unsigned int hash: 28; unsigned int hash: 28;
} _flags; } _flags;

View file

@ -61,6 +61,7 @@
struct objc_class _NSConstantStringClassReference; struct objc_class _NSConstantStringClassReference;
#endif #endif
/* /*
* GSPlaceholderString - placeholder class for objects awaiting intialisation. * GSPlaceholderString - placeholder class for objects awaiting intialisation.
*/ */
@ -69,71 +70,116 @@ struct objc_class _NSConstantStringClassReference;
} }
@end @end
/* /*
* GSCString - concrete class for strings using 8-bit character sets. GSString is the root class of our hierarchy of string classes. All our
*/ classes except GSPlaceholderString inherit from it. GSString provides
the common part of the ivar layout. It also has safe implementations
of all the memory management methods subclasses should override.
Concrete subclasses of GSString are identified by two properties:
how the string is encoded (its structure; 8-bit data or 16-bit unicode
data), and how the memory for the contents is handled (its memory
management).
Two direct subclasses of GSString provide the code for the two structures.
The memory management part of the concrete subclasses is abstracted to
a single flag for the structure classes: free. This is set only if the
_contents buffer is guaranteed to remain valid at least until the instance
has been deallocated.
(It really should be named 'ownsContents' or something similar, but it's
'free' in GSMutableString, and the structures need to be interchangeable.)
Many optimizations, such as retaining instead of copying, and using pointers
to another strings _contents buffer, are valid only if this flag is set.
GSCString, an abstract class that stores the string as 8-bit data in the
internal encoding. GSCString and its subclasses are used only if
intEnc==defEnc.
*/
@interface GSCString : GSString @interface GSCString : GSString
{ {
} }
@end @end
/* /*
* GSCInlineString - concrete subclass of GSCString, that expects the And GSUnicodeString, an abstract class that stores the string as 16-bit
* characterData to appear in memory immediately after the object itsself. unicode characters.
*/ */
@interface GSCInlineString : GSCString
{
}
@end
/*
* GSCSubString - concrete subclass of GSCString, that relies on the
* data stored in a GSCString object.
*/
@interface GSCSubString : GSCString
{
@public
GSCString *_parent;
}
@end
/*
* GSCEmptyString - concrete class for empty string
*/
@interface GSCEmptyString : GSCString
{
}
@end
/*
* GSUnicodeString - concrete class for strings using 16-bit character sets.
*/
@interface GSUnicodeString : GSString @interface GSUnicodeString : GSString
{ {
} }
@end @end
/* /*
* GSUnicodeInlineString - concrete subclass of GSUnicodeString, that For each memory management scheme, there is a pair of concrete subclasses
* expects the characterData to appear in memory immediately after the of the two abstract structure classes. Each subclass has a single -init...
* object itsself. method which can be used to initialize that specific subclass.
*/
GS*BufferString, concrete subclasses that store the data in an external
(wrt. the instance itself) buffer. The buffer may or may not be owned
by the instance; the 'free' flag indicates which. If it is set,
we need to free the buffer when we are deallocated.
*/
@interface GSCBufferString : GSCString
{
}
- (id) initWithCStringNoCopy: (char*)chars
length: (unsigned int)length
freeWhenDone: (BOOL)flag;
@end
@interface GSUnicodeBufferString : GSUnicodeString
{
}
- (id) initWithCharactersNoCopy: (unichar *)chars
length: (unsigned int)length
freeWhenDone: (BOOL)flag;
@end
/*
GS*InlineString, concrete subclasses that store the data immediately after
the instance iself.
*/
@interface GSCInlineString : GSCString
{
}
- (id) initWithCString: (const char*)chars length: (unsigned)length;
@end
@interface GSUnicodeInlineString : GSUnicodeString @interface GSUnicodeInlineString : GSUnicodeString
{ {
} }
- (id) initWithCharacters: (const unichar*)chars length: (unsigned)length;
@end @end
/* /*
* GSUnicodeSubString - concrete subclass of GSUnicodeString, that GS*SubString, concrete subclasses that use the data in another string
* relies on data stored in a GSUnicodeString object. instance.
*/ */
@interface GSCSubString : GSCString
{
@public
GSCString *_parent;
}
- (id) initWithCString: (char *)chars length: (unsigned)length
fromParent: (GSCString *)parent;
@end
@interface GSUnicodeSubString : GSUnicodeString @interface GSUnicodeSubString : GSUnicodeString
{ {
@public @public
GSUnicodeString *_parent; GSUnicodeString *_parent;
} }
- (id) initWithCharacters: (unichar *)chars length: (unsigned)length
fromParent: (GSUnicodeString *)parent;
@end @end
/* /*
* GSMutableString - concrete mutable string, capable of changing its storage * GSMutableString - concrete mutable string, capable of changing its storage
* from holding 8-bit to 16-bit character set. * from holding 8-bit to 16-bit character set.
@ -207,9 +253,11 @@ static Class NSDataClass = 0;
static Class NSStringClass = 0; static Class NSStringClass = 0;
static Class GSStringClass = 0; static Class GSStringClass = 0;
static Class GSCStringClass = 0; static Class GSCStringClass = 0;
static Class GSCBufferStringClass = 0;
static Class GSCInlineStringClass = 0; static Class GSCInlineStringClass = 0;
static Class GSCSubStringClass = 0; static Class GSCSubStringClass = 0;
static Class GSUnicodeStringClass = 0; static Class GSUnicodeStringClass = 0;
static Class GSUnicodeBufferStringClass = 0;
static Class GSUnicodeSubStringClass = 0; static Class GSUnicodeSubStringClass = 0;
static Class GSUnicodeInlineStringClass = 0; static Class GSUnicodeInlineStringClass = 0;
static Class GSMutableStringClass = 0; static Class GSMutableStringClass = 0;
@ -250,6 +298,8 @@ setup(void)
GSStringClass = [GSString class]; GSStringClass = [GSString class];
GSCStringClass = [GSCString class]; GSCStringClass = [GSCString class];
GSUnicodeStringClass = [GSUnicodeString class]; GSUnicodeStringClass = [GSUnicodeString class];
GSCBufferStringClass = [GSCBufferString class];
GSUnicodeBufferStringClass = [GSUnicodeBufferString class];
GSCInlineStringClass = [GSCInlineString class]; GSCInlineStringClass = [GSCInlineString class];
GSUnicodeInlineStringClass = [GSUnicodeInlineString class]; GSUnicodeInlineStringClass = [GSUnicodeInlineString class];
GSCSubStringClass = [GSCSubString class]; GSCSubStringClass = [GSCSubString class];
@ -319,11 +369,11 @@ setup(void)
- (void) dealloc - (void) dealloc
{ {
return; // placeholders never get deallocated. return; // Placeholders never get deallocated.
} }
/* /*
* Replace self with an inline unicode string * Replace self with an inline unicode string.
*/ */
- (id) initWithCharacters: (const unichar*)chars - (id) initWithCharacters: (const unichar*)chars
length: (unsigned)length length: (unsigned)length
@ -335,12 +385,13 @@ setup(void)
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1]; me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
me->_count = length; me->_count = length;
me->_flags.wide = 1; me->_flags.wide = 1;
me->_flags.free = 1;
memcpy(me->_contents.u, chars, length*sizeof(unichar)); memcpy(me->_contents.u, chars, length*sizeof(unichar));
return (id)me; return (id)me;
} }
/* /*
* Replace self with a simple unicode string * Replace self with a simple unicode string.
*/ */
- (id) initWithCharactersNoCopy: (unichar*)chars - (id) initWithCharactersNoCopy: (unichar*)chars
length: (unsigned)length length: (unsigned)length
@ -348,7 +399,7 @@ setup(void)
{ {
ivars me; ivars me;
me = (ivars)NSAllocateObject(GSUnicodeStringClass, 0, GSObjCZone(self)); me = (ivars)NSAllocateObject(GSUnicodeBufferStringClass, 0, GSObjCZone(self));
me->_contents.u = chars; me->_contents.u = chars;
me->_count = length; me->_count = length;
me->_flags.wide = 1; me->_flags.wide = 1;
@ -360,7 +411,7 @@ setup(void)
} }
/* /*
* Replace self with an inline 'C' string * Replace self with an inline 'C' string.
*/ */
- (id) initWithCString: (const char*)chars - (id) initWithCString: (const char*)chars
length: (unsigned)length length: (unsigned)length
@ -374,6 +425,7 @@ setup(void)
me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1]; me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1];
me->_count = length; me->_count = length;
me->_flags.wide = 0; me->_flags.wide = 0;
me->_flags.free = 1;
memcpy(me->_contents.c, chars, length); memcpy(me->_contents.c, chars, length);
return (id)me; return (id)me;
} }
@ -401,7 +453,7 @@ setup(void)
{ {
ivars me; ivars me;
me = (ivars)NSAllocateObject(GSCStringClass, 0, GSObjCZone(self)); me = (ivars)NSAllocateObject(GSCBufferStringClass, 0, GSObjCZone(self));
me->_contents.c = (unsigned char*)chars; me->_contents.c = (unsigned char*)chars;
me->_count = length; me->_count = length;
me->_flags.wide = 0; me->_flags.wide = 0;
@ -464,6 +516,7 @@ setup(void)
me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1]; me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1];
me->_count = length; me->_count = length;
me->_flags.wide = 0; me->_flags.wide = 0;
me->_flags.free = 1;
memcpy(me->_contents.c, ((ivars)string)->_contents.c, length); memcpy(me->_contents.c, ((ivars)string)->_contents.c, length);
} }
else if (GSObjCIsKindOf(c, GSUnicodeStringClass) == YES else if (GSObjCIsKindOf(c, GSUnicodeStringClass) == YES
@ -478,6 +531,7 @@ setup(void)
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1]; me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
me->_count = length; me->_count = length;
me->_flags.wide = 1; me->_flags.wide = 1;
me->_flags.free = 1;
memcpy(me->_contents.u, ((ivars)string)->_contents.u, memcpy(me->_contents.u, ((ivars)string)->_contents.u,
length*sizeof(unichar)); length*sizeof(unichar));
} }
@ -492,6 +546,7 @@ setup(void)
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1]; me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
me->_count = length; me->_count = length;
me->_flags.wide = 1; me->_flags.wide = 1;
me->_flags.free = 1;
[string getCharacters: me->_contents.u]; [string getCharacters: me->_contents.u];
} }
return (id)me; return (id)me;
@ -521,9 +576,11 @@ setup(void)
* The following inline functions are used by the concrete string classes * The following inline functions are used by the concrete string classes
* to implement their core functionality. * to implement their core functionality.
* GSCString uses the functions with the _c suffix. * GSCString uses the functions with the _c suffix.
* GSCSubString and ??ConstantString inherit methods from GSCString. * GSCSubString, GSCInlineString, GSCBufferString, and ??ConstantString
* inherit methods from GSCString.
* GSUnicodeString uses the functions with the _u suffix. * GSUnicodeString uses the functions with the _u suffix.
* GSUnicodeSubString inherits methods from GSUnicodeString. * GSUnicodeSubString, GSUnicodeInlineString, and GSUnicodeBufferString
* inherit methods from GSUnicodeString.
* GSMutableString uses all the functions, selecting the _c or _u versions * GSMutableString uses all the functions, selecting the _c or _u versions
* depending on whether its storage is 8-bit or 16-bit. * depending on whether its storage is 8-bit or 16-bit.
* In addition, GSMutableString uses a few functions without a suffix that are * In addition, GSMutableString uses a few functions without a suffix that are
@ -1692,13 +1749,9 @@ substring_c(ivars self, NSRange aRange)
if (self->_flags.free == 1) if (self->_flags.free == 1)
{ {
sub = NSAllocateObject(GSCSubStringClass, 0, NSDefaultMallocZone()); sub = NSAllocateObject(GSCSubStringClass, 0, NSDefaultMallocZone());
sub = [sub initWithCStringNoCopy: self->_contents.c + aRange.location sub = [sub initWithCString: self->_contents.c + aRange.location
length: aRange.length length: aRange.length
freeWhenDone: NO]; fromParent: (GSCString *)self];
if (sub != nil)
{
((GSCSubString*)sub)->_parent = RETAIN((id)self);
}
} }
else else
{ {
@ -1719,13 +1772,9 @@ substring_u(ivars self, NSRange aRange)
if (self->_flags.free == 1) if (self->_flags.free == 1)
{ {
sub = NSAllocateObject(GSUnicodeSubStringClass, 0, NSDefaultMallocZone()); sub = NSAllocateObject(GSUnicodeSubStringClass, 0, NSDefaultMallocZone());
sub = [sub initWithCharactersNoCopy: self->_contents.u + aRange.location sub = [sub initWithCharacters: self->_contents.u + aRange.location
length: aRange.length length: aRange.length
freeWhenDone: NO]; fromParent: (GSUnicodeString *)self];
if (sub != nil)
{
((GSUnicodeSubString*)sub)->_parent = RETAIN((id)self);
}
} }
else else
{ {
@ -1862,11 +1911,12 @@ transmute(ivars self, NSString *aString)
/* /*
* The GSString class is actually only provided to provide a common ivar * The GSString class is actually only provided to provide a common ivar
* layout for all subclasses, so that they can all share the same code. * layout for all subclasses, so that they can all share the same code.
* We don't expect this class to ever be instantiated, but we do provide * This class should never be instantiated, and with the exception of
* a common deallocation method, and standard initialisation methods that * -copyWithZone:, none of its memory management related methods
* will try to convert an instance to a type we can really use if necessary. * (initializers and -dealloc) should ever be called. We guard against
* this happening.
*/ */
@implementation GSString @implementation GSString
+ (void) initialize + (void) initialize
{ {
@ -1875,12 +1925,7 @@ transmute(ivars self, NSString *aString)
- (void) dealloc - (void) dealloc
{ {
if (_flags.free == 1 && _contents.c != 0) [self subclassResponsibility: _cmd];
{
NSZoneFree(NSZoneFromPointer(_contents.c), _contents.c);
_contents.c = 0;
}
NSDeallocateObject(self);
} }
/* /*
@ -1890,23 +1935,8 @@ transmute(ivars self, NSString *aString)
length: (unsigned int)length length: (unsigned int)length
freeWhenDone: (BOOL)flag freeWhenDone: (BOOL)flag
{ {
if (isa == GSStringClass) [self subclassResponsibility: _cmd];
{ return nil;
isa = GSUnicodeStringClass;
}
else if (_contents.u != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.u = chars;
_flags.wide = 1;
if (flag == YES)
{
_flags.free = 1;
}
return self;
} }
/* /*
@ -1917,33 +1947,20 @@ transmute(ivars self, NSString *aString)
length: (unsigned int)length length: (unsigned int)length
freeWhenDone: (BOOL)flag freeWhenDone: (BOOL)flag
{ {
if (isa == GSStringClass) [self subclassResponsibility: _cmd];
{ return nil;
isa = GSCStringClass;
}
else if (_contents.c != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.c = chars;
_flags.wide = 0;
if (flag == YES)
{
_flags.free = 1;
}
return self;
} }
- (id) copyWithZone: (NSZone*)z
{
[self subclassResponsibility: _cmd];
return nil;
}
@end @end
/*
* The GSCString class is the basic implementation of a concrete
* 8-bit string class, storing immutable data in a single buffer.
* It is only ever used when defEnc==intEnc
*/
@implementation GSCString @implementation GSCString
- (const char *) UTF8String - (const char *) UTF8String
{ {
@ -1972,23 +1989,6 @@ transmute(ivars self, NSString *aString)
return compare_c((ivars)self, aString, mask, aRange); return compare_c((ivars)self, aString, mask, aRange);
} }
- (id) copyWithZone: (NSZone*)z
{
if (_flags.free == NO
|| NSShouldRetainWithZone(self, z) == NO)
{
NSString *obj;
obj = (NSString*)NSAllocateObject(GSCInlineStringClass, _count, z);
obj = [obj initWithCString: _contents.c length: _count];
return obj;
}
else
{
return RETAIN(self);
}
}
- (const char *) cString - (const char *) cString
{ {
return cString_c((ivars)self); return cString_c((ivars)self);
@ -2160,41 +2160,13 @@ transmute(ivars self, NSString *aString)
return _count; return _count;
} }
@end
/* /*
* The GSCInlineString class is a GSCString subclass that stores data Default copy implementation. Retain if we own the buffer and the zones
* in memory immediately after the object. agree, create a new GSCInlineString otherwise.
*/ */
@implementation GSCInlineString
- (id) initWithCStringNoCopy: (char*)chars
length: (unsigned)length
freeWhenDone: (BOOL)flag
{
RELEASE(self);
[NSException raise: NSInternalInconsistencyException
format: @"Illegal method used to initialise inline string"];
return nil;
}
- (id) initWithCString: (const char*)chars length: (unsigned)length
{
if (_contents.c != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.c = (unsigned char*)&self[1];
if (_count > 0)
memcpy(_contents.c, chars, length);
_flags.wide = 0;
return self;
}
- (id) copyWithZone: (NSZone*)z - (id) copyWithZone: (NSZone*)z
{ {
if (NSShouldRetainWithZone(self, z) == NO) if (!_flags.free || NSShouldRetainWithZone(self, z) == NO)
{ {
NSString *obj; NSString *obj;
@ -2207,6 +2179,61 @@ transmute(ivars self, NSString *aString)
return RETAIN(self); return RETAIN(self);
} }
} }
@end
@implementation GSCBufferString
- (id) initWithCStringNoCopy: (char*)chars
length: (unsigned int)length
freeWhenDone: (BOOL)flag
{
if (_contents.c != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.c = chars;
_flags.wide = 0;
if (flag == YES)
{
_flags.free = 1;
}
return self;
}
- (void) dealloc
{
if (_flags.free && _contents.c != 0)
{
NSZoneFree(NSZoneFromPointer(_contents.c), _contents.c);
_contents.c = 0;
}
NSDeallocateObject(self);
}
@end
@implementation GSCInlineString
- (id) initWithCString: (const char*)chars length: (unsigned)length
{
if (_contents.c != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.c = (unsigned char*)&self[1];
if (_count > 0)
memcpy(_contents.c, chars, length);
_flags.wide = 0;
_flags.free = 1;
return self;
}
- (void) dealloc - (void) dealloc
{ {
NSDeallocateObject(self); NSDeallocateObject(self);
@ -2215,11 +2242,23 @@ transmute(ivars self, NSString *aString)
/*
* The GSCSubString class is a GSCString subclass that points into
* a section of a parent constant string class.
*/
@implementation GSCSubString @implementation GSCSubString
- (id) initWithCString: (char *)chars length: (unsigned)length
fromParent: (GSCString *)parent
{
if (_contents.c != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.c = (unsigned char *)chars;
_flags.wide = 0;
_flags.free = 1;
ASSIGN(_parent, parent);
return self;
}
/* /*
* Assume that a copy should be a new string, never just a retained substring. * Assume that a copy should be a new string, never just a retained substring.
*/ */
@ -2231,9 +2270,10 @@ transmute(ivars self, NSString *aString)
obj = [obj initWithCString: _contents.c length: _count]; obj = [obj initWithCString: _contents.c length: _count];
return obj; return obj;
} }
- (void) dealloc - (void) dealloc
{ {
RELEASE(_parent); DESTROY(_parent);
NSDeallocateObject(self); NSDeallocateObject(self);
} }
@end @end
@ -2268,24 +2308,6 @@ transmute(ivars self, NSString *aString)
return compare_u((ivars)self, aString, mask, aRange); return compare_u((ivars)self, aString, mask, aRange);
} }
- (id) copyWithZone: (NSZone*)z
{
if (_flags.free == NO
|| NSShouldRetainWithZone(self, z) == NO)
{
NSString *obj;
obj = (NSString*)NSAllocateObject(GSUnicodeInlineStringClass,
_count*sizeof(unichar), z);
obj = [obj initWithCharacters: _contents.u length: _count];
return obj;
}
else
{
return RETAIN(self);
}
}
- (const char *) cString - (const char *) cString
{ {
return cString_u((ivars)self); return cString_u((ivars)self);
@ -2466,37 +2488,13 @@ transmute(ivars self, NSString *aString)
return blen; return blen;
} }
@end /*
Default -copy implementation. Retain if we own the buffer and the zones
agree, create a new GSUnicodeInlineString otherwise.
*/
@implementation GSUnicodeInlineString
- (id) initWithCharactersNoCopy: (unichar*)chars
length: (unsigned)length
freeWhenDone: (BOOL)flag
{
RELEASE(self);
[NSException raise: NSInternalInconsistencyException
format: @"Illegal method used to initialise inline string"];
return nil;
}
- (id) initWithCharacters: (const unichar*)chars length: (unsigned)length
{
if (_contents.u != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.u = (unichar*)&((GSUnicodeInlineString*)self)[1];
if (_count > 0)
memcpy(_contents.u, chars, length*sizeof(unichar));
_flags.wide = 1;
return self;
}
- (id) copyWithZone: (NSZone*)z - (id) copyWithZone: (NSZone*)z
{ {
if (NSShouldRetainWithZone(self, z) == NO) if (!_flags.free || NSShouldRetainWithZone(self, z) == NO)
{ {
NSString *obj; NSString *obj;
@ -2510,6 +2508,61 @@ transmute(ivars self, NSString *aString)
return RETAIN(self); return RETAIN(self);
} }
} }
@end
@implementation GSUnicodeBufferString
- (id) initWithCharactersNoCopy: (unichar *)chars
length: (unsigned int)length
freeWhenDone: (BOOL)flag
{
if (_contents.u != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.u = chars;
_flags.wide = 1;
if (flag == YES)
{
_flags.free = 1;
}
return self;
}
- (void) dealloc
{
if (_flags.free && _contents.u != 0)
{
NSZoneFree(NSZoneFromPointer(_contents.u), _contents.u);
_contents.u = 0;
}
NSDeallocateObject(self);
}
@end
@implementation GSUnicodeInlineString
- (id) initWithCharacters: (const unichar*)chars length: (unsigned)length
{
if (_contents.u != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.u = (unichar*)&((GSUnicodeInlineString*)self)[1];
if (_count > 0)
memcpy(_contents.u, chars, length*sizeof(unichar));
_flags.wide = 1;
_flags.free = 1;
return self;
}
- (void) dealloc - (void) dealloc
{ {
NSDeallocateObject(self); NSDeallocateObject(self);
@ -2518,11 +2571,23 @@ transmute(ivars self, NSString *aString)
/*
* The GSUnicodeSubString class is a GSUnicodeString subclass that points
* into a section of a parent constant string class.
*/
@implementation GSUnicodeSubString @implementation GSUnicodeSubString
- (id) initWithCharacters: (unichar *)chars length: (unsigned)length
fromParent: (GSUnicodeString *)parent
{
if (_contents.u != 0)
{
[NSException raise: NSInternalInconsistencyException
format: @"re-initialisation of string"];
}
_count = length;
_contents.u = chars;
_flags.wide = 1;
_flags.free = 1;
ASSIGN(_parent, parent);
return self;
}
/* /*
* Assume that a copy should be a new string, never just a retained substring. * Assume that a copy should be a new string, never just a retained substring.
*/ */
@ -2535,9 +2600,10 @@ transmute(ivars self, NSString *aString)
obj = [obj initWithCharacters: _contents.u length: _count]; obj = [obj initWithCharacters: _contents.u length: _count];
return obj; return obj;
} }
- (void) dealloc - (void) dealloc
{ {
RELEASE(_parent); DESTROY(_parent);
NSDeallocateObject(self); NSDeallocateObject(self);
} }
@end @end
@ -2982,11 +3048,11 @@ transmute(ivars self, NSString *aString)
#endif #endif
if (_flags.wide == 1) if (_flags.wide == 1)
{ {
isa = [GSUnicodeString class]; isa = [GSUnicodeBufferString class];
} }
else else
{ {
isa = [GSCString class]; isa = [GSCBufferString class];
} }
#ifndef NDEBUG #ifndef NDEBUG
GSDebugAllocationAdd(isa, self); GSDebugAllocationAdd(isa, self);
@ -3895,7 +3961,7 @@ transmute(ivars self, NSString *aString)
NSLog(@"Warning - decoding archive containing obsolete %@ object - please delete/replace this archive", NSStringFromClass([self class])); NSLog(@"Warning - decoding archive containing obsolete %@ object - please delete/replace this archive", NSStringFromClass([self class]));
RELEASE(self); RELEASE(self);
self = (id)NSAllocateObject(GSCStringClass, 0, NSDefaultMallocZone()); self = (id)NSAllocateObject(GSCBufferStringClass, 0, NSDefaultMallocZone());
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &count]; [aCoder decodeValueOfObjCType: @encode(unsigned) at: &count];
if (count > 0) if (count > 0)
{ {
@ -3957,7 +4023,7 @@ transmute(ivars self, NSString *aString)
NSLog(@"Warning - decoding archive containing obsolete %@ object - please delete/replace this archive", NSStringFromClass([self class])); NSLog(@"Warning - decoding archive containing obsolete %@ object - please delete/replace this archive", NSStringFromClass([self class]));
RELEASE(self); RELEASE(self);
self = (id)NSAllocateObject(GSUnicodeStringClass, 0, NSDefaultMallocZone()); self = (id)NSAllocateObject(GSUnicodeBufferStringClass, 0, NSDefaultMallocZone());
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &count]; [aCoder decodeValueOfObjCType: @encode(unsigned) at: &count];
if (count > 0) if (count > 0)
{ {

View file

@ -45,9 +45,11 @@
@class GSMutableDictionary; @class GSMutableDictionary;
@class NSDataMalloc; @class NSDataMalloc;
@class GSInlineArray; @class GSInlineArray;
@class GSMutableArray; @class GSMutableArray;
@class GSCString; @class GSCString;
@class GSCBufferString;
@class GSUnicodeString; @class GSUnicodeString;
@class GSUnicodeBufferString;
@class GSMutableString; @class GSMutableString;
/* /*
@ -100,7 +102,8 @@ static char st_number = (char)ST_NUMBER;
/* /*
* Variables to cache class information. * Variables to cache class information. These are used to check how
* an instance should be serialized.
*/ */
static Class ArrayClass = 0; static Class ArrayClass = 0;
static Class MutableArrayClass = 0; static Class MutableArrayClass = 0;
@ -421,10 +424,12 @@ static BOOL shouldBeCompact = NO;
/*
* Variables to cache class information.
*/
static BOOL uniquing = NO; /* Make incoming strings unique */ static BOOL uniquing = NO; /* Make incoming strings unique */
/*
* Variables to cache class information. These are used to create instances
* when deserializing.
*/
static Class MACls = 0; /* Mutable Array */ static Class MACls = 0; /* Mutable Array */
static Class DCls = 0; /* Data */ static Class DCls = 0; /* Data */
static Class MDCls = 0; /* Mutable Dictionary */ static Class MDCls = 0; /* Mutable Dictionary */
@ -818,8 +823,8 @@ deserializeFromInfo(_NSDeserializerInfo* info)
MACls = [GSMutableArray class]; MACls = [GSMutableArray class];
DCls = [NSDataMalloc class]; DCls = [NSDataMalloc class];
MDCls = [GSMutableDictionary class]; MDCls = [GSMutableDictionary class];
USCls = [GSUnicodeString class]; USCls = [GSUnicodeBufferString class];
CSCls = [GSCString class]; CSCls = [GSCBufferString class];
csInitImp = [CSCls instanceMethodForSelector: csInitSel]; csInitImp = [CSCls instanceMethodForSelector: csInitSel];
usInitImp = [USCls instanceMethodForSelector: usInitSel]; usInitImp = [USCls instanceMethodForSelector: usInitSel];
dInitImp = [DCls instanceMethodForSelector: dInitSel]; dInitImp = [DCls instanceMethodForSelector: dInitSel];