mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-06 22:15:31 +00:00
ICU-3346 support loading extension files from non-NULL (application) packages (same package as where the base file is for now)
X-SVN-Rev: 13673
This commit is contained in:
parent
38e6180871
commit
dfb7248160
7 changed files with 94 additions and 23 deletions
|
@ -197,7 +197,7 @@ isCnvAcceptable(void *context,
|
|||
* Un flatten shared data from a UDATA..
|
||||
*/
|
||||
static UConverterSharedData*
|
||||
ucnv_data_unFlattenClone(UDataMemory *pData, UErrorCode *status)
|
||||
ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCode *status)
|
||||
{
|
||||
/* UDataInfo info; -- necessary only if some converters have different formatVersion */
|
||||
const uint8_t *raw = (const uint8_t *)udata_getMemory(pData);
|
||||
|
@ -254,7 +254,7 @@ ucnv_data_unFlattenClone(UDataMemory *pData, UErrorCode *status)
|
|||
data->dataMemory = (void*)pData; /* for future use */
|
||||
|
||||
if(data->impl->load != NULL) {
|
||||
data->impl->load(data, raw + source->structSize, status);
|
||||
data->impl->load(data, pArgs, raw + source->structSize, status);
|
||||
if(U_FAILURE(*status)) {
|
||||
uprv_free(data->table);
|
||||
uprv_free(data);
|
||||
|
@ -268,7 +268,7 @@ ucnv_data_unFlattenClone(UDataMemory *pData, UErrorCode *status)
|
|||
*goes to disk and opens it.
|
||||
*allocates the memory and returns a new UConverter object
|
||||
*/
|
||||
static UConverterSharedData *createConverterFromFile(const char* pkg, const char *fileName, UErrorCode * err)
|
||||
static UConverterSharedData *createConverterFromFile(UConverterLoadArgs *pArgs, UErrorCode * err)
|
||||
{
|
||||
UDataMemory *data;
|
||||
UConverterSharedData *sharedData;
|
||||
|
@ -277,13 +277,13 @@ static UConverterSharedData *createConverterFromFile(const char* pkg, const char
|
|||
return NULL;
|
||||
}
|
||||
|
||||
data = udata_openChoice(pkg, DATA_TYPE, fileName, isCnvAcceptable, NULL, err);
|
||||
data = udata_openChoice(pArgs->pkg, DATA_TYPE, pArgs->name, isCnvAcceptable, NULL, err);
|
||||
if(U_FAILURE(*err))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sharedData = ucnv_data_unFlattenClone(data, err);
|
||||
sharedData = ucnv_data_unFlattenClone(pArgs, data, err);
|
||||
if(U_FAILURE(*err))
|
||||
{
|
||||
udata_close(data);
|
||||
|
@ -481,23 +481,23 @@ ucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
|
|||
* If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
|
||||
*/
|
||||
UConverterSharedData *
|
||||
ucnv_load(const char *pkg, const char *realName, UErrorCode *err) {
|
||||
ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
|
||||
UConverterSharedData *mySharedConverterData;
|
||||
|
||||
if(err == NULL || U_FAILURE(*err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(pkg != NULL && *pkg != 0) {
|
||||
if(pArgs->pkg != NULL && *pArgs->pkg != 0) {
|
||||
/* application-provided converters are not currently cached */
|
||||
return createConverterFromFile(pkg, realName, err);
|
||||
return createConverterFromFile(pArgs, err);
|
||||
}
|
||||
|
||||
mySharedConverterData = ucnv_getSharedConverterData(realName);
|
||||
mySharedConverterData = ucnv_getSharedConverterData(pArgs->name);
|
||||
if (mySharedConverterData == NULL)
|
||||
{
|
||||
/*Not cached, we need to stream it in from file */
|
||||
mySharedConverterData = createConverterFromFile(NULL, realName, err);
|
||||
mySharedConverterData = createConverterFromFile(pArgs, err);
|
||||
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
|
||||
{
|
||||
return NULL;
|
||||
|
@ -703,8 +703,16 @@ ucnv_createConverter(UConverter *myUConverter, const char *converterName, UError
|
|||
/* converter data cache, and adding new entries to the cache */
|
||||
/* to prevent other threads from modifying the cache during the */
|
||||
/* process. */
|
||||
UConverterLoadArgs args={ 0 };
|
||||
|
||||
args.size=sizeof(UConverterLoadArgs);
|
||||
args.nestedLoads=1;
|
||||
args.options=options;
|
||||
args.pkg=NULL;
|
||||
args.name=realName;
|
||||
|
||||
umtx_lock(&cnvCacheMutex);
|
||||
mySharedConverterData = ucnv_load(NULL, realName, err);
|
||||
mySharedConverterData = ucnv_load(&args, err);
|
||||
umtx_unlock(&cnvCacheMutex);
|
||||
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
|
||||
{
|
||||
|
@ -763,30 +771,36 @@ 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;
|
||||
UConverterSharedData *mySharedConverterData;
|
||||
|
||||
UConverterLoadArgs args={ 0 };
|
||||
|
||||
if(U_FAILURE(*err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* first, get the options out of the convertername string */
|
||||
parseConverterOptions(converterName, cnvName, locale, &options, err);
|
||||
args.size=sizeof(UConverterLoadArgs);
|
||||
args.nestedLoads=1;
|
||||
args.pkg=packageName;
|
||||
|
||||
/* first, get the options out of the converterName string */
|
||||
parseConverterOptions(converterName, cnvName, locale, &args.options, err);
|
||||
if (U_FAILURE(*err)) {
|
||||
/* Very bad name used. */
|
||||
return NULL;
|
||||
}
|
||||
args.name=cnvName;
|
||||
|
||||
/* open the data, unflatten the shared structure */
|
||||
mySharedConverterData = createConverterFromFile(packageName, cnvName, err);
|
||||
mySharedConverterData = createConverterFromFile(&args, err);
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create the actual converter */
|
||||
myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, cnvName, locale, options, err);
|
||||
myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, cnvName, locale, args.options, err);
|
||||
|
||||
if (U_FAILURE(*err)) {
|
||||
ucnv_close(myUConverter);
|
||||
|
|
|
@ -232,7 +232,7 @@ UConverterDataLMBCS;
|
|||
* If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
|
||||
*/
|
||||
UConverterSharedData *
|
||||
ucnv_load(const char *pkg, const char *name, UErrorCode *err);
|
||||
ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err);
|
||||
|
||||
/**
|
||||
* Unload a non-algorithmic converter.
|
||||
|
|
|
@ -41,7 +41,18 @@ typedef struct UConverterSharedData UConverterSharedData;
|
|||
|
||||
/* function types for UConverterImpl ---------------------------------------- */
|
||||
|
||||
typedef void (*UConverterLoad) (UConverterSharedData *sharedData, const uint8_t *raw, UErrorCode *pErrorCode);
|
||||
/* struct with arguments for UConverterLoad and ucnv_load() */
|
||||
typedef struct {
|
||||
int32_t size; /* sizeof(UConverterLoadArgs) */
|
||||
int32_t nestedLoads; /* count nested ucnv_load() calls */
|
||||
int32_t reserved; /* reserved - for good alignment of the pointers */
|
||||
uint32_t options;
|
||||
const char *pkg, *name;
|
||||
} UConverterLoadArgs;
|
||||
|
||||
typedef void (*UConverterLoad) (UConverterSharedData *sharedData,
|
||||
UConverterLoadArgs *pArgs,
|
||||
const uint8_t *raw, UErrorCode *pErrorCode);
|
||||
typedef void (*UConverterUnload) (UConverterSharedData *sharedData);
|
||||
|
||||
typedef void (*UConverterOpen) (UConverter *cnv, const char *name, const char *locale,uint32_t options, UErrorCode *pErrorCode);
|
||||
|
|
|
@ -863,6 +863,7 @@ _EBCDICSwapLFNL(UConverterSharedData *sharedData, UErrorCode *pErrorCode) {
|
|||
|
||||
static void
|
||||
_MBCSLoad(UConverterSharedData *sharedData,
|
||||
UConverterLoadArgs *pArgs,
|
||||
const uint8_t *raw,
|
||||
UErrorCode *pErrorCode) {
|
||||
UDataInfo info;
|
||||
|
@ -884,6 +885,7 @@ _MBCSLoad(UConverterSharedData *sharedData,
|
|||
}
|
||||
|
||||
if(mbcsTable->outputType==MBCS_OUTPUT_EXT_ONLY) {
|
||||
UConverterLoadArgs args={ 0 };
|
||||
UConverterSharedData *baseSharedData;
|
||||
const int32_t *extIndexes;
|
||||
const char *baseName;
|
||||
|
@ -895,17 +897,28 @@ _MBCSLoad(UConverterSharedData *sharedData,
|
|||
return;
|
||||
}
|
||||
|
||||
if(pArgs->nestedLoads!=1) {
|
||||
/* an extension table must not be loaded as a base table */
|
||||
*pErrorCode=U_INVALID_TABLE_FILE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* load the base table */
|
||||
baseName=(const char *)(header+1);
|
||||
if(0==uprv_strcmp(baseName, sharedData->staticData->name)) {
|
||||
/* forbid loading this same extension-only file */
|
||||
/* TODO better prevention of loading another extension table */
|
||||
*pErrorCode=U_INVALID_TABLE_FORMAT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO pass package name, same as current converter (see ucnv_bld.c) and/or parse out of prefix of base name */
|
||||
baseSharedData=ucnv_load(NULL, baseName, pErrorCode);
|
||||
/* TODO parse package name out of the prefix of the base name in the extension .cnv file? */
|
||||
args.size=sizeof(UConverterLoadArgs);
|
||||
args.nestedLoads=2;
|
||||
args.reserved=pArgs->reserved;
|
||||
args.options=pArgs->options;
|
||||
args.pkg=pArgs->pkg;
|
||||
args.name=baseName;
|
||||
baseSharedData=ucnv_load(&args, pErrorCode);
|
||||
if(U_FAILURE(*pErrorCode)) {
|
||||
return;
|
||||
}
|
||||
|
|
9
icu4c/source/test/testdata/conversion.txt
vendored
9
icu4c/source/test/testdata/conversion.txt
vendored
|
@ -177,6 +177,15 @@ conversion {
|
|||
fromUnicode {
|
||||
Headers { "charset", "unicode", "bytes", "offsets", "flush", "fallbacks", "errorCode", "callback", "invalidUChars" }
|
||||
Cases {
|
||||
// extension in testdata
|
||||
{
|
||||
"*test4x",
|
||||
"\u20ac\x09",
|
||||
:bin{ 0009 },
|
||||
:intvector{ 0, 1 },
|
||||
:int{1}, :int{1}, "", "?", ""
|
||||
}
|
||||
|
||||
// DBCS-only extensions
|
||||
{
|
||||
"ibm-970",
|
||||
|
|
20
icu4c/source/test/testdata/test4x.ucm
vendored
Normal file
20
icu4c/source/test/testdata/test4x.ucm
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
# *******************************************************************************
|
||||
# * Copyright (C) 2003, International Business Machines
|
||||
# * Corporation and others. All Rights Reserved.
|
||||
# *******************************************************************************
|
||||
#
|
||||
# test4x.ucm
|
||||
#
|
||||
# Test file for MBCS conversion extension with four-byte codepage data.
|
||||
|
||||
<code_set_name> "test4x"
|
||||
<mb_cur_max> 4
|
||||
<mb_cur_min> 1
|
||||
<uconv_class> "MBCS"
|
||||
|
||||
# test loading an extension table from the testdata package
|
||||
<icu:base> "test4"
|
||||
|
||||
CHARMAP
|
||||
<U0009> \x09 |0
|
||||
END CHARMAP
|
6
icu4c/source/test/testdata/testdata.mk
vendored
6
icu4c/source/test/testdata/testdata.mk
vendored
|
@ -14,7 +14,7 @@ TESTDT=$(TESTPKG)_
|
|||
ALL : "$(TESTDATAOUT)\testdata.dat"
|
||||
@echo Test data is built.
|
||||
|
||||
"$(TESTDATAOUT)\testdata.dat" : "$(TESTDATABLD)\casing.res" "$(TESTDATABLD)\conversion.res" "$(TESTDATABLD)\mc.res" "$(TESTDATABLD)\root.res" "$(TESTDATABLD)\te.res" "$(TESTDATABLD)\te_IN.res" "$(TESTDATABLD)\testaliases.res" "$(TESTDATABLD)\testtypes.res" "$(TESTDATABLD)\testempty.res" "$(TESTDATABLD)\$(TESTDT)iscii.res" "$(TESTDATABLD)\$(TESTDT)idna_rules.res" "$(TESTDATABLD)\DataDrivenCollationTest.res" "$(TESTDATABLD)\$(TESTDT)test.icu" "$(TESTDATABLD)\$(TESTDT)testtable32.res" "$(TESTDATABLD)\$(TESTDT)test1.cnv" "$(TESTDATABLD)\$(TESTDT)test3.cnv" "$(TESTDATABLD)\$(TESTDT)test4.cnv" "$(TESTDATABLD)\$(TESTDT)ibm9027.cnv" "$(TESTDATABLD)\$(TESTDT)nfscsi.spp" "$(TESTDATABLD)\$(TESTDT)nfscss.spp" "$(TESTDATABLD)\$(TESTDT)nfscis.spp" "$(TESTDATABLD)\$(TESTDT)nfsmxs.spp" "$(TESTDATABLD)\$(TESTDT)nfsmxp.spp"
|
||||
"$(TESTDATAOUT)\testdata.dat" : "$(TESTDATABLD)\casing.res" "$(TESTDATABLD)\conversion.res" "$(TESTDATABLD)\mc.res" "$(TESTDATABLD)\root.res" "$(TESTDATABLD)\te.res" "$(TESTDATABLD)\te_IN.res" "$(TESTDATABLD)\testaliases.res" "$(TESTDATABLD)\testtypes.res" "$(TESTDATABLD)\testempty.res" "$(TESTDATABLD)\$(TESTDT)iscii.res" "$(TESTDATABLD)\$(TESTDT)idna_rules.res" "$(TESTDATABLD)\DataDrivenCollationTest.res" "$(TESTDATABLD)\$(TESTDT)test.icu" "$(TESTDATABLD)\$(TESTDT)testtable32.res" "$(TESTDATABLD)\$(TESTDT)test1.cnv" "$(TESTDATABLD)\$(TESTDT)test3.cnv" "$(TESTDATABLD)\$(TESTDT)test4.cnv" "$(TESTDATABLD)\$(TESTDT)test4x.cnv" "$(TESTDATABLD)\$(TESTDT)ibm9027.cnv" "$(TESTDATABLD)\$(TESTDT)nfscsi.spp" "$(TESTDATABLD)\$(TESTDT)nfscss.spp" "$(TESTDATABLD)\$(TESTDT)nfscis.spp" "$(TESTDATABLD)\$(TESTDT)nfsmxs.spp" "$(TESTDATABLD)\$(TESTDT)nfsmxp.spp"
|
||||
@echo Building test data
|
||||
@copy "$(TESTDATABLD)\$(TESTDT)te.res" "$(TESTDATAOUT)\$(TESTDT)nam.typ"
|
||||
@"$(ICUP)\bin\pkgdata" -f -v -m common -c -p"$(TESTPKG)" -d "$(TESTDATAOUT)" -T "$(TESTDATABLD)" -s "$(TESTDATABLD)" <<
|
||||
|
@ -34,6 +34,7 @@ $(TESTDT)test.icu
|
|||
$(TESTDT)test1.cnv
|
||||
$(TESTDT)test3.cnv
|
||||
$(TESTDT)test4.cnv
|
||||
$(TESTDT)test4x.cnv
|
||||
$(TESTDT)ibm9027.cnv
|
||||
$(TESTDT)idna_rules.res
|
||||
$(TESTDT)nfscsi.spp
|
||||
|
@ -107,6 +108,9 @@ $(TESTDT)nfsmxp.spp
|
|||
"$(TESTDATABLD)\$(TESTDT)test4.cnv": "$(TESTDATA)\test4.ucm"
|
||||
@"$(ICUTOOLS)\makeconv\$(CFG)\makeconv" -d"$(TESTDATABLD)" -p $(TESTPKG) $**
|
||||
|
||||
"$(TESTDATABLD)\$(TESTDT)test4x.cnv": "$(TESTDATA)\test4x.ucm"
|
||||
@"$(ICUTOOLS)\makeconv\$(CFG)\makeconv" -d"$(TESTDATABLD)" -p $(TESTPKG) $**
|
||||
|
||||
"$(TESTDATABLD)\$(TESTDT)ibm9027.cnv": "$(TESTDATA)\ibm9027.ucm"
|
||||
@"$(ICUTOOLS)\makeconv\$(CFG)\makeconv" -d"$(TESTDATABLD)" -p $(TESTPKG) $**
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue