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:
Markus Scherer 2003-11-12 02:04:55 +00:00
parent 38e6180871
commit dfb7248160
7 changed files with 94 additions and 23 deletions

View file

@ -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);

View file

@ -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.

View file

@ -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);

View file

@ -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;
}

View file

@ -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
View 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

View file

@ -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) $**