ICU-770 Change code for u_cleanup() API.
X-SVN-Rev: 5462
This commit is contained in:
parent
59e51a0248
commit
f850ad2c5e
@ -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
|
||||
|
27
icu4c/source/common/ucln_cmn.c
Normal file
27
icu4c/source/common/ucln_cmn.c
Normal 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();
|
||||
}
|
30
icu4c/source/common/ucln_cmn.h
Normal file
30
icu4c/source/common/ucln_cmn.h
Normal 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
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user