ICU-1739 Fix memory leaks, array offsets problems, getting the proper default converter and use uchar.h functions.

X-SVN-Rev: 8243
This commit is contained in:
George Rhoten 2002-03-26 05:33:56 +00:00
parent e07356022c
commit eea2bf2492
8 changed files with 142 additions and 123 deletions

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
*
* Copyright (C) 1998-1999, International Business Machines
* Copyright (C) 1998-2002, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
@ -21,68 +21,96 @@
#include "uhash.h"
#include "unicode/uloc.h"
#include "umutex.h"
#include "ucln.h"
/* The global cache */
UHashtable *gLocaleCache = 0;
UHashtable *gLocaleCache = NULL;
static U_EXPORT2 void U_CALLCONV
hash_freeBundle(void* obj)
{
u_locbund_delete((ULocaleBundle *)obj);
}
ULocaleBundle*
u_loccache_get(const char *loc)
{
ULocaleBundle *result;
ULocaleBundle *tempBundle;
/*Mutex *lock;*/
UHashtable *tempCache;
int32_t locCount;
UErrorCode status = U_ZERO_ERROR;
ULocaleBundle *result;
UErrorCode status = U_ZERO_ERROR;
/* Create the cache, if needed */
if(gLocaleCache == 0) {
locCount = uloc_countAvailable();
tempCache = uhash_openSize(uhash_hashChars, uhash_compareChars, locCount, &status);
if(U_FAILURE(status)) return 0;
/* Lock the cache */
umtx_lock(0);
/* Make sure it didn't change while we were acquiring the lock */
if(gLocaleCache == 0) {
gLocaleCache = tempCache;
/* Create the cache, if needed */
if(gLocaleCache == NULL) {
UHashtable *tempCache;
int32_t locCount = uloc_countAvailable();
tempCache = uhash_openSize(uhash_hashChars, uhash_compareChars, locCount, &status);
if(U_FAILURE(status))
return NULL;
uhash_setValueDeleter(tempCache, hash_freeBundle);
/* Lock the cache */
umtx_lock(NULL);
/* Make sure it didn't change while we were acquiring the lock */
if(gLocaleCache == NULL) {
gLocaleCache = tempCache;
}
else {
uhash_close(tempCache);
}
/* Unlock the cache */
umtx_unlock(NULL);
ucln_ustdio_registerCleanup();
}
else {
uhash_close(tempCache);
}
/* Unlock the cache */
umtx_unlock(0);
}
/* Try and get the bundle from the cache */
/* This will be slightly wasteful the first time around, */
/* since we know the cache will be empty. But, it simplifies */
/* the code a great deal. */
result = (ULocaleBundle*)uhash_get(gLocaleCache, loc);
/* If the bundle wasn't found, create it and add it to the cache */
if(result == 0) {
/* Create the bundle */
tempBundle = u_locbund_new(loc);
/* Try and get the bundle from the cache */
/* This will be slightly wasteful the first time around, */
/* since we know the cache will be empty. But, it simplifies */
/* the code a great deal. */
/* Lock the cache */
umtx_lock(0);
/* Make sure the cache didn't change while we were locking it */
result = (ULocaleBundle*)uhash_get(gLocaleCache, loc);
if(result == 0) {
result = tempBundle;
uhash_put(gLocaleCache, tempBundle->fLocale, tempBundle, &status);
/* If the bundle wasn't found, create it and add it to the cache */
if(result == NULL) {
/* Create the bundle */
ULocaleBundle *tempBundle = u_locbund_new(loc);
/* Lock the cache */
umtx_lock(NULL);
/* Make sure the cache didn't change while we were locking it */
result = (ULocaleBundle*)uhash_get(gLocaleCache, loc);
if(result == NULL) {
result = tempBundle;
uhash_put(gLocaleCache, tempBundle->fLocale, tempBundle, &status);
}
else {
u_locbund_delete(tempBundle);
}
/* Unlock the cache */
umtx_unlock(NULL);
}
else
u_locbund_delete(tempBundle);
/* Unlock the cache */
umtx_unlock(0);
}
return result;
return result;
}
static loccache_cleanup()
{
if (gLocaleCache) {
uhash_close(gLocaleCache);
gLocaleCache = NULL;
}
}
static UBool ustdio_cleanup(void)
{
return loccache_cleanup();
}
void ucln_ustdio_registerCleanup()
{
ucln_registerCleanup(UCLN_USTDIO, ustdio_cleanup);
}

View File

@ -27,4 +27,7 @@ extern struct UHashtable *gLocaleCache;
ULocaleBundle*
u_loccache_get(const char *loc);
/* Main library cleanup function. */
U_CFUNC void ucln_ustdio_registerCleanup(void);
#endif

View File

@ -1380,6 +1380,13 @@ u_vsnprintf_u(UChar *buffer,
alias += patCount;
}
// Release the cloned bundle, if we cloned it.
if(outStr.fOwnBundle) {
u_locbund_delete(outStr.fBundle);
outStr.fBundle = NULL;
outStr.fOwnBundle = FALSE;
}
/* return # of UChars written */
return written;
}

View File

@ -30,6 +30,7 @@
#include "unicode/uloc.h"
#include "cmemory.h"
#include "ustr_imp.h"
/* --- Prototypes ---------------------------- */
@ -343,10 +344,10 @@ u_sscanf_skip_leading_ws(u_localized_string *input,
int32_t skipped;
/* skip all leading ws in the stream */
while( ((c = input->str[count]) != 0xFFFF) && (c == pad || ufmt_isws(c)) )
while( ((c = input->str[count]) != U_EOF) && (c == pad || u_isWhitespace(c)) )
count++;
if(c == 0xFFFF)
if(c == U_EOF)
count++;
skipped = count - input->pos;
@ -392,21 +393,20 @@ u_sscanf_string_handler(u_localized_string *input,
count = 0;
/* open the default converter */
conv = ucnv_open(ucnv_getDefaultName(), &status);
conv = u_getDefaultConverter(&status);
if(U_FAILURE(status))
return -1;
/* since there is no real limit, just use a reasonable value */
limit = alias + 2048; /* TODO: Specify a real limit! */
while( ((c = input->str[input->pos++]) != 0xFFFF)
&& (c != info->fPadChar && ! ufmt_isws(c))
while( ((c = input->str[input->pos++]) != U_EOF)
&& (c != info->fPadChar && !u_isWhitespace(c))
&& (info->fWidth == -1 || count < info->fWidth) )
{
/* put the character from the stream onto the target */
source = &c;
/* Since we do this one character at a time, do it this way. */
limit = alias + ucnv_getMaxCharSize(conv);
/* convert the character to the default codepage */
ucnv_fromUnicode(conv, &alias, limit, &source, source + 1,
@ -420,14 +420,14 @@ u_sscanf_string_handler(u_localized_string *input,
}
/* put the final character we read back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
input->pos--;
/* add the terminator */
*alias = 0x00;
/* clean up */
ucnv_close(conv);
u_releaseDefaultConverter(conv);
/* we converted 1 arg */
return 1;
@ -451,8 +451,8 @@ u_sscanf_ustring_handler(u_localized_string *input,
/* get the string one character at a time, truncating to the width */
count = 0;
while( ((c = input->str[input->pos++]) != 0xFFFF)
&& (c != info->fPadChar && ! ufmt_isws(c))
while( ((c = input->str[input->pos++]) != U_EOF)
&& (c != info->fPadChar && ! u_isWhitespace(c))
&& (info->fWidth == -1 || count < info->fWidth) )
{
@ -464,7 +464,7 @@ u_sscanf_ustring_handler(u_localized_string *input,
}
/* put the final character we read back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
input->pos--;
/* add the terminator */
@ -911,7 +911,7 @@ u_sscanf_char_handler(u_localized_string *input,
uc = input->str[input->pos++];
/* handle EOF */
if(uc == 0xFFFF)
if(uc == U_EOF)
return -1;
/* convert the character to the default codepage */
@ -942,7 +942,7 @@ u_sscanf_uchar_handler(u_localized_string *input,
*c = input->str[input->pos];
/* handle EOF */
if(*c == 0xFFFF)
if(*c == U_EOF)
return -1;
/* we converted 1 arg */
@ -1145,14 +1145,14 @@ u_sscanf_scanset_handler(u_localized_string *input,
++(*consumed);
/* open the default converter */
conv = ucnv_open(ucnv_getDefaultName(), &status);
conv = u_getDefaultConverter(&status);
/* verify that the parse was successful and the converter opened */
if(! success || U_FAILURE(status))
return -1;
/* grab characters one at a time and make sure they are in the scanset */
while( (c = input->str[input->pos++]) != 0xFFFF && alias < limit) {
while( (c = input->str[input->pos++]) != U_EOF && alias < limit) {
if(u_scanf_scanset_in(&scanset, c)) {
source = &c;
/* convert the character to the default codepage */
@ -1169,7 +1169,7 @@ u_sscanf_scanset_handler(u_localized_string *input,
}
/* put the final character we read back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
input->pos--;
/* if we didn't match at least 1 character, fail */
@ -1180,7 +1180,7 @@ u_sscanf_scanset_handler(u_localized_string *input,
*alias = 0x00;
/* clean up */
ucnv_close(conv);
u_releaseDefaultConverter(conv);
/* we converted 1 arg */
return 1;

View File

@ -109,19 +109,6 @@ ufmt_utol(const UChar *buffer,
return result;
}
UBool
ufmt_isws(UChar c)
{
return (UBool)(c == 0x0020 || /* space */
c == 0x0009 || /* tab */
c == 0x000D || /* CR */
c == 0x000A || /* LF */
c == 0x000B || /* vertical tab */
c == 0x000C || /* form feed */
u_isspace(c));
}
UChar*
ufmt_defaultCPToUnicode(const char *s,
int32_t len)

View File

@ -67,7 +67,7 @@ typedef union ufmt_args ufmt_args;
#define ufmt_min(a,b) ((a) < (b) ? (a) : (b))
/**
* Convert a UChar in a some radix to an integer value.
* Convert a UChar in hex radix to an integer value.
* @param c The UChar to convert.
* @return The integer value of <TT>c</TT>.
*/
@ -116,17 +116,6 @@ ufmt_utol(const UChar *buffer,
int32_t *len,
int32_t radix);
/**
* Determine if a UChar is a whitespace character.
* @param c The UChar to test.
* @return TRUE if the UChar is a space (U+0020), tab (U+0009),
* carriage-return (U+000D), newline (U+000A), vertical-tab (U+000B),
* form-feed (U+000C), or any other Unicode-defined space, line, or paragraph
* separator.
*/
UBool
ufmt_isws(UChar c);
/**
* Convert a string from the default codepage to Unicode.
* @param s The string to convert, in the default codepage.

View File

@ -30,6 +30,7 @@
#include "unicode/udat.h"
#include "cmemory.h"
#include "ustr_imp.h"
/* --- Prototypes ---------------------------- */
@ -339,11 +340,11 @@ u_scanf_skip_leading_ws(UFILE *stream,
int32_t count = 0;
/* skip all leading ws in the stream */
while( ((c = u_fgetc(stream)) != 0xFFFF) && (c == pad || ufmt_isws(c)) )
while( ((c = u_fgetc(stream)) != U_EOF) && (c == pad || u_isWhitespace(c)) )
++count;
/* put the final character back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
u_fungetc(c, stream);
return count;
@ -386,20 +387,20 @@ u_scanf_string_handler(UFILE *stream,
count = 0;
/* open the default converter */
conv = ucnv_open(ucnv_getDefaultName(), &status);
conv = u_getDefaultConverter(&status);
if(U_FAILURE(status))
return -1;
/* since there is no real limit, just use a reasonable value */
limit = alias + 2048; /* TODO: Specify a real limit! */
while( ((c = u_fgetc(stream)) != 0xFFFF) &&
(c != info->fPadChar && ! ufmt_isws(c)) &&
(info->fWidth == -1 || count < info->fWidth) ) {
while( ((c = u_fgetc(stream)) != U_EOF) &&
(c != info->fPadChar && !u_isWhitespace(c)) &&
(info->fWidth == -1 || count < info->fWidth) )
{
/* put the character from the stream onto the target */
source = &c;
/* Since we do this one character at a time, do it this way. */
limit = alias + ucnv_getMaxCharSize(conv);
/* convert the character to the default codepage */
ucnv_fromUnicode(conv, &alias, limit, &source, source + 1,
@ -413,14 +414,14 @@ u_scanf_string_handler(UFILE *stream,
}
/* put the final character we read back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
u_fungetc(c, stream);
/* add the terminator */
*alias = 0x00;
/* clean up */
ucnv_close(conv);
u_releaseDefaultConverter(conv);
/* we converted 1 arg */
return 1;
@ -444,8 +445,8 @@ u_scanf_ustring_handler(UFILE *stream,
/* get the string one character at a time, truncating to the width */
count = 0;
while( ((c = u_fgetc(stream)) != 0xFFFF) &&
(c != info->fPadChar && ! ufmt_isws(c)) &&
while( ((c = u_fgetc(stream)) != U_EOF) &&
(c != info->fPadChar && ! u_isWhitespace(c)) &&
(info->fWidth == -1 || count < info->fWidth) ) {
/* put the character from the stream onto the target */
@ -456,7 +457,7 @@ u_scanf_ustring_handler(UFILE *stream,
}
/* put the final character we read back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
u_fungetc(c, stream);
/* add the terminator */
@ -923,7 +924,7 @@ u_scanf_char_handler(UFILE *stream,
uc = u_fgetc(stream);
/* handle EOF */
if(uc == 0xFFFF)
if(uc == U_EOF)
return -1;
/* convert the character to the default codepage */
@ -954,7 +955,7 @@ u_scanf_uchar_handler(UFILE *stream,
*c = u_fgetc(stream);
/* handle EOF */
if(*c == 0xFFFF)
if(*c == U_EOF)
return -1;
/* we converted 1 arg */
@ -1172,14 +1173,14 @@ u_scanf_scanset_handler(UFILE *stream,
++(*consumed);
/* open the default converter */
conv = ucnv_open(ucnv_getDefaultName(), &status);
conv = u_getDefaultConverter(&status);
/* verify that the parse was successful and the converter opened */
if(! success || U_FAILURE(status))
return -1;
/* grab characters one at a time and make sure they are in the scanset */
while( (c = u_fgetc(stream)) != 0xFFFF && alias < limit) {
while( (c = u_fgetc(stream)) != U_EOF && alias < limit) {
if(u_scanf_scanset_in(&scanset, c)) {
source = &c;
/* convert the character to the default codepage */
@ -1196,7 +1197,7 @@ u_scanf_scanset_handler(UFILE *stream,
}
/* put the final character we read back on the stream */
if(c != 0xFFFF)
if(c != U_EOF)
u_fungetc(c, stream);
/* if we didn't match at least 1 character, fail */
@ -1207,7 +1208,7 @@ u_scanf_scanset_handler(UFILE *stream,
*alias = 0x00;
/* clean up */
ucnv_close(conv);
u_releaseDefaultConverter(conv);
/* we converted 1 arg */
return 1;

View File

@ -282,6 +282,7 @@ u_file_write_flush( const UChar *chars,
char *myTarget = f->fCharBuffer;
int32_t bufferSize = UFILE_CHARBUFFER_SIZE;
int32_t written = 0;
int32_t numConverted = 0;
if((f->fTranslit) && (f->fTranslit->translit))
{
@ -308,14 +309,17 @@ u_file_write_flush( const UChar *chars,
u_UCharsToChars(mySource, myTarget, count);
myTarget += count;
}
numConverted = (myTarget - f->fCharBuffer);
/* write the converted bytes */
fwrite(f->fCharBuffer,
sizeof(char),
myTarget - f->fCharBuffer,
f->fFile);
if (numConverted > 0) {
/* write the converted bytes */
fwrite(f->fCharBuffer,
sizeof(char),
numConverted,
f->fFile);
written += (myTarget - f->fCharBuffer);
written += numConverted;
}
myTarget = f->fCharBuffer;
}
while(status == U_BUFFER_OVERFLOW_ERROR);