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:
parent
e07356022c
commit
eea2bf2492
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user