ICU-770 Change code for u_cleanup() API.

X-SVN-Rev: 5462
This commit is contained in:
George Rhoten 2001-08-11 00:29:58 +00:00
parent 59e51a0248
commit f850ad2c5e
10 changed files with 465 additions and 306 deletions

View File

@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMMON_EXPORTS" /YX /FD /c
# ADD CPP /nologo /G6 /MD /W3 /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMMON_EXPORTS" /D "U_COMMON_IMPLEMENTATION" /D "UDATA_STATIC_LIB" /FD /c
# ADD CPP /nologo /G6 /MD /Za /W3 /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMMON_EXPORTS" /D "U_COMMON_IMPLEMENTATION" /D "UDATA_STATIC_LIB" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
@ -216,6 +216,10 @@ SOURCE=.\uchriter.cpp
# End Source File
# Begin Source File
SOURCE=.\ucln_cmn.c
# End Source File
# Begin Source File
SOURCE=.\ucmp16.c
# ADD CPP /Za
# End Source File
@ -827,6 +831,37 @@ InputPath=.\unicode\uchriter.h
# End Source File
# Begin Source File
SOURCE=.\unicode\uclean.h
!IF "$(CFG)" == "common - Win32 Release"
# Begin Custom Build
InputPath=.\unicode\uclean.h
"..\..\include\unicode\uclean.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(InputPath) ..\..\include\unicode
# End Custom Build
!ELSEIF "$(CFG)" == "common - Win32 Debug"
# Begin Custom Build
InputPath=.\unicode\uclean.h
"..\..\include\unicode\uclean.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(InputPath) ..\..\include\unicode
# End Custom Build
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\ucln_cmn.h
# End Source File
# Begin Source File
SOURCE=.\ucmp16.h
# End Source File
# Begin Source File

View File

@ -0,0 +1,27 @@
/*
******************************************************************************
* *
* Copyright (C) 2001-2001, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
* file name: ucln_cmn.c
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2001July05
* created by: George Rhoten
*/
#include "unicode/uclean.h"
#include "ucln_cmn.h"
#include "umutex.h"
void u_cleanup(void)
{
ucln_uloc();
ucln_ustring();
ucln_ucnv();
ucln_ures();
}

View File

@ -0,0 +1,30 @@
/*
******************************************************************************
* *
* Copyright (C) 2001-2001, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
* file name: ucln_cmn.h
* encoding: US-ASCII
* tab size: 8 (not used)
* indentation:4
*
* created on: 2001July05
* created by: George Rhoten
*/
#ifndef __UCLN_CMN_H__
#define __UCLN_CMN_H__
#include "unicode/utypes.h"
U_CAPI UBool U_EXPORT2 ucln_ucnv(void);
U_CAPI UBool U_EXPORT2 ucln_ures(void);
U_CAPI UBool U_EXPORT2 ucln_uloc(void);
U_CAPI UBool U_EXPORT2 ucln_ustring(void);
#endif

View File

