mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 08:53:20 +00:00
ICU-1991 ucnv_openPackage
X-SVN-Rev: 9220
This commit is contained in:
parent
0c4a2395ca
commit
4ef2dc2ea1
5 changed files with 150 additions and 29 deletions
|
@ -93,6 +93,12 @@ ucnv_open (const char *name,
|
|||
return ucnv_createConverter(name, err);
|
||||
}
|
||||
|
||||
U_CAPI UConverter* U_EXPORT2
|
||||
ucnv_openPackage (const char *packageName, const char *converterName, UErrorCode * err)
|
||||
{
|
||||
return ucnv_createConverterFromPackage(packageName, converterName, err);
|
||||
}
|
||||
|
||||
/*Extracts the UChar* to a char* and calls through createConverter */
|
||||
U_CAPI UConverter* U_EXPORT2
|
||||
ucnv_openU (const UChar * name,
|
||||
|
@ -243,14 +249,23 @@ ucnv_close (UConverter * converter)
|
|||
if (converter->sharedData->impl->close != NULL) {
|
||||
converter->sharedData->impl->close(converter);
|
||||
}
|
||||
if(!converter->isCopyLocal){
|
||||
if (converter->sharedData->referenceCounter != ~0) {
|
||||
umtx_lock (NULL);
|
||||
if (converter->sharedData->referenceCounter != 0) {
|
||||
converter->sharedData->referenceCounter--;
|
||||
}
|
||||
umtx_unlock (NULL);
|
||||
|
||||
#if 1
|
||||
if(!converter->isCopyLocal)
|
||||
#endif
|
||||
if (converter->sharedData->referenceCounter != ~0) {
|
||||
umtx_lock (NULL);
|
||||
if (converter->sharedData->referenceCounter != 0) {
|
||||
converter->sharedData->referenceCounter--;
|
||||
}
|
||||
umtx_unlock (NULL);
|
||||
|
||||
if((converter->sharedData->referenceCounter == 0)&&(converter->sharedData->sharedDataCached == FALSE)) {
|
||||
ucnv_deleteSharedConverterData(converter->sharedData);
|
||||
}
|
||||
}
|
||||
|
||||
if(!converter->isCopyLocal){
|
||||
uprv_free (converter);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -107,7 +107,7 @@ static struct {
|
|||
*goes to disk and opens it.
|
||||
*allocates the memory and returns a new UConverter object
|
||||
*/
|
||||
static UConverterSharedData *createConverterFromFile (const char *converterName, UErrorCode * err);
|
||||
static UConverterSharedData *createConverterFromFile (const char *pkg, const char *converterName, UErrorCode * err);
|
||||
|
||||
static const UConverterSharedData *getAlgorithmicTypeFromName (const char *realName);
|
||||
|
||||
|
@ -155,12 +155,12 @@ isCnvAcceptable(void *context,
|
|||
pInfo->dataFormat[1]==0x6e &&
|
||||
pInfo->dataFormat[2]==0x76 &&
|
||||
pInfo->dataFormat[3]==0x74 &&
|
||||
pInfo->formatVersion[0]==6);
|
||||
pInfo->formatVersion[0]==6); /* Everything will be version 6 */
|
||||
}
|
||||
|
||||
#define DATA_TYPE "cnv"
|
||||
|
||||
static UConverterSharedData *createConverterFromFile (const char *fileName, UErrorCode * err)
|
||||
static UConverterSharedData *createConverterFromFile (const char* pkg, const char *fileName, UErrorCode * err)
|
||||
{
|
||||
UDataMemory *data;
|
||||
UConverterSharedData *sharedData;
|
||||
|
@ -169,7 +169,7 @@ static UConverterSharedData *createConverterFromFile (const char *fileName, UErr
|
|||
return NULL;
|
||||
}
|
||||
|
||||
data = udata_openChoice(NULL, DATA_TYPE, fileName, isCnvAcceptable, NULL, err);
|
||||
data = udata_openChoice(pkg, DATA_TYPE, fileName, isCnvAcceptable, NULL, err);
|
||||
if(U_FAILURE(*err))
|
||||
{
|
||||
return NULL;
|
||||
|
@ -245,6 +245,9 @@ ucnv_shareConverterData(UConverterSharedData * data)
|
|||
}
|
||||
UCNV_DEBUG_LOG("put:chk",data->staticData->name,sanity);
|
||||
*/
|
||||
|
||||
/* Mark it shared */
|
||||
data->sharedDataCached = TRUE;
|
||||
|
||||
uhash_put(SHARED_DATA_HASHTABLE,
|
||||
(void*) data->staticData->name, /* Okay to cast away const as long as
|
||||
|
@ -283,11 +286,11 @@ ucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
|
|||
{
|
||||
if (deadSharedData->referenceCounter > 0)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (deadSharedData->impl->unload != NULL) {
|
||||
deadSharedData->impl->unload(deadSharedData);
|
||||
}
|
||||
|
||||
|
||||
if(deadSharedData->dataMemory != NULL)
|
||||
{
|
||||
UDataMemory *data = (UDataMemory*)deadSharedData->dataMemory;
|
||||
|
@ -299,6 +302,20 @@ ucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
|
|||
uprv_free(deadSharedData->table);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* if the static data is actually owned by the shared data */
|
||||
/* enable if we ever have this situation. */
|
||||
if(deadSharedData->staticDataOwned == TRUE) /* see ucnv_bld.h */
|
||||
{
|
||||
uprv_free((void*)deadSharedData->staticData);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Zap it ! */
|
||||
uprv_memset(deadSharedData->0, sizeof(*deadSharedData));
|
||||
#endif
|
||||
|
||||
uprv_free(deadSharedData);
|
||||
|
||||
return TRUE;
|
||||
|
@ -452,7 +469,7 @@ ucnv_createConverter (const char *converterName, UErrorCode * err)
|
|||
if (mySharedConverterData == NULL)
|
||||
{
|
||||
/*Not cached, we need to stream it in from file */
|
||||
mySharedConverterData = createConverterFromFile (realName, err);
|
||||
mySharedConverterData = createConverterFromFile (NULL, realName, err);
|
||||
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
|
||||
{
|
||||
umtx_unlock(&cnvCacheMutex);
|
||||
|
@ -475,8 +492,9 @@ ucnv_createConverter (const char *converterName, UErrorCode * err)
|
|||
umtx_unlock(&cnvCacheMutex);
|
||||
}
|
||||
|
||||
myUConverter = ucnv_createConverterFromSharedData(mySharedConverterData, realName, locale, options, err);
|
||||
|
||||
/* allocate the converter */
|
||||
myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
|
||||
if (myUConverter == NULL)
|
||||
{
|
||||
if (mySharedConverterData->referenceCounter != ~0) {
|
||||
|
@ -488,6 +506,60 @@ ucnv_createConverter (const char *converterName, UErrorCode * err)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return myUConverter;
|
||||
}
|
||||
|
||||
|
||||
UConverter*
|
||||
ucnv_createConverterFromPackage(const char *packageName, const char *converterName, UErrorCode * err)
|
||||
{
|
||||
char cnvName[UCNV_MAX_CONVERTER_NAME_LENGTH], locale[ULOC_FULLNAME_CAPACITY];
|
||||
uint32_t options=0;
|
||||
UConverter *myUConverter;
|
||||
UConverterSharedData *mySharedConverterData = NULL;
|
||||
|
||||
if(U_FAILURE(*err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first, get the options out of the convertername string */
|
||||
parseConverterOptions(converterName, cnvName, locale, &options, err);
|
||||
if (U_FAILURE(*err)) {
|
||||
/* Very bad name used. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* open the data, unflatten the shared structure */
|
||||
mySharedConverterData = createConverterFromFile(packageName, cnvName, err);
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create the actual converter */
|
||||
myUConverter = ucnv_createConverterFromSharedData( mySharedConverterData, cnvName, locale, options, err);
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
ucnv_close(myUConverter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return myUConverter;
|
||||
}
|
||||
|
||||
|
||||
UConverter*
|
||||
ucnv_createConverterFromSharedData(UConverterSharedData *mySharedConverterData, const char *realName, const char *locale, uint32_t options, UErrorCode *err)
|
||||
{
|
||||
UConverter *myUConverter;
|
||||
|
||||
myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
|
||||
if(myUConverter == NULL)
|
||||
{
|
||||
*err = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* initialize the converter */
|
||||
uprv_memset(myUConverter, 0, sizeof(UConverter));
|
||||
myUConverter->sharedData = mySharedConverterData;
|
||||
|
@ -531,17 +603,6 @@ ucnv_data_unFlattenClone(UDataMemory *pData, UErrorCode *status)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* necessary only if some converters have different formatVersion; now everything is at version 5 */
|
||||
/* test for the format version: MBCS is at version 5, the rest still at 4 */
|
||||
info.size=sizeof(UDataInfo);
|
||||
udata_getInfo(pData, &info);
|
||||
if(type == UCNV_MBCS ? info.formatVersion[0] != 5 : info.formatVersion[0] != 4) {
|
||||
*status = U_INVALID_TABLE_FORMAT;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
data = (UConverterSharedData *)uprv_malloc(sizeof(UConverterSharedData));
|
||||
if(data == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
|
@ -560,6 +621,8 @@ ucnv_data_unFlattenClone(UDataMemory *pData, UErrorCode *status)
|
|||
}
|
||||
|
||||
data->staticData = source;
|
||||
|
||||
data->sharedDataCached = FALSE;
|
||||
|
||||
/* fill in fields from the loaded data */
|
||||
data->dataMemory = (void*)pData; /* for future use */
|
||||
|
@ -614,6 +677,7 @@ ucnv_flushCache ()
|
|||
UCNV_DEBUG_LOG("del",mySharedData->staticData->name,mySharedData);
|
||||
|
||||
uhash_removeElement(SHARED_DATA_HASHTABLE, e);
|
||||
mySharedData->sharedDataCached = FALSE;
|
||||
ucnv_deleteSharedConverterData (mySharedData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,11 +75,14 @@ struct UConverterSharedData {
|
|||
uint32_t structSize; /* Size of this structure */
|
||||
uint32_t referenceCounter; /* used to count number of clients, 0xffffffff for static SharedData */
|
||||
|
||||
const void *dataMemory; /* from udata_openChoice() */
|
||||
const void *dataMemory; /* from udata_openChoice() - for cleanup */
|
||||
UConverterTable *table; /* Pointer to conversion data */
|
||||
|
||||
const UConverterStaticData *staticData; /* pointer to the static (non changing) data. */
|
||||
UBool staticDataOwned; /* T if we own the staticData */
|
||||
|
||||
UBool sharedDataCached; /* TRUE: shared data is in cache, don't destroy on ucnv_close() if 0 ref. FALSE: shared data isn't in the cache, do attempt to clean it up if the ref is 0 */
|
||||
/*UBool staticDataOwned; TRUE if static data owned by shared data & should be freed with it, NEVER true for udata() loaded statics. This ignored variable was removed to make space for sharedDataCached. */
|
||||
|
||||
const UConverterImpl *impl; /* vtable-style struct of mostly function pointers */
|
||||
|
||||
/*initial values of some members of the mutable part of object */
|
||||
|
@ -137,8 +140,9 @@ struct UConverter {
|
|||
|
||||
const void *fromUContext;
|
||||
const void *toUContext;
|
||||
UBool isCopyLocal; /* TRUE if created by safeClone with no allocation or ref count */
|
||||
UBool isCopyLocal; /* TRUE if created by safeClone with no allocation - Don't free cnv memory on ucnv_close. */
|
||||
UConverterSharedData *sharedData; /* Pointer to the shared immutable part of the converter object */
|
||||
UBool sharedDataIsCached; /* TRUE: shared data is in cache, don't destroy on ucnv_close() if 0 ref. FALSE: shared data isn't in the cache, do attempt to clean it up if the ref is 0 */
|
||||
|
||||
/*
|
||||
* currently only used to point to a struct containing UConverter used by iso 2022;
|
||||
|
|
|
@ -30,6 +30,14 @@
|
|||
*/
|
||||
UConverter *ucnv_createConverter (const char *converterName, UErrorCode * err);
|
||||
|
||||
/* Creates a converter from shared data
|
||||
*/
|
||||
UConverter*
|
||||
ucnv_createConverterFromSharedData(UConverterSharedData *mySharedConverterData, const char *realName, const char *locale, uint32_t options, UErrorCode *err);
|
||||
|
||||
UConverter* ucnv_createConverterFromPackage(const char *packageName, const char *converterName,
|
||||
UErrorCode *err);
|
||||
|
||||
/* Stores the shared data in the SHARED_DATA_HASHTABLE
|
||||
* @param data The shared data
|
||||
*/
|
||||
|
|
|
@ -324,6 +324,36 @@ ucnv_openCCSID (int32_t codepage,
|
|||
UConverterPlatform platform,
|
||||
UErrorCode * err);
|
||||
|
||||
/**
|
||||
* <p>Creates a UConverter object specified from a packageName and a converterName.</p>
|
||||
*
|
||||
* <p>The packageName and converterName must point to an ICU udata object, as defined by
|
||||
* <code> udata_open( packageName, "cnv", converterName, err) </code> or equivalent.
|
||||
* Typically, packageName will refer to a (.dat) file, or to a package registered with
|
||||
* udata_setAppData().</p>
|
||||
*
|
||||
* <p>The name will NOT be looked up in the alias mechanism, nor will the converter be
|
||||
* stored in the converter cache or the alias table. The only way to open further converters
|
||||
* is call this function multiple times, or use the ucnv_safeClone() function to clone a
|
||||
* 'master' converter.</p>
|
||||
*
|
||||
* <p>Example Use:
|
||||
* <code>cnv = ucnv_openPackage("myapp", "myconverter", &err);</conv>
|
||||
* </p>
|
||||
*
|
||||
* @param packageName name of the package (equivalent to 'path' in udata_open() call)
|
||||
* @param converterName name of the data item to be used, without suffix.
|
||||
* @param err outgoing error status <TT>U_MEMORY_ALLOCATION_ERROR, U_FILE_ACCESS_ERROR</TT>
|
||||
* @return the created Unicode converter object, or <TT>NULL</TT> if an error occured
|
||||
* @see udata_open
|
||||
* @see ucnv_open
|
||||
* @see ucnv_safeClone
|
||||
* @see ucnv_close
|
||||
* @draft ICU 2.2
|
||||
*/
|
||||
U_CAPI UConverter* U_EXPORT2
|
||||
ucnv_openPackage (const char *packageName, const char *converterName, UErrorCode * err);
|
||||
|
||||
/**
|
||||
* Thread safe cloning operation
|
||||
* @param cnv converter to be cloned
|
||||
|
|
Loading…
Add table
Reference in a new issue