Improve startup time by doing lazy checks for available encodings.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14359 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-08-28 13:41:54 +00:00
parent 8be710069a
commit 667b539a1b
3 changed files with 104 additions and 64 deletions

View file

@ -1,3 +1,11 @@
2002-08-28 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Unicode.m: Rewritten the way that iconv is used to decide
upon the available encodings ... lazy evaluation so that we don't
try to lookup an encoding until we have to. This should improve
process startup time (especially in gdb) since the iconv operations
seem to be very slow.
2002-08-27 Richard Frith-Macdonald <rfm@gnu.org> 2002-08-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/Additions/GSXML.m: Integrated GSXPath code by Nicola Pero * Source/Additions/GSXML.m: Integrated GSXPath code by Nicola Pero

View file

@ -113,11 +113,14 @@ struct _strenc_ {
* and the first 128 are identical to * and the first 128 are identical to
* the ASCII character set. * the ASCII character set.
*/ */
BOOL supported; /* Is this supported? Some encodings char supported; /* Is this supported? Some encodings
* have builtin conversion to/from * have builtin conversion to/from
* unicode, but for others we must * unicode, but for others we must
* check with iconv to see if it * check with iconv to see if it
* supports them on this platform. * supports them on this platform.
* A one means supported.
* A negative means unsupported.
* A zero means not yet checked.
*/ */
}; };
@ -169,16 +172,15 @@ static struct _strenc_ str_encoding_table[] = {
static struct _strenc_ **encodingTable = 0; static struct _strenc_ **encodingTable = 0;
static unsigned encTableSize = 0; static unsigned encTableSize = 0;
NSStringEncoding *GetAvailableEncodings() static void GSSetupEncodingTable()
{ {
if (_availableEncodings == 0) if (encodingTable == 0)
{ {
[gnustep_global_lock lock]; [gnustep_global_lock lock];
if (_availableEncodings == 0) if (encodingTable == 0)
{ {
NSStringEncoding *encodings; static struct _strenc_ **encTable = 0;
unsigned count; unsigned count;
unsigned pos;
unsigned i; unsigned i;
/* /*
@ -207,8 +209,8 @@ NSStringEncoding *GetAvailableEncodings()
encTableSize = tmp; encTableSize = tmp;
} }
} }
encodingTable = malloc((encTableSize+1)*sizeof(struct _strenc_ *)); encTable = malloc((encTableSize+1)*sizeof(struct _strenc_ *));
memset(encodingTable, 0, (encTableSize+1)*sizeof(struct _strenc_ *)); memset(encTable, 0, (encTableSize+1)*sizeof(struct _strenc_ *));
/* /*
* Now set up the pointers at the correct location in the table. * Now set up the pointers at the correct location in the table.
@ -219,65 +221,91 @@ NSStringEncoding *GetAvailableEncodings()
if (tmp < MAX_ENCODING) if (tmp < MAX_ENCODING)
{ {
encodingTable[tmp] = &str_encoding_table[i]; encTable[tmp] = &str_encoding_table[i];
} }
} }
encodingTable = encTable;
}
[gnustep_global_lock unlock];
}
}
static BOOL GSEncodingSupported(NSStringEncoding enc)
{
GSSetupEncodingTable();
if (enc == 0 || enc > encTableSize || encodingTable[enc] == 0)
{
return NO;
}
#ifdef HAVE_ICONV
if (encodingTable[enc]->iconv != 0 && encodingTable[enc]->supported == 0)
{
if (enc == NSUnicodeStringEncoding)
{
encodingTable[enc]->iconv = UNICODE_ENC;
encodingTable[enc]->supported = 1;
}
else
{
iconv_t c;
c = iconv_open(UNICODE_ENC, encodingTable[enc]->iconv);
if (c == (iconv_t)-1)
{
encodingTable[enc]->supported = -1;
}
else
{
iconv_close(c);
c = iconv_open(encodingTable[enc]->iconv, UNICODE_ENC);
if (c == (iconv_t)-1)
{
encodingTable[enc]->supported = -1;
}
else
{
iconv_close(c);
encodingTable[enc]->supported = 1;
}
}
}
}
#endif
if (encodingTable[enc]->supported == 1)
{
return YES;
}
return NO;
}
NSStringEncoding *GetAvailableEncodings()
{
if (_availableEncodings == 0)
{
[gnustep_global_lock lock];
if (_availableEncodings == 0)
{
NSStringEncoding *encodings;
unsigned pos;
unsigned i;
/* /*
* Now build up a list of supported encodings ... in the * Now build up a list of supported encodings ... in the
* format needed to support [NSStirng+availableStringEncodings] * format needed to support [NSString+availableStringEncodings]
* Check to see what iconv support we have as we go along. * Check to see what iconv support we have as we go along.
* This is also the palce where we determine the name we use * This is also the place where we determine the name we use
* for iconv to support unicode. * for iconv to support unicode.
*/ */
encodings = objc_malloc(sizeof(NSStringEncoding) * count); GSSetupEncodingTable();
encodings = objc_malloc(sizeof(NSStringEncoding) * encTableSize);
pos = 0; pos = 0;
for (i = 0; i < count; i++) for (i = 0; i < encTableSize; i++)
{ {
NSStringEncoding enc = str_encoding_table[i].enc; if (GSEncodingSupported(i) == YES)
if (enc == 0 || enc >= MAX_ENCODING)
{ {
continue; encodings[pos++] = i;
} }
#ifdef HAVE_ICONV
if (enc == NSUnicodeStringEncoding)
{
encodingTable[enc]->iconv = UNICODE_ENC;
encodingTable[enc]->supported = 1;
}
if (encodingTable[enc]->supported == 0)
{
if (encodingTable[enc]->iconv == 0)
{
continue; // Not handled by iconv.
}
else
{
iconv_t c;
c = iconv_open(UNICODE_ENC, encodingTable[enc]->iconv);
if (c == (iconv_t)-1)
{
continue; // Can't convert to unicode
}
iconv_close(c);
c = iconv_open(encodingTable[enc]->iconv, UNICODE_ENC);
if (c == (iconv_t)-1)
{
continue; // Can't convert from unicode
}
iconv_close(c);
encodingTable[enc]->supported = 1;
}
}
#else
if (encodingTable[enc]->supported == 0)
{
continue;
}
#endif
encodings[pos++] = enc;
} }
encodings[pos] = 0; encodings[pos] = 0;
_availableEncodings = encodings; _availableEncodings = encodings;
@ -287,6 +315,9 @@ NSStringEncoding *GetAvailableEncodings()
return _availableEncodings; return _availableEncodings;
} }
/**
* Return the default encoding
*/
NSStringEncoding NSStringEncoding
GetDefEncoding() GetDefEncoding()
{ {
@ -294,7 +325,6 @@ GetDefEncoding()
{ {
char *encoding; char *encoding;
unsigned int count; unsigned int count;
NSStringEncoding *availableEncodings;
[gnustep_global_lock lock]; [gnustep_global_lock lock];
if (defEnc != GSUndefinedEncoding) if (defEnc != GSUndefinedEncoding)
@ -303,7 +333,7 @@ GetDefEncoding()
return defEnc; return defEnc;
} }
availableEncodings = GetAvailableEncodings(); GSSetupEncodingTable();
encoding = getenv("GNUSTEP_STRING_ENCODING"); encoding = getenv("GNUSTEP_STRING_ENCODING");
if (encoding != 0) if (encoding != 0)
@ -317,7 +347,7 @@ GetDefEncoding()
if (str_encoding_table[count].enc) if (str_encoding_table[count].enc)
{ {
defEnc = str_encoding_table[count].enc; defEnc = str_encoding_table[count].enc;
if (str_encoding_table[count].supported == 0) if (GSEncodingSupported(defEnc) == NO)
{ {
fprintf(stderr, "WARNING: %s - encoding not implemented as " fprintf(stderr, "WARNING: %s - encoding not implemented as "
"default c string encoding.\n", encoding); "default c string encoding.\n", encoding);
@ -350,8 +380,7 @@ GetDefEncoding()
BOOL BOOL
GSIsByteEncoding(NSStringEncoding encoding) GSIsByteEncoding(NSStringEncoding encoding)
{ {
GetAvailableEncodings(); if (GSEncodingSupported(encoding) == NO)
if (encoding == 0 || encoding > encTableSize || encodingTable[encoding] == 0)
{ {
return NO; return NO;
} }
@ -361,8 +390,7 @@ GSIsByteEncoding(NSStringEncoding encoding)
NSString* NSString*
GSEncodingName(NSStringEncoding encoding) GSEncodingName(NSStringEncoding encoding)
{ {
GetAvailableEncodings(); if (GSEncodingSupported(encoding) == NO)
if (encoding == 0 || encoding > encTableSize || encodingTable[encoding] == 0)
{ {
return @"Unknown encoding"; return @"Unknown encoding";
} }
@ -378,8 +406,7 @@ GetEncodingName(NSStringEncoding encoding)
static const char * static const char *
iconv_stringforencoding(NSStringEncoding encoding) iconv_stringforencoding(NSStringEncoding encoding)
{ {
GetAvailableEncodings(); if (GSEncodingSupported(encoding) == NO)
if (encoding == 0 || encoding > encTableSize || encodingTable[encoding] == 0)
{ {
return ""; return "";
} }

View file

@ -32,6 +32,7 @@ int main()
NSString *us2 = [NSString stringWithCharacters: u2 length: 7]; NSString *us2 = [NSString stringWithCharacters: u2 length: 7];
NSMutableString *fo = [NSMutableString stringWithString: @"abcdef"]; NSMutableString *fo = [NSMutableString stringWithString: @"abcdef"];
NSMutableString *f1 = [NSMutableString stringWithString: @"ab"]; NSMutableString *f1 = [NSMutableString stringWithString: @"ab"];
NSStringEncoding *encs;
NS_DURING NS_DURING
[fo replaceCharactersInRange: [fo rangeOfString: @"xx"] withString: us1]; [fo replaceCharactersInRange: [fo rangeOfString: @"xx"] withString: us1];
@ -98,6 +99,10 @@ int main()
for (i = 0; i < 1000; i++) for (i = 0; i < 1000; i++)
[base appendString: want]; [base appendString: want];
print_string(base); print_string(base);
encs = [NSString availableStringEncodings];
while (*encs != 0)
printf("Encoding %x\n", *encs++);
} }
[arp release]; [arp release];
exit(0); exit(0);