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:
Alexander Malmberg 2003-11-05 02:11:49 +00:00
parent 61e0197b79
commit 6d7a021d6c
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>
* Source/NSNotificationCenter.m: Use locking at all times until

View file

@ -76,7 +76,8 @@ GS_EXPORT BOOL GSIsByteEncoding(NSStringEncoding encoding);
unsigned int _count;
struct {
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 hash: 28;
} _flags;

View file

@ -61,6 +61,7 @@
struct objc_class _NSConstantStringClassReference;
#endif
/*
* GSPlaceholderString - placeholder class for objects awaiting intialisation.
*/
@ -69,71 +70,116 @@ struct objc_class _NSConstantStringClassReference;
}
@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
{
}
@end
/*
* GSCInlineString - concrete subclass of GSCString, that expects the
* characterData to appear in memory immediately after the object itsself.
*/
@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.
*/
And GSUnicodeString, an abstract class that stores the string as 16-bit
unicode characters.
*/
@interface GSUnicodeString : GSString
{
}
@end
/*
* GSUnicodeInlineString - concrete subclass of GSUnicodeString, that
* expects the characterData to appear in memory immediately after the
* object itsself.
*/
For each memory management scheme, there is a pair of concrete subclasses
of the two abstract structure classes. Each subclass has a single -init...
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
{
}
- (id) initWithCharacters: (const unichar*)chars length: (unsigned)length;
@end
/*
* GSUnicodeSubString - concrete subclass of GSUnicodeString, that
* relies on data stored in a GSUnicodeString object.
*/
GS*SubString, concrete subclasses that use the data in another string
instance.
*/
@interface GSCSubString : GSCString
{
@public
GSCString *_parent;
}
- (id) initWithCString: (char *)chars length: (unsigned)length
fromParent: (GSCString *)parent;
@end
@interface GSUnicodeSubString : GSUnicodeString
{
@public
GSUnicodeString *_parent;
}
- (id) initWithCharacters: (unichar *)chars length: (unsigned)length
fromParent: (GSUnicodeString *)parent;
@end
/*
* GSMutableString - concrete mutable string, capable of changing its storage
* from holding 8-bit to 16-bit character set.
@ -207,9 +253,11 @@ static Class NSDataClass = 0;
static Class NSStringClass = 0;
static Class GSStringClass = 0;
static Class GSCStringClass = 0;
static Class GSCBufferStringClass = 0;
static Class GSCInlineStringClass = 0;
static Class GSCSubStringClass = 0;
static Class GSUnicodeStringClass = 0;
static Class GSUnicodeBufferStringClass = 0;
static Class GSUnicodeSubStringClass = 0;
static Class GSUnicodeInlineStringClass = 0;
static Class GSMutableStringClass = 0;
@ -250,6 +298,8 @@ setup(void)
GSStringClass = [GSString class];
GSCStringClass = [GSCString class];
GSUnicodeStringClass = [GSUnicodeString class];
GSCBufferStringClass = [GSCBufferString class];
GSUnicodeBufferStringClass = [GSUnicodeBufferString class];
GSCInlineStringClass = [GSCInlineString class];
GSUnicodeInlineStringClass = [GSUnicodeInlineString class];
GSCSubStringClass = [GSCSubString class];
@ -319,11 +369,11 @@ setup(void)
- (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
length: (unsigned)length
@ -335,12 +385,13 @@ setup(void)
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
me->_count = length;
me->_flags.wide = 1;
me->_flags.free = 1;
memcpy(me->_contents.u, chars, length*sizeof(unichar));
return (id)me;
}
/*
* Replace self with a simple unicode string
* Replace self with a simple unicode string.
*/
- (id) initWithCharactersNoCopy: (unichar*)chars
length: (unsigned)length
@ -348,7 +399,7 @@ setup(void)
{
ivars me;
me = (ivars)NSAllocateObject(GSUnicodeStringClass, 0, GSObjCZone(self));
me = (ivars)NSAllocateObject(GSUnicodeBufferStringClass, 0, GSObjCZone(self));
me->_contents.u = chars;
me->_count = length;
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
length: (unsigned)length
@ -374,6 +425,7 @@ setup(void)
me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1];
me->_count = length;
me->_flags.wide = 0;
me->_flags.free = 1;
memcpy(me->_contents.c, chars, length);
return (id)me;
}
@ -401,7 +453,7 @@ setup(void)
{
ivars me;
me = (ivars)NSAllocateObject(GSCStringClass, 0, GSObjCZone(self));
me = (ivars)NSAllocateObject(GSCBufferStringClass, 0, GSObjCZone(self));
me->_contents.c = (unsigned char*)chars;
me->_count = length;
me->_flags.wide = 0;
@ -464,6 +516,7 @@ setup(void)
me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1];
me->_count = length;
me->_flags.wide = 0;
me->_flags.free = 1;
memcpy(me->_contents.c, ((ivars)string)->_contents.c, length);
}
else if (GSObjCIsKindOf(c, GSUnicodeStringClass) == YES
@ -478,6 +531,7 @@ setup(void)
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
me->_count = length;
me->_flags.wide = 1;
me->_flags.free = 1;
memcpy(me->_contents.u, ((ivars)string)->_contents.u,
length*sizeof(unichar));
}
@ -492,6 +546,7 @@ setup(void)
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
me->_count = length;
me->_flags.wide = 1;
me->_flags.free = 1;
[string getCharacters: me->_contents.u];
}
return (id)me;
@ -521,9 +576,11 @@ setup(void)
* 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 ??ConstantString inherit methods from GSCString.
* GSCSubString, GSCInlineString, GSCBufferString, and ??ConstantString
* inherit methods from GSCString.
* 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
* depending on whether its storage is 8-bit or 16-bit.
* 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)
{
sub = NSAllocateObject(GSCSubStringClass, 0, NSDefaultMallocZone());
sub = [sub initWithCStringNoCopy: self->_contents.c + aRange.location
length: aRange.length
freeWhenDone: NO];
if (sub != nil)
{
((GSCSubString*)sub)->_parent = RETAIN((id)self);
}
sub = [sub initWithCString: self->_contents.c + aRange.location
length: aRange.length
fromParent: (GSCString *)self];
}
else
{
@ -1719,13 +1772,9 @@ substring_u(ivars self, NSRange aRange)
if (self->_flags.free == 1)
{
sub = NSAllocateObject(GSUnicodeSubStringClass, 0, NSDefaultMallocZone());
sub = [sub initWithCharactersNoCopy: self->_contents.u + aRange.location
length: aRange.length
freeWhenDone: NO];
if (sub != nil)
{
((GSUnicodeSubString*)sub)->_parent = RETAIN((id)self);
}
sub = [sub initWithCharacters: self->_contents.u + aRange.location
length: aRange.length
fromParent: (GSUnicodeString *)self];
}
else
{
@ -1862,11 +1911,12 @@ transmute(ivars self, NSString *aString)
/*
* 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.
* We don't expect this class to ever be instantiated, but we do provide
* a common deallocation method, and standard initialisation methods that
* will try to convert an instance to a type we can really use if necessary.
* This class should never be instantiated, and with the exception of
* -copyWithZone:, none of its memory management related methods
* (initializers and -dealloc) should ever be called. We guard against
* this happening.
*/
@implementation GSString
@implementation GSString
+ (void) initialize
{
@ -1875,12 +1925,7 @@ transmute(ivars self, NSString *aString)
- (void) dealloc
{
if (_flags.free == 1 && _contents.c != 0)
{
NSZoneFree(NSZoneFromPointer(_contents.c), _contents.c);
_contents.c = 0;
}
NSDeallocateObject(self);
[self subclassResponsibility: _cmd];
}
/*
@ -1890,23 +1935,8 @@ transmute(ivars self, NSString *aString)
length: (unsigned int)length
freeWhenDone: (BOOL)flag
{
if (isa == GSStringClass)
{
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;
[self subclassResponsibility: _cmd];
return nil;
}
/*
@ -1917,33 +1947,20 @@ transmute(ivars self, NSString *aString)
length: (unsigned int)length
freeWhenDone: (BOOL)flag
{
if (isa == GSStringClass)
{
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;
[self subclassResponsibility: _cmd];
return nil;
}
- (id) copyWithZone: (NSZone*)z
{
[self subclassResponsibility: _cmd];
return nil;
}
@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
- (const char *) UTF8String
{
@ -1972,23 +1989,6 @@ transmute(ivars self, NSString *aString)
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
{
return cString_c((ivars)self);
@ -2160,41 +2160,13 @@ transmute(ivars self, NSString *aString)
return _count;
}
@end
/*
* The GSCInlineString class is a GSCString subclass that stores data
* in memory immediately after the object.
*/
@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;
}
Default copy implementation. Retain if we own the buffer and the zones
agree, create a new GSCInlineString otherwise.
*/
- (id) copyWithZone: (NSZone*)z
{
if (NSShouldRetainWithZone(self, z) == NO)
if (!_flags.free || NSShouldRetainWithZone(self, z) == NO)
{
NSString *obj;
@ -2207,6 +2179,61 @@ transmute(ivars self, NSString *aString)
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
{
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
- (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.
*/
@ -2231,9 +2270,10 @@ transmute(ivars self, NSString *aString)
obj = [obj initWithCString: _contents.c length: _count];
return obj;
}
- (void) dealloc
{
RELEASE(_parent);
DESTROY(_parent);
NSDeallocateObject(self);
}
@end
@ -2268,24 +2308,6 @@ transmute(ivars self, NSString *aString)
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
{
return cString_u((ivars)self);
@ -2466,37 +2488,13 @@ transmute(ivars self, NSString *aString)
return blen;
}
@end
@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;
}
/*
Default -copy implementation. Retain if we own the buffer and the zones
agree, create a new GSUnicodeInlineString otherwise.
*/
- (id) copyWithZone: (NSZone*)z
{
if (NSShouldRetainWithZone(self, z) == NO)
if (!_flags.free || NSShouldRetainWithZone(self, z) == NO)
{
NSString *obj;
@ -2510,6 +2508,61 @@ transmute(ivars self, NSString *aString)
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
{
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
- (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.
*/
@ -2535,9 +2600,10 @@ transmute(ivars self, NSString *aString)
obj = [obj initWithCharacters: _contents.u length: _count];
return obj;
}
- (void) dealloc
{
RELEASE(_parent);
DESTROY(_parent);
NSDeallocateObject(self);
}
@end
@ -2982,11 +3048,11 @@ transmute(ivars self, NSString *aString)
#endif
if (_flags.wide == 1)
{
isa = [GSUnicodeString class];
isa = [GSUnicodeBufferString class];
}
else
{
isa = [GSCString class];
isa = [GSCBufferString class];
}
#ifndef NDEBUG
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]));
RELEASE(self);
self = (id)NSAllocateObject(GSCStringClass, 0, NSDefaultMallocZone());
self = (id)NSAllocateObject(GSCBufferStringClass, 0, NSDefaultMallocZone());
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &count];
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]));
RELEASE(self);
self = (id)NSAllocateObject(GSUnicodeStringClass, 0, NSDefaultMallocZone());
self = (id)NSAllocateObject(GSUnicodeBufferStringClass, 0, NSDefaultMallocZone());
[aCoder decodeValueOfObjCType: @encode(unsigned) at: &count];
if (count > 0)
{

View file

@ -45,9 +45,11 @@
@class GSMutableDictionary;
@class NSDataMalloc;
@class GSInlineArray;
@class GSMutableArray;
@class GSMutableArray;
@class GSCString;
@class GSCBufferString;
@class GSUnicodeString;
@class GSUnicodeBufferString;
@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 MutableArrayClass = 0;
@ -421,10 +424,12 @@ static BOOL shouldBeCompact = NO;
/*
* Variables to cache class information.
*/
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 DCls = 0; /* Data */
static Class MDCls = 0; /* Mutable Dictionary */
@ -818,8 +823,8 @@ deserializeFromInfo(_NSDeserializerInfo* info)
MACls = [GSMutableArray class];
DCls = [NSDataMalloc class];
MDCls = [GSMutableDictionary class];
USCls = [GSUnicodeString class];
CSCls = [GSCString class];
USCls = [GSUnicodeBufferString class];
CSCls = [GSCBufferString class];
csInitImp = [CSCls instanceMethodForSelector: csInitSel];
usInitImp = [USCls instanceMethodForSelector: usInitSel];
dInitImp = [DCls instanceMethodForSelector: dInitSel];