@ -32,6 +32,7 @@
#include "cstring.h"
#include "cmemory.h"
#include "filestrm.h"
#include "ucln_cmn.h"
#if 0
@ -113,13 +114,19 @@ U_CAPI UConverterSharedData* U_EXPORT2 ucnv_data_unFlattenClone(UDataMemory *pD
/*initializes some global variables */
UHashtable *SHARED_DATA_HASHTABLE = NULL;
#if 0
/* For MEMORY LEAK checking.. */
U_CAPI void U_EXPORT2 ucnv_orphanAllConverters()
{
SHARED_DATA_HASHTABLE = NULL; /* will leak: hashtable + hashtable elements */
/* The calling function uses the global mutex, so there is no need to use it here too */
UBool ucln_ucnv(void) {
if (SHARED_DATA_HASHTABLE != NULL) {
ucnv_flushCache();
umtx_lock(NULL);
if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
uhash_close(SHARED_DATA_HASHTABLE);
SHARED_DATA_HASHTABLE = NULL;
}
umtx_unlock(NULL);
}
return (SHARED_DATA_HASHTABLE == NULL);
}
#endif
static UBool
isCnvAcceptable(void *context,
@ -141,125 +148,128 @@ isCnvAcceptable(void *context,
static UConverterSharedData *createConverterFromFile (const char *fileName, UErrorCode * err)
{
UDataMemory *data;
UConverterSharedData *sharedData;
UDataMemory *data;
UConverterSharedData *sharedData;
if (err == NULL || U_FAILURE (*err)) {
return NULL;
}
data = udata_openChoice(NULL, DATA_TYPE, fileName, isCnvAcceptable, NULL, err);
if(U_FAILURE(*err))
{
return NULL;
if (err == NULL || U_FAILURE (*err)) {
return NULL;
}
sharedData = ucnv_data_unFlattenClone(data, err);
if(U_FAILURE(*err))
data = udata_openChoice(NULL, DATA_TYPE, fileName, isCnvAcceptable, NULL, err);
if(U_FAILURE(*err))
{
udata_close(data);
return NULL;
return NULL;
}
return sharedData;
sharedData = ucnv_data_unFlattenClone(data, err);
if(U_FAILURE(*err))
{
udata_close(data);
return NULL;
}
return sharedData;
}
void
copyPlatformString (char *platformString, UConverterPlatform pltfrm)
copyPlatformString(char *platformString, UConverterPlatform pltfrm)
{
switch (pltfrm)
switch (pltfrm)
{
case UCNV_IBM:
{
uprv_strcpy (platformString, "ibm");
break;
}
{
uprv_strcpy (platformString, "ibm");
break;
}
default:
{
uprv_strcpy (platformString, "");
break;
}
{
uprv_strcpy (platformString, "");
break;
}
};
return;
return;
}
/*returns a converter type from a string
*/
static const UConverterSharedData *
getAlgorithmicTypeFromName (const char *realName)
getAlgorithmicTypeFromName(const char *realName)
{
int i;
for(i=0; i<sizeof(cnvNameType)/sizeof(cnvNameType[0]); ++i) {
if(uprv_strcmp(realName, cnvNameType[i].name)==0) {
return converterData[cnvNameType[i].type];
int i;
for(i=0; i<sizeof(cnvNameType)/sizeof(cnvNameType[0]); ++i) {
if(uprv_strcmp(realName, cnvNameType[i].name)==0) {
return converterData[cnvNameType[i].type];
}
}
}
return NULL;
return NULL;
}
/*Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */
void shareConverterData (UConverterSharedData * data)
void shareConverterData(UConverterSharedData * data)
{
UErrorCode err = U_ZERO_ERROR;
/*Lazy evaluates the Hashtable itself */
/*void *sanity = NULL;*/
UErrorCode err = U_ZERO_ERROR;
/*Lazy evaluates the Hashtable itself */
/*void *sanity = NULL;*/
if (SHARED_DATA_HASHTABLE == NULL)
if (SHARED_DATA_HASHTABLE == NULL)
{
UHashtable* myHT = uhash_openSize (uhash_hashIChars, uhash_compareIChars,
ucnv_io_countAvailableAliases(&err),
&err);
if (U_FAILURE (err)) return;
umtx_lock (NULL);
if (SHARED_DATA_HASHTABLE == NULL) SHARED_DATA_HASHTABLE = myHT;
else uhash_close(myHT);
umtx_unlock (NULL);
UHashtable* myHT = uhash_openSize (uhash_hashIChars, uhash_compareIChars,
ucnv_io_countAvailableAliases(&err),
&err);
if (U_FAILURE(err))
return;
umtx_lock(NULL);
if (SHARED_DATA_HASHTABLE == NULL)
SHARED_DATA_HASHTABLE = myHT;
else
uhash_close(myHT);
umtx_unlock(NULL);
}
umtx_lock (NULL);
/* ### check to see if the element is not already there! */
umtx_lock (NULL);
/* ### check to see if the element is not already there! */
/*
/*
sanity = getSharedConverterData (data->staticData->name);
if(sanity != NULL)
{
UCNV_DEBUG_LOG("put:overwrite!",data->staticData->name,sanity);
UCNV_DEBUG_LOG("put:overwrite!",data->staticData->name,sanity);
}
UCNV_DEBUG_LOG("put:chk",data->staticData->name,sanity);
*/
*/
uhash_put(SHARED_DATA_HASHTABLE,
(void*) data->staticData->name, /* Okay to cast away const as long as
keyDeleter == NULL */
uhash_put(SHARED_DATA_HASHTABLE,
(void*) data->staticData->name, /* Okay to cast away const as long as
keyDeleter == NULL */
data,
&err);
UCNV_DEBUG_LOG("put",data->staticData->name,data);
umtx_unlock (NULL);
return;
UCNV_DEBUG_LOG("put", data->staticData->name,data);
umtx_unlock (NULL);
}
UConverterSharedData *getSharedConverterData (const char *name)
UConverterSharedData *getSharedConverterData(const char *name)
{
/*special case when no Table has yet been created we return NULL */
if (SHARED_DATA_HASHTABLE == NULL) return NULL;
else
/*special case when no Table has yet been created we return NULL */
if (SHARED_DATA_HASHTABLE == NULL)
{
UConverterSharedData *rc;
return NULL;
}
else
{
UConverterSharedData *rc;
umtx_lock(NULL);
rc = (UConverterSharedData*)uhash_get (SHARED_DATA_HASHTABLE, name);
rc = (UConverterSharedData*)uhash_get(SHARED_DATA_HASHTABLE, name);
umtx_unlock(NULL);
UCNV_DEBUG_LOG("get",name,rc);
return rc;
UCNV_DEBUG_LOG("get",name,rc);
return rc;
}
}
/*frees the string of memory blocks associates with a sharedConverter
*if and only if the referenceCounter == 0
*/
UBool deleteSharedConverterData (UConverterSharedData * deadSharedData)
UBool deleteSharedConverterData(UConverterSharedData * deadSharedData)
{
if (deadSharedData->referenceCounter > 0)
return FALSE;
@ -279,7 +289,7 @@ UBool deleteSharedConverterData (UConverterSharedData * deadSharedData)
uprv_free(deadSharedData->table);
}
uprv_free (deadSharedData);
uprv_free(deadSharedData);
return TRUE;
}
@ -355,111 +365,111 @@ parseConverterOptions(const char *inName,
* -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE)
*/
UConverter *
createConverter (const char *converterName, UErrorCode * err)
createConverter (const char *converterName, UErrorCode * err)
{
char cnvName[100], locale[20];
const char *realName;
UConverter *myUConverter = NULL;
UConverterSharedData *mySharedConverterData = NULL;
UErrorCode internalErrorCode = U_ZERO_ERROR;
uint32_t options=0;
if (U_FAILURE (*err))
return NULL;
char cnvName[100], locale[20];
const char *realName;
UConverter *myUConverter = NULL;
UConverterSharedData *mySharedConverterData = NULL;
UErrorCode internalErrorCode = U_ZERO_ERROR;
uint32_t options=0;
if (U_FAILURE (*err))
return NULL;
locale[0] = 0;
locale[0] = 0;
/* In case "name" is NULL we want to open the default converter. */
if (converterName == NULL) {
realName = ucnv_io_getDefaultConverterName();
if (realName == NULL) {
*err = U_MISSING_RESOURCE_ERROR;
return NULL;
/* In case "name" is NULL we want to open the default converter. */
if (converterName == NULL) {
realName = ucnv_io_getDefaultConverterName();
if (realName == NULL) {
*err = U_MISSING_RESOURCE_ERROR;
return NULL;
}
/* the default converter name is already canonical */
} else {
/* separate the converter name from the options */
parseConverterOptions(converterName, cnvName, locale,&options);
/* get the canonical converter name */
realName = ucnv_io_getConverterName(cnvName, &internalErrorCode);
if (U_FAILURE(internalErrorCode) || realName == NULL) {
/*
* set the input name in case the converter was added
* without updating the alias table, or when there is no alias table
*/
realName = cnvName;
}
}
/* the default converter name is already canonical */
} else {
/* separate the converter name from the options */
parseConverterOptions(converterName, cnvName, locale,&options);
/* get the canonical converter name */
realName = ucnv_io_getConverterName(cnvName, &internalErrorCode);
if (U_FAILURE(internalErrorCode) || realName == NULL) {
/*
* set the input name in case the converter was added
* without updating the alias table, or when there is no alias table
*/
realName = cnvName;
if(realName != cnvName) {
parseConverterOptions(realName, cnvName, locale,&options);
realName = cnvName;
}
}
/* separate the converter name from the options */
if(realName != cnvName) {
parseConverterOptions(realName, cnvName, locale,&options);
realName = cnvName;
}
/* get the shared data for an algorithmic converter, if it is one */
mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName (realName);
if (mySharedConverterData == NULL)
/* get the shared data for an algorithmic converter, if it is one */
mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName (realName);
if (mySharedConverterData == NULL)
{
/* it is a data-based converter, get its shared data */
mySharedConverterData = getSharedConverterData (realName);
if (mySharedConverterData == NULL)
/* it is a data-based converter, get its shared data */
mySharedConverterData = getSharedConverterData (realName);
if (mySharedConverterData == NULL)
{
/*Not cached, we need to stream it in from file */
mySharedConverterData = createConverterFromFile (realName, err);
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
/*Not cached, we need to stream it in from file */
mySharedConverterData = createConverterFromFile (realName, err);
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
{
return NULL;
return NULL;
}
else
else
{
/* share it with other library clients */
shareConverterData (mySharedConverterData);
/* share it with other library clients */
shareConverterData(mySharedConverterData);
}
}
else
else
{
/* ### this is unsafe: the shared data could have been deleted since sharing or getting it - these operations should increase the counter! */
/* update the reference counter: one more client */
umtx_lock (NULL);
mySharedConverterData->referenceCounter++;
umtx_unlock (NULL);
/* ### this is unsafe: the shared data could have been deleted since sharing or getting it - these operations should increase the counter! */
/* update the reference counter: one more client */
umtx_lock (NULL);
mySharedConverterData->referenceCounter++;
umtx_unlock (NULL);
}
}
/* allocate the converter */
myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
if (myUConverter == NULL)
/* allocate the converter */
myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
if (myUConverter == NULL)
{
if (mySharedConverterData->referenceCounter != ~0) {
umtx_lock (NULL);
--mySharedConverterData->referenceCounter;
umtx_unlock (NULL);
}
*err = U_MEMORY_ALLOCATION_ERROR;
return NULL;
if (mySharedConverterData->referenceCounter != ~0) {
umtx_lock (NULL);
--mySharedConverterData->referenceCounter;
umtx_unlock (NULL);
}
*err = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
/* initialize the converter */
uprv_memset(myUConverter, 0, sizeof(UConverter));
myUConverter->sharedData = mySharedConverterData;
myUConverter->mode = UCNV_SI;
myUConverter->fromCharErrorBehaviour = (UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE;
myUConverter->fromUCharErrorBehaviour = (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE;
myUConverter->toUnicodeStatus = myUConverter->sharedData->toUnicodeStatus;
myUConverter->subChar1 = myUConverter->sharedData->staticData->subChar1;
myUConverter->subCharLen = myUConverter->sharedData->staticData->subCharLen;
uprv_memcpy (myUConverter->subChar, myUConverter->sharedData->staticData->subChar, myUConverter->subCharLen);
/* initialize the converter */
uprv_memset(myUConverter, 0, sizeof(UConverter));
myUConverter->sharedData = mySharedConverterData;
myUConverter->mode = UCNV_SI;
myUConverter->fromCharErrorBehaviour = (UConverterToUCallback) UCNV_TO_U_CALLBACK_SUBSTITUTE;
myUConverter->fromUCharErrorBehaviour = (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_SUBSTITUTE;
myUConverter->toUnicodeStatus = myUConverter->sharedData->toUnicodeStatus;
myUConverter->subChar1 = myUConverter->sharedData->staticData->subChar1;
myUConverter->subCharLen = myUConverter->sharedData->staticData->subCharLen;
uprv_memcpy (myUConverter->subChar, myUConverter->sharedData->staticData->subChar, myUConverter->subCharLen);
if(myUConverter != NULL && myUConverter->sharedData->impl->open != NULL) {
myUConverter->sharedData->impl->open(myUConverter, realName, locale,options, err);
if(U_FAILURE(*err)) {
ucnv_close(myUConverter);
return NULL;
if(myUConverter != NULL && myUConverter->sharedData->impl->open != NULL) {
myUConverter->sharedData->impl->open(myUConverter, realName, locale,options, err);
if(U_FAILURE(*err)) {
ucnv_close(myUConverter);
return NULL;
}
}
}
return myUConverter;
return myUConverter;
}
UConverterSharedData* ucnv_data_unFlattenClone(UDataMemory *pData, UErrorCode *status)

View File

@ -37,6 +37,7 @@
#include "cstring.h"
#include "unicode/ustring.h"
#include "cmemory.h"
#include "ucln_cmn.h"
/****************************************************************************
Global variable and type definitions
@ -1219,11 +1220,34 @@ uloc_getAvailable(int32_t offset)
int32_t uloc_countAvailable()
{
if (_installedLocales == NULL) _lazyEvaluate_installedLocales();
if (_installedLocales == NULL)
_lazyEvaluate_installedLocales();
return _installedLocalesCount;
}
UBool ucln_uloc(void) {
char ** temp;
int32_t localeCount;
int32_t i;
umtx_lock(NULL);
temp = _installedLocales;
_installedLocales = NULL;
localeCount = _installedLocalesCount;
_installedLocalesCount = 0;
umtx_unlock(NULL);
for (i = 0; i < localeCount; i++) {
uprv_free(temp[i]);
}
uprv_free(temp);
return TRUE;
}
static void _lazyEvaluate_installedLocales()
{
UResourceBundle *index = NULL;
@ -1233,15 +1257,16 @@ static void _lazyEvaluate_installedLocales()
char ** temp;
int32_t i = 0;
int32_t len = 0;
int32_t localeCount;
ures_setIsStackObject(&installed, TRUE);
index = ures_open(NULL, kIndexLocaleName, &status);
ures_getByKey(index, kIndexTag, &installed, &status);
if(U_SUCCESS(status)) {
_installedLocalesCount = ures_getSize(&installed);
temp = (char **) uprv_malloc(sizeof(char*) * (_installedLocalesCount+1));
localeCount = ures_getSize(&installed);
temp = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
ures_resetIterator(&installed);
while(ures_hasNext(&installed)) {
lname = ures_getNextString(&installed, &len, NULL, &status);
@ -1251,19 +1276,20 @@ static void _lazyEvaluate_installedLocales()
temp[i][len] = 0; /* Terminate the string */
i++;
}
umtx_lock(NULL);
if (_installedLocales == NULL)
{
umtx_lock(NULL);
if (_installedLocales == NULL)
{
_installedLocales = temp;
temp = NULL;
} else {
for (i = 0; i < _installedLocalesCount; i++) uprv_free(temp[i]);
uprv_free(temp);
_installedLocales = temp;
_installedLocalesCount = localeCount;
} else {
for (i = 0; i < localeCount; i++) {
uprv_free(temp[i]);
}
umtx_unlock(NULL);
uprv_free(temp);
}
umtx_unlock(NULL);
ures_close(&installed);
}
ures_close(index);

View File

@ -88,8 +88,6 @@ us_arrayCopy(const UChar *src, int32_t srcStart,
}
}
UConverter* UnicodeString::fgDefaultConverter = 0;
//========================================
// Constructors
//========================================
@ -1270,7 +1268,7 @@ UnicodeString::extract(UTextOffset start,
// if the codepage is the default, use our cache
// if it is an empty string, then use the "invariant character" conversion
if (codepage == 0) {
converter = getDefaultConverter(status);
converter = u_getDefaultConverter(&status);
} else if (*codepage == 0) {
// use the "invariant characters" conversion
if (length > fLength - start) {
@ -1329,7 +1327,7 @@ UnicodeString::extract(UTextOffset start,
// close the converter
if (codepage == 0) {
releaseDefaultConverter(converter);
u_releaseDefaultConverter(converter);
} else {
ucnv_close(converter);
}
@ -1353,7 +1351,7 @@ UnicodeString::doCodepageCreate(const char *codepageData,
// if the codepage is the default, use our cache
// if it is an empty string, then use the "invariant character" conversion
UConverter *converter = (codepage == 0 ?
getDefaultConverter(status) :
u_getDefaultConverter(&status) :
*codepage == 0 ?
0 :
ucnv_open(codepage, &status));
@ -1419,7 +1417,7 @@ UnicodeString::doCodepageCreate(const char *codepageData,
// close the converter
if(codepage == 0) {
releaseDefaultConverter(converter);
u_releaseDefaultConverter(converter);
} else {
ucnv_close(converter);
}
@ -1525,54 +1523,3 @@ UnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
return TRUE;
}
//========================================
// Default converter caching
//========================================
UConverter*
UnicodeString::getDefaultConverter(UErrorCode &status)
{
UConverter *converter = 0;
if(fgDefaultConverter != 0) {
Mutex lock;
// need to check to make sure it wasn't taken out from under us
if(fgDefaultConverter != 0) {
converter = fgDefaultConverter;
fgDefaultConverter = 0;
}
}
// if the cache was empty, create a converter
if(converter == 0) {
converter = ucnv_open(0, &status);
if(U_FAILURE(status)) {
return 0;
}
}
return converter;
}
void
UnicodeString::releaseDefaultConverter(UConverter *converter)
{
if(fgDefaultConverter == 0) {
if (converter != 0) {
ucnv_reset(converter);
}
Mutex lock;
if(fgDefaultConverter == 0) {
fgDefaultConverter = converter;
converter = 0;
}
}
// it's safe to close a 0 converter
ucnv_close(converter);
}

View File

@ -20,6 +20,7 @@
#include "uresimp.h"
#include "cwchar.h"
#include "ucln_cmn.h"
/* this is just for internal purposes. DO NOT USE! */
static void entryCloseInt(UResourceDataEntry *resB);
@ -158,6 +159,68 @@ static void initCache(UErrorCode *status) {
}
}
/* Works just like ucnv_flushCache() */
static int32_t ures_flushCache()
{
UResourceDataEntry *resB = NULL;
int32_t pos = -1;
int32_t rbDeletedNum = 0;
const UHashElement *e;
/*if shared data hasn't even been lazy evaluated yet
* return 0
*/
if (cache == NULL)
return 0;
/*creates an enumeration to iterate through every element in the table */
umtx_lock(&resbMutex);
while ((e = uhash_nextElement(cache, &pos)) != NULL)
{
resB = (UResourceDataEntry *) e->value;
/* Deletes only if reference counter == 0
* Don't worry about the children of this node.
* Those will eventually get deleted too, if not already.
* Don't worry about the parents of this node.
* Those will eventually get deleted too, if not already.
*/
if (resB->fCountExisting == 0)
{
rbDeletedNum++;
uhash_removeElement(cache, e);
if(resB->fBogus == U_ZERO_ERROR) {
res_unload(&(resB->fData));
}
if(resB->fName != NULL) {
uprv_free(resB->fName);
}
if(resB->fPath != NULL) {
uprv_free(resB->fPath);
}
uprv_free(resB);
}
}
umtx_unlock(&resbMutex);
return rbDeletedNum;
}
UBool ucln_ures(void)
{
if (cache != NULL) {
ures_flushCache();
umtx_lock(NULL);
if (cache != NULL && uhash_count(cache) == 0) {
uhash_close(cache);
cache = NULL;
umtx_destroy(&resbMutex);
}
umtx_unlock(NULL);
}
return (cache == NULL);
}
/** INTERNAL: sets the name (locale) of the resource bundle to given name */
static void setEntryName(UResourceDataEntry *res, char *name, UErrorCode *status) {
@ -891,11 +954,10 @@ static void entryCloseInt(UResourceDataEntry *resB) {
p = resB->fParent;
resB->fCountExisting--;
if(resB->fCountExisting <= 0) {
/* Entries are left in the cache. TODO: add ures_cacheFlush() to force a flush
of the cache. */
/* Entries are left in the cache. TODO: add ures_cacheFlush() to force a flush
of the cache. */
/*
if(resB->fCountExisting <= 0) {
uhash_remove(cache, resB);
if(resB->fBogus == U_ZERO_ERROR) {
res_unload(&(resB->fData));
@ -907,8 +969,8 @@ static void entryCloseInt(UResourceDataEntry *resB) {
uprv_free(resB->fPath);
}
uprv_free(resB);
*/
}
*/
resB = p;
}

View File

@ -16,6 +16,7 @@
#define __USTR_IMP_H__
#include "unicode/utypes.h"
#include "unicode/ucnv.h"
/**
* Are the Unicode properties loaded?
@ -109,4 +110,21 @@ u_internalStrcasecmp(const UChar *s1, int32_t length1,
U_CFUNC uint8_t
u_internalGetCombiningClass(UChar32 c);
/**
* Get the default converter. This is a commonly used converter
* that is used for the ustring and UnicodeString API.
* Remember to use the u_releaseDefaultConverter when you are done.
* @internal
*/
U_CFUNC UConverter*
u_getDefaultConverter(UErrorCode *status);
/**
* Release the default converter to the converter cache.
* @internal
*/
U_CFUNC void
u_releaseDefaultConverter(UConverter *converter);
#endif

View File

@ -16,34 +16,25 @@
#include "unicode/utypes.h"
#include "unicode/ustream.h"
#include "unicode/ucnv.h"
#if U_IOSTREAM_SOURCE >= 199711
using namespace std;
#elif U_IOSTREAM_SOURCE >= 198506
#endif
#include "ustr_imp.h"
class UnicodeStreamer {
public:
inline static const UChar *getArrayStart(const UnicodeString& s) {return s.getArrayStart();}
inline static UConverter *getDefaultConverter(UErrorCode &err) {return UnicodeString::getDefaultConverter(err);}
inline static void releaseDefaultConverter(UConverter *conv) {UnicodeString::releaseDefaultConverter(conv);}
};
// console IO
#if U_IOSTREAM_SOURCE >= 198506
#if U_IOSTREAM_SOURCE >= 199711
U_COMMON_API std::ostream &
operator<<(std::ostream& stream, const UnicodeString& s)
#define STD_OSTREAM std::ostream
#else
U_COMMON_API ostream &
operator<<(ostream& stream, const UnicodeString& s)
#define STD_OSTREAM ostream
#endif
U_COMMON_API STD_OSTREAM &
operator<<(STD_OSTREAM& stream, const UnicodeString& s)
{
if(s.length() > 0) {
char buffer[200];
@ -51,7 +42,7 @@ operator<<(ostream& stream, const UnicodeString& s)
UErrorCode errorCode = U_ZERO_ERROR;
// use the default converter to convert chunks of text
converter = UnicodeStreamer::getDefaultConverter(errorCode);
converter = u_getDefaultConverter(&errorCode);
if(U_SUCCESS(errorCode)) {
const UChar *us = UnicodeStreamer::getArrayStart(s);
const UChar *uLimit = us + s.length();
@ -66,7 +57,7 @@ operator<<(ostream& stream, const UnicodeString& s)
stream.write(buffer, s - buffer);
}
} while(errorCode == U_BUFFER_OVERFLOW_ERROR);
UnicodeStreamer::releaseDefaultConverter(converter);
u_releaseDefaultConverter(converter);
}
}

View File

@ -24,16 +24,11 @@
#include "cmemory.h"
#include "umutex.h"
#include "ustr_imp.h"
#include "ucln_cmn.h"
/* forward declaractions of definitions for the shared default converter */
static UConverter *fgDefaultConverter = NULL;
static UConverter*
getDefaultConverter(void);
static void
releaseDefaultConverter(UConverter *converter);
static UConverter *gDefaultConverter = NULL;
/* ANSI string.h - style functions ------------------------------------------ */
@ -878,9 +873,9 @@ UChar* u_uastrncpy(UChar *ucs1,
int32_t n)
{
UChar *target = ucs1;
UConverter *cnv = getDefaultConverter();
if(cnv != NULL) {
UErrorCode err = U_ZERO_ERROR;
UErrorCode err = U_ZERO_ERROR;
UConverter *cnv = u_getDefaultConverter(&err);
if(U_SUCCESS(err) && cnv != NULL) {
ucnv_reset(cnv);
ucnv_toUnicode(cnv,
&target,
@ -891,7 +886,7 @@ UChar* u_uastrncpy(UChar *ucs1,
TRUE,
&err);
ucnv_reset(cnv); /* be good citizens */
releaseDefaultConverter(cnv);
u_releaseDefaultConverter(cnv);
if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
*ucs1 = 0; /* failure */
}
@ -907,16 +902,16 @@ UChar* u_uastrncpy(UChar *ucs1,
UChar* u_uastrcpy(UChar *ucs1,
const char *s2 )
{
UConverter *cnv = getDefaultConverter();
if(cnv != NULL) {
UErrorCode err = U_ZERO_ERROR;
UErrorCode err = U_ZERO_ERROR;
UConverter *cnv = u_getDefaultConverter(&err);
if(U_SUCCESS(err) && cnv != NULL) {
ucnv_toUChars(cnv,
ucs1,
MAX_STRLEN,
s2,
uprv_strlen(s2),
&err);
releaseDefaultConverter(cnv);
u_releaseDefaultConverter(cnv);
if(U_FAILURE(err)) {
*ucs1 = 0;
}
@ -948,9 +943,9 @@ char* u_austrncpy(char *s1,
int32_t n)
{
char *target = s1;
UConverter *cnv = getDefaultConverter();
if(cnv != NULL) {
UErrorCode err = U_ZERO_ERROR;
UErrorCode err = U_ZERO_ERROR;
UConverter *cnv = u_getDefaultConverter(&err);
if(U_SUCCESS(err) && cnv != NULL) {
ucnv_reset(cnv);
ucnv_fromUnicode(cnv,
&target,
@ -961,7 +956,7 @@ char* u_austrncpy(char *s1,
TRUE,
&err);
ucnv_reset(cnv); /* be good citizens */
releaseDefaultConverter(cnv);
u_releaseDefaultConverter(cnv);
if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
*s1 = 0; /* failure */
}
@ -977,16 +972,16 @@ char* u_austrncpy(char *s1,
char* u_austrcpy(char *s1,
const UChar *ucs2 )
{
UConverter *cnv = getDefaultConverter();
if(cnv != NULL) {
UErrorCode err = U_ZERO_ERROR;
UErrorCode err = U_ZERO_ERROR;
UConverter *cnv = u_getDefaultConverter(&err);
if(U_SUCCESS(err) && cnv != NULL) {
int32_t len = ucnv_fromUChars(cnv,
s1,
MAX_STRLEN,
ucs2,
-1,
&err);
releaseDefaultConverter(cnv);
u_releaseDefaultConverter(cnv);
s1[len] = 0;
} else {
*s1 = 0;
@ -996,44 +991,62 @@ char* u_austrcpy(char *s1,
/* mutexed access to a shared default converter ----------------------------- */
/* this is the same implementation as in unistr.cpp */
UBool ucln_ustring(void) {
UConverter *converter = 0;
static UConverter*
getDefaultConverter()
{
UConverter *converter = NULL;
if(fgDefaultConverter != NULL) {
umtx_lock(NULL);
/* need to check to make sure it wasn't taken out from under us */
if(fgDefaultConverter != NULL) {
converter = fgDefaultConverter;
fgDefaultConverter = NULL;
if (gDefaultConverter) {
umtx_lock(NULL);
if (gDefaultConverter) {
converter = gDefaultConverter;
gDefaultConverter = NULL;
}
umtx_unlock(NULL);
}
umtx_unlock(NULL);
}
/* if the cache was empty, create a converter */
if(converter == NULL) {
UErrorCode status = U_ZERO_ERROR;
converter = ucnv_open(NULL, &status);
if(U_FAILURE(status)) {
return NULL;
}
}
return converter;
// it's safe to close a 0 converter
ucnv_close(converter);
return TRUE;
}
static void
releaseDefaultConverter(UConverter *converter)
UConverter*
u_getDefaultConverter(UErrorCode *status)
{
if(fgDefaultConverter == NULL) {
UConverter *converter = NULL;
if (gDefaultConverter != NULL) {
umtx_lock(NULL);
/* need to check to make sure it wasn't taken out from under us */
if (gDefaultConverter != NULL) {
converter = gDefaultConverter;
gDefaultConverter = NULL;
}
umtx_unlock(NULL);
}
/* if the cache was empty, create a converter */
if(converter == NULL) {
converter = ucnv_open(NULL, status);
if(U_FAILURE(*status)) {
return NULL;
}
}
return converter;
}
void
u_releaseDefaultConverter(UConverter *converter)
{
if(gDefaultConverter == NULL) {
if (converter != NULL) {
ucnv_reset(converter);
}
umtx_lock(NULL);
if(fgDefaultConverter == NULL) {
fgDefaultConverter = converter;
if(gDefaultConverter == NULL) {
gDefaultConverter = converter;
converter = NULL;
}
umtx_unlock(NULL);