ICU-6441 make ucnv_countAvailable() not fully load converters

X-SVN-Rev: 25584
This commit is contained in:
Markus Scherer 2009-03-13 22:05:01 +00:00
parent 67f42c995f
commit abb7ac7522
12 changed files with 386 additions and 218 deletions

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2000-2008, International Business Machines
* Copyright (C) 2000-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnv2022.c
@ -165,7 +165,8 @@ typedef enum {
* all versions, not just JIS7 and JIS8.
* - ICU does not distinguish between different versions of JIS X 0208.
*/
static const uint16_t jpCharsetMasks[5]={
enum { MAX_JA_VERSION=4 };
static const uint16_t jpCharsetMasks[MAX_JA_VERSION+1]={
CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT),
CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212),
CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7),
@ -370,7 +371,7 @@ typedef enum{
/*********** ISO 2022 Converter Protos ***********/
static void
_ISO2022Open(UConverter *cnv, const char *name, const char *locale,uint32_t options, UErrorCode *errorCode);
_ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode);
static void
_ISO2022Close(UConverter *converter);
@ -448,40 +449,53 @@ setInitialStateFromUnicodeKR(UConverter* converter,UConverterDataISO2022 *myConv
}
static void
_ISO2022Open(UConverter *cnv, const char *name, const char *locale,uint32_t options, UErrorCode *errorCode){
_ISO2022Open(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){
char myLocale[6]={' ',' ',' ',' ',' ',' '};
cnv->extraInfo = uprv_malloc (sizeof (UConverterDataISO2022));
if(cnv->extraInfo != NULL) {
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
UConverterDataISO2022 *myConverterData=(UConverterDataISO2022 *) cnv->extraInfo;
uint32_t version;
stackArgs.onlyTestIsLoadable = pArgs->onlyTestIsLoadable;
uprv_memset(myConverterData, 0, sizeof(UConverterDataISO2022));
myConverterData->currentType = ASCII1;
cnv->fromUnicodeStatus =FALSE;
if(locale){
uprv_strncpy(myLocale, locale, sizeof(myLocale));
if(pArgs->locale){
uprv_strncpy(myLocale, pArgs->locale, sizeof(myLocale));
}
version = options & UCNV_OPTIONS_VERSION_MASK;
version = pArgs->options & UCNV_OPTIONS_VERSION_MASK;
myConverterData->version = version;
if(myLocale[0]=='j' && (myLocale[1]=='a'|| myLocale[1]=='p') &&
(myLocale[2]=='_' || myLocale[2]=='\0'))
{
size_t len=0;
/* open the required converters and cache them */
if(jpCharsetMasks[version]&CSM(ISO8859_7)) {
myConverterData->myConverterArray[ISO8859_7]= ucnv_loadSharedData("ISO8859_7", NULL, errorCode);
if(version>MAX_JA_VERSION) {
/* prevent indexing beyond jpCharsetMasks[] */
myConverterData->version = version = 0;
}
myConverterData->myConverterArray[JISX208] = ucnv_loadSharedData("Shift-JIS", NULL, errorCode);
if(jpCharsetMasks[version]&CSM(ISO8859_7)) {
myConverterData->myConverterArray[ISO8859_7] =
ucnv_loadSharedData("ISO8859_7", &stackPieces, &stackArgs, errorCode);
}
myConverterData->myConverterArray[JISX208] =
ucnv_loadSharedData("Shift-JIS", &stackPieces, &stackArgs, errorCode);
if(jpCharsetMasks[version]&CSM(JISX212)) {
myConverterData->myConverterArray[JISX212] = ucnv_loadSharedData("jisx-212", NULL, errorCode);
myConverterData->myConverterArray[JISX212] =
ucnv_loadSharedData("jisx-212", &stackPieces, &stackArgs, errorCode);
}
if(jpCharsetMasks[version]&CSM(GB2312)) {
myConverterData->myConverterArray[GB2312] = ucnv_loadSharedData("ibm-5478", NULL, errorCode); /* gb_2312_80-1 */
myConverterData->myConverterArray[GB2312] =
ucnv_loadSharedData("ibm-5478", &stackPieces, &stackArgs, errorCode); /* gb_2312_80-1 */
}
if(jpCharsetMasks[version]&CSM(KSC5601)) {
myConverterData->myConverterArray[KSC5601] = ucnv_loadSharedData("ksc_5601", NULL, errorCode);
myConverterData->myConverterArray[KSC5601] =
ucnv_loadSharedData("ksc_5601", &stackPieces, &stackArgs, errorCode);
}
/* set the function pointers to appropriate funtions */
@ -496,48 +510,56 @@ _ISO2022Open(UConverter *cnv, const char *name, const char *locale,uint32_t opti
else if(myLocale[0]=='k' && (myLocale[1]=='o'|| myLocale[1]=='r') &&
(myLocale[2]=='_' || myLocale[2]=='\0'))
{
if (version==1){
myConverterData->currentConverter=
ucnv_open("icu-internal-25546",errorCode);
if (U_FAILURE(*errorCode)) {
_ISO2022Close(cnv);
return;
}
(void)uprv_strcpy(myConverterData->name,"ISO_2022,locale=ko,version=1");
uprv_memcpy(cnv->subChars, myConverterData->currentConverter->subChars, 4);
cnv->subCharLen = myConverterData->currentConverter->subCharLen;
}else{
myConverterData->currentConverter=ucnv_open("ibm-949",errorCode);
if (U_FAILURE(*errorCode)) {
_ISO2022Close(cnv);
return;
}
myConverterData->version = 0;
(void)uprv_strcpy(myConverterData->name,"ISO_2022,locale=ko,version=0");
const char *cnvName;
if(version==1) {
cnvName="icu-internal-25546";
} else {
cnvName="ibm-949";
myConverterData->version=version=0;
}
if(pArgs->onlyTestIsLoadable) {
UErrorCode localStatus=U_ZERO_ERROR;
pArgs->isLoadable=ucnv_canCreateConverter(cnvName, &localStatus);
uprv_free(cnv->extraInfo);
cnv->extraInfo=NULL;
return;
} else {
myConverterData->currentConverter=ucnv_open(cnvName, errorCode);
if (U_FAILURE(*errorCode)) {
_ISO2022Close(cnv);
return;
}
/* initialize the state variables */
setInitialStateToUnicodeKR(cnv, myConverterData);
setInitialStateFromUnicodeKR(cnv, myConverterData);
if(version==1) {
(void)uprv_strcpy(myConverterData->name,"ISO_2022,locale=ko,version=1");
uprv_memcpy(cnv->subChars, myConverterData->currentConverter->subChars, 4);
cnv->subCharLen = myConverterData->currentConverter->subCharLen;
}else{
(void)uprv_strcpy(myConverterData->name,"ISO_2022,locale=ko,version=0");
}
/* set the function pointers to appropriate funtions */
cnv->sharedData=(UConverterSharedData*)&_ISO2022KRData;
uprv_strcpy(myConverterData->locale,"ko");
/* initialize the state variables */
setInitialStateToUnicodeKR(cnv, myConverterData);
setInitialStateFromUnicodeKR(cnv, myConverterData);
/* set the function pointers to appropriate funtions */
cnv->sharedData=(UConverterSharedData*)&_ISO2022KRData;
uprv_strcpy(myConverterData->locale,"ko");
}
}
else if(((myLocale[0]=='z' && myLocale[1]=='h') || (myLocale[0]=='c'&& myLocale[1]=='n'))&&
(myLocale[2]=='_' || myLocale[2]=='\0'))
{
/* open the required converters and cache them */
myConverterData->myConverterArray[GB2312_1] = ucnv_loadSharedData("ibm-5478", NULL, errorCode);
myConverterData->myConverterArray[GB2312_1] =
ucnv_loadSharedData("ibm-5478", &stackPieces, &stackArgs, errorCode);
if(version==1) {
myConverterData->myConverterArray[ISO_IR_165] = ucnv_loadSharedData("iso-ir-165", NULL, errorCode);
myConverterData->myConverterArray[ISO_IR_165] =
ucnv_loadSharedData("iso-ir-165", &stackPieces, &stackArgs, errorCode);
}
myConverterData->myConverterArray[CNS_11643] = ucnv_loadSharedData("cns-11643-1992", NULL, errorCode);
myConverterData->myConverterArray[CNS_11643] =
ucnv_loadSharedData("cns-11643-1992", &stackPieces, &stackArgs, errorCode);
/* set the function pointers to appropriate funtions */
@ -575,6 +597,10 @@ _ISO2022Open(UConverter *cnv, const char *name, const char *locale,uint32_t opti
if(U_FAILURE(*errorCode)) {
_ISO2022Close(cnv);
}
if(pArgs->onlyTestIsLoadable) {
_ISO2022Close(cnv);
pArgs->isLoadable=TRUE;
}
} else {
*errorCode = U_MEMORY_ALLOCATION_ERROR;
}

View file

@ -219,8 +219,8 @@ static UBool U_CALLCONV ucnv_cleanup(void) {
static UBool U_CALLCONV
isCnvAcceptable(void *context,
const char *type, const char *name,
const UDataInfo *pInfo) {
const char *type, const char *name,
const UDataInfo *pInfo) {
return (UBool)(
pInfo->size>=20 &&
pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
@ -551,7 +551,7 @@ ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
{
return NULL;
}
else
else if (!pArgs->onlyTestIsLoadable)
{
/* share it with other library clients */
ucnv_shareConverterData(mySharedConverterData);
@ -603,6 +603,11 @@ ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
void
ucnv_incrementRefCount(UConverterSharedData *sharedData)
{
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if(sharedData != NULL && sharedData->referenceCounter != ~0) {
umtx_lock(&cnvCacheMutex);
sharedData->referenceCounter++;
@ -610,27 +615,39 @@ ucnv_incrementRefCount(UConverterSharedData *sharedData)
}
}
/*
* *pPieces must be initialized.
* The name without options will be copied to pPieces->cnvName.
* The locale and options will be copied to pPieces only if present in inName,
* otherwise the existing values in pPieces remain.
* *pArgs will be set to the pPieces values.
*/
static void
parseConverterOptions(const char *inName,
char *cnvName,
char *locale,
uint32_t *pFlags,
UConverterNamePieces *pPieces,
UConverterLoadArgs *pArgs,
UErrorCode *err)
{
char *cnvName = pPieces->cnvName;
char c;
int32_t len = 0;
pArgs->name=inName;
pArgs->locale=pPieces->locale;
pArgs->options=pPieces->options;
/* copy the converter name itself to cnvName */
while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
if (++len>=UCNV_MAX_CONVERTER_NAME_LENGTH) {
*err = U_ILLEGAL_ARGUMENT_ERROR; /* bad name */
*cnvName=0;
pPieces->cnvName[0]=0;
return;
}
*cnvName++=c;
inName++;
}
*cnvName=0;
pArgs->name=pPieces->cnvName;
/* parse options. No more name copying should occur. */
while((c=*inName)!=0) {
@ -641,7 +658,7 @@ parseConverterOptions(const char *inName,
/* inName is behind an option separator */
if(uprv_strncmp(inName, "locale=", 7)==0) {
/* do not modify locale itself in case we have multiple locale options */
char *dest=locale;
char *dest=pPieces->locale;
/* copy the locale option value */
inName+=7;
@ -651,7 +668,7 @@ parseConverterOptions(const char *inName,
if(++len>=ULOC_FULLNAME_CAPACITY) {
*err=U_ILLEGAL_ARGUMENT_ERROR; /* bad name */
*locale=0;
pPieces->locale[0]=0;
return;
}
@ -659,19 +676,19 @@ parseConverterOptions(const char *inName,
}
*dest=0;
} else if(uprv_strncmp(inName, "version=", 8)==0) {
/* copy the version option value into bits 3..0 of *pFlags */
/* copy the version option value into bits 3..0 of pPieces->options */
inName+=8;
c=*inName;
if(c==0) {
*pFlags&=~UCNV_OPTION_VERSION;
pArgs->options=(pPieces->options&=~UCNV_OPTION_VERSION);
return;
} else if((uint8_t)(c-'0')<10) {
*pFlags=(*pFlags&~UCNV_OPTION_VERSION)|(uint32_t)(c-'0');
pArgs->options=pPieces->options=(pPieces->options&~UCNV_OPTION_VERSION)|(uint32_t)(c-'0');
++inName;
}
} else if(uprv_strncmp(inName, "swaplfnl", 8)==0) {
inName+=8;
*pFlags|=UCNV_OPTION_SWAP_LFNL;
pArgs->options=(pPieces->options|=UCNV_OPTION_SWAP_LFNL);
/* add processing for new options here with another } else if(uprv_strncmp(inName, "option-name=", XX)==0) { */
} else {
/* ignore any other options until we define some */
@ -692,8 +709,12 @@ parseConverterOptions(const char *inName,
* -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE)
*/
UConverterSharedData *
ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UErrorCode * err) {
UConverterLookupData stackLookup;
ucnv_loadSharedData(const char *converterName,
UConverterNamePieces *pPieces,
UConverterLoadArgs *pArgs,
UErrorCode * err) {
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs;
UConverterSharedData *mySharedConverterData = NULL;
UErrorCode internalErrorCode = U_ZERO_ERROR;
UBool mayContainOption = TRUE;
@ -703,21 +724,40 @@ ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UEr
return NULL;
}
if(lookup == NULL) {
lookup = &stackLookup;
if(pPieces == NULL) {
if(pArgs != NULL) {
/*
* Bad: We may set pArgs pointers to stackPieces fields
* which will be invalid after this function returns.
*/
*err = U_INTERNAL_PROGRAM_ERROR;
return NULL;
}
pPieces = &stackPieces;
}
if(pArgs == NULL) {
uprv_memset(&stackArgs, 0, sizeof(stackArgs));
stackArgs.size = (int32_t)sizeof(stackArgs);
pArgs = &stackArgs;
}
lookup->locale[0] = 0;
lookup->options = 0;
pPieces->cnvName[0] = 0;
pPieces->locale[0] = 0;
pPieces->options = 0;
pArgs->name = converterName;
pArgs->locale = pPieces->locale;
pArgs->options = pPieces->options;
/* In case "name" is NULL we want to open the default converter. */
if (converterName == NULL) {
#if U_CHARSET_IS_UTF8
pArgs->name = "UTF-8";
return (UConverterSharedData *)converterData[UCNV_UTF8];
#else
/* Call ucnv_getDefaultName first to query the name from the OS. */
lookup->realName = ucnv_getDefaultName();
if (lookup->realName == NULL) {
pArgs->name = ucnv_getDefaultName();
if (pArgs->name == NULL) {
*err = U_MISSING_RESOURCE_ERROR;
return NULL;
}
@ -729,36 +769,36 @@ ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UEr
}
else if(UCNV_FAST_IS_UTF8(converterName)) {
/* fastpath for UTF-8 */
pArgs->name = "UTF-8";
return (UConverterSharedData *)converterData[UCNV_UTF8];
}
else {
/* separate the converter name from the options */
parseConverterOptions(converterName, lookup->cnvName, lookup->locale, &lookup->options, err);
parseConverterOptions(converterName, pPieces, pArgs, err);
if (U_FAILURE(*err)) {
/* Very bad name used. */
return NULL;
}
/* get the canonical converter name */
lookup->realName = ucnv_io_getConverterName(lookup->cnvName, &mayContainOption, &internalErrorCode);
if (U_FAILURE(internalErrorCode) || lookup->realName == NULL) {
pArgs->name = ucnv_io_getConverterName(pArgs->name, &mayContainOption, &internalErrorCode);
if (U_FAILURE(internalErrorCode) || pArgs->name == NULL) {
/*
* set the input name in case the converter was added
* without updating the alias table, or when there is no alias table
*/
lookup->realName = lookup->cnvName;
pArgs->name = pPieces->cnvName;
}
}
/* separate the converter name from the options */
if(mayContainOption && lookup->realName != lookup->cnvName) {
parseConverterOptions(lookup->realName, lookup->cnvName, lookup->locale, &lookup->options, err);
lookup->realName = lookup->cnvName;
if(mayContainOption && pArgs->name != pPieces->cnvName) {
parseConverterOptions(pArgs->name, pPieces, pArgs, err);
}
/* get the shared data for an algorithmic converter, if it is one */
if (checkForAlgorithmic) {
mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName(lookup->realName);
mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName(pArgs->name);
}
if (mySharedConverterData == NULL)
{
@ -767,16 +807,11 @@ ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UEr
/* 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=lookup->options;
args.pkg=NULL;
args.name=lookup->realName;
pArgs->nestedLoads=1;
pArgs->pkg=NULL;
umtx_lock(&cnvCacheMutex);
mySharedConverterData = ucnv_load(&args, err);
mySharedConverterData = ucnv_load(pArgs, err);
umtx_unlock(&cnvCacheMutex);
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
{
@ -790,7 +825,8 @@ ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UEr
UConverter *
ucnv_createConverter(UConverter *myUConverter, const char *converterName, UErrorCode * err)
{
UConverterLookupData stackLookup;
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
UConverterSharedData *mySharedConverterData;
UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
@ -798,25 +834,16 @@ ucnv_createConverter(UConverter *myUConverter, const char *converterName, UError
if(U_SUCCESS(*err)) {
UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open converter %s", converterName);
mySharedConverterData = ucnv_loadSharedData(converterName, &stackLookup, err);
mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
myUConverter = ucnv_createConverterFromSharedData(
myUConverter, mySharedConverterData,
&stackArgs,
err);
if(U_SUCCESS(*err)) {
myUConverter = ucnv_createConverterFromSharedData(
myUConverter, mySharedConverterData,
stackLookup.realName, stackLookup.locale, stackLookup.options,
err);
if(U_SUCCESS(*err)) {
UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
return myUConverter;
}
/*
else mySharedConverterData was already cleaned up by
ucnv_createConverterFromSharedData.
*/
/*else {
ucnv_unloadSharedDataIfReady(mySharedConverterData);
}*/
UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
return myUConverter;
}
}
@ -825,6 +852,31 @@ ucnv_createConverter(UConverter *myUConverter, const char *converterName, UError
return NULL;
}
U_CFUNC UBool
ucnv_canCreateConverter(const char *converterName, UErrorCode *err) {
UConverter myUConverter;
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
UConverterSharedData *mySharedConverterData;
UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
if(U_SUCCESS(*err)) {
UTRACE_DATA1(UTRACE_OPEN_CLOSE, "test if can open converter %s", converterName);
stackArgs.onlyTestIsLoadable=TRUE;
mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
ucnv_createConverterFromSharedData(
&myUConverter, mySharedConverterData,
&stackArgs,
err);
ucnv_unloadSharedDataIfReady(mySharedConverterData);
}
UTRACE_EXIT_STATUS(*err);
return U_SUCCESS(*err) && stackArgs.isLoadable;
}
UConverter *
ucnv_createAlgorithmicConverter(UConverter *myUConverter,
UConverterType type,
@ -832,7 +884,7 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter,
UErrorCode *err) {
UConverter *cnv;
const UConverterSharedData *sharedData;
UBool isAlgorithmicConverter;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_ALGORITHMIC);
UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open algorithmic converter type %d", (int32_t)type);
@ -844,18 +896,24 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter,
}
sharedData = converterData[type];
umtx_lock(&cnvCacheMutex);
isAlgorithmicConverter = (UBool)(sharedData == NULL || sharedData->referenceCounter != ~0);
umtx_unlock(&cnvCacheMutex);
if (isAlgorithmicConverter) {
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if(sharedData == NULL || sharedData->referenceCounter != ~0) {
/* not a valid type, or not an algorithmic converter */
*err = U_ILLEGAL_ARGUMENT_ERROR;
UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
return NULL;
}
cnv = ucnv_createConverterFromSharedData(myUConverter, (UConverterSharedData *)sharedData, "",
locale != NULL ? locale : "", options, err);
stackArgs.name = "";
stackArgs.options = options;
stackArgs.locale=locale;
cnv = ucnv_createConverterFromSharedData(
myUConverter, (UConverterSharedData *)sharedData,
&stackArgs, err);
UTRACE_EXIT_PTR_STATUS(cnv, *err);
return cnv;
@ -864,11 +922,10 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter,
UConverter*
ucnv_createConverterFromPackage(const char *packageName, const char *converterName, UErrorCode * err)
{
char cnvName[UCNV_MAX_CONVERTER_NAME_LENGTH], locale[ULOC_FULLNAME_CAPACITY];
UConverter *myUConverter;
UConverterSharedData *mySharedConverterData;
UConverterLoadArgs args={ 0 };
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_PACKAGE);
@ -879,21 +936,21 @@ ucnv_createConverterFromPackage(const char *packageName, const char *converterNa
UTRACE_DATA2(UTRACE_OPEN_CLOSE, "open converter %s from package %s", converterName, packageName);
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);
stackPieces.cnvName[0] = 0;
stackPieces.locale[0] = 0;
stackPieces.options = 0;
parseConverterOptions(converterName, &stackPieces, &stackArgs, err);
if (U_FAILURE(*err)) {
/* Very bad name used. */
UTRACE_EXIT_STATUS(*err);
return NULL;
}
args.name=cnvName;
stackArgs.nestedLoads=1;
stackArgs.pkg=packageName;
/* open the data, unflatten the shared structure */
mySharedConverterData = createConverterFromFile(&args, err);
mySharedConverterData = createConverterFromFile(&stackArgs, err);
if (U_FAILURE(*err)) {
UTRACE_EXIT_STATUS(*err);
@ -901,7 +958,7 @@ ucnv_createConverterFromPackage(const char *packageName, const char *converterNa
}
/* create the actual converter */
myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, cnvName, locale, args.options, err);
myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, &stackArgs, err);
if (U_FAILURE(*err)) {
ucnv_close(myUConverter);
@ -917,17 +974,22 @@ ucnv_createConverterFromPackage(const char *packageName, const char *converterNa
UConverter*
ucnv_createConverterFromSharedData(UConverter *myUConverter,
UConverterSharedData *mySharedConverterData,
const char *realName, const char *locale, uint32_t options,
UConverterLoadArgs *pArgs,
UErrorCode *err)
{
UBool isCopyLocal;
if(U_FAILURE(*err)) {
ucnv_unloadSharedDataIfReady(mySharedConverterData);
return myUConverter;
}
if(myUConverter == NULL)
{
myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
if(myUConverter == NULL)
{
*err = U_MEMORY_ALLOCATION_ERROR;
ucnv_unloadSharedDataIfReady(mySharedConverterData);
return NULL;
}
isCopyLocal = FALSE;
@ -940,20 +1002,24 @@ ucnv_createConverterFromSharedData(UConverter *myUConverter,
myUConverter->isCopyLocal = isCopyLocal;
/*myUConverter->isExtraLocal = FALSE;*/ /* Set by the memset call */
myUConverter->sharedData = mySharedConverterData;
myUConverter->options = options;
myUConverter->preFromUFirstCP = U_SENTINEL;
myUConverter->fromCharErrorBehaviour = UCNV_TO_U_DEFAULT_CALLBACK;
myUConverter->fromUCharErrorBehaviour = UCNV_FROM_U_DEFAULT_CALLBACK;
myUConverter->toUnicodeStatus = mySharedConverterData->toUnicodeStatus;
myUConverter->maxBytesPerUChar = mySharedConverterData->staticData->maxBytesPerChar;
myUConverter->subChar1 = mySharedConverterData->staticData->subChar1;
myUConverter->subCharLen = mySharedConverterData->staticData->subCharLen;
myUConverter->subChars = (uint8_t *)myUConverter->subUChars;
uprv_memcpy(myUConverter->subChars, mySharedConverterData->staticData->subChar, myUConverter->subCharLen);
myUConverter->toUCallbackReason = UCNV_ILLEGAL; /* default reason to invoke (*fromCharErrorBehaviour) */
myUConverter->options = pArgs->options;
if(!pArgs->onlyTestIsLoadable) {
myUConverter->preFromUFirstCP = U_SENTINEL;
myUConverter->fromCharErrorBehaviour = UCNV_TO_U_DEFAULT_CALLBACK;
myUConverter->fromUCharErrorBehaviour = UCNV_FROM_U_DEFAULT_CALLBACK;
myUConverter->toUnicodeStatus = mySharedConverterData->toUnicodeStatus;
myUConverter->maxBytesPerUChar = mySharedConverterData->staticData->maxBytesPerChar;
myUConverter->subChar1 = mySharedConverterData->staticData->subChar1;
myUConverter->subCharLen = mySharedConverterData->staticData->subCharLen;
myUConverter->subChars = (uint8_t *)myUConverter->subUChars;
uprv_memcpy(myUConverter->subChars, mySharedConverterData->staticData->subChar, myUConverter->subCharLen);
myUConverter->toUCallbackReason = UCNV_ILLEGAL; /* default reason to invoke (*fromCharErrorBehaviour) */
}
if(mySharedConverterData->impl->open != NULL) {
mySharedConverterData->impl->open(myUConverter, realName, locale, options, err);
if(mySharedConverterData->impl->open == NULL) {
pArgs->isLoadable = pArgs->onlyTestIsLoadable;
} else {
mySharedConverterData->impl->open(myUConverter, pArgs, err);
if(U_FAILURE(*err)) {
ucnv_close(myUConverter);
return NULL;
@ -1073,8 +1139,7 @@ static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
for (idx = 0; idx < allConverterCount; idx++) {
localStatus = U_ZERO_ERROR;
converterName = uenum_next(allConvEnum, NULL, &localStatus);
ucnv_close(ucnv_createConverter(&tempConverter, converterName, &localStatus));
if (U_SUCCESS(localStatus)) {
if (ucnv_canCreateConverter(converterName, &localStatus)) {
localConverterList[localConverterCount++] = converterName;
}
}
@ -1130,19 +1195,23 @@ you shouldn't be modifying or deleting the string from a separate thread.
*/
static U_INLINE void
internalSetName(const char *name, UErrorCode *status) {
UConverterLookupData lookup;
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
int32_t length=(int32_t)(uprv_strlen(name));
UBool containsOption = (UBool)(uprv_strchr(name, UCNV_OPTION_SEP_CHAR) != NULL);
const UConverterSharedData *algorithmicSharedData;
lookup.locale[0] = 0;
lookup.options = 0;
lookup.realName = name;
stackArgs.name = name;
if(containsOption) {
parseConverterOptions(lookup.realName, lookup.cnvName, lookup.locale, &lookup.options, status);
lookup.realName = lookup.cnvName;
stackPieces.cnvName[0] = 0;
stackPieces.locale[0] = 0;
stackPieces.options = 0;
parseConverterOptions(name, &stackPieces, &stackArgs, status);
if(U_FAILURE(*status)) {
return;
}
}
algorithmicSharedData = getAlgorithmicTypeFromName(lookup.realName);
algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
umtx_lock(&cnvCacheMutex);

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 1999-2007, International Business Machines
* Copyright (C) 1999-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
@ -49,9 +49,11 @@ typedef struct UConverterSharedData UConverterSharedData;
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 */
UBool onlyTestIsLoadable; /* input: don't actually load */
UBool isLoadable; /* output, if onlyTestIsLoadable is set */
int16_t reserved; /* reserved - for good alignment of the pointers */
uint32_t options;
const char *pkg, *name;
const char *pkg, *name, *locale;
} UConverterLoadArgs;
typedef void (*UConverterLoad) (UConverterSharedData *sharedData,
@ -59,7 +61,7 @@ typedef void (*UConverterLoad) (UConverterSharedData *sharedData,
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);
typedef void (*UConverterOpen) (UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *pErrorCode);
typedef void (*UConverterClose) (UConverter *cnv);
typedef enum UConverterResetChoice {

View file

@ -42,6 +42,15 @@
(name[4]=='8' && name[5]==0) : \
(name[3]=='8' && name[4]==0)))
typedef struct {
char cnvName[UCNV_MAX_CONVERTER_NAME_LENGTH];
char locale[ULOC_FULLNAME_CAPACITY];
uint32_t options;
} UConverterNamePieces;
U_CFUNC UBool
ucnv_canCreateConverter(const char *converterName, UErrorCode *err);
/* figures out if we need to go to file to read in the data tables.
* @param converterName The name of the converter
* @param err The error code
@ -66,28 +75,41 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter,
const char *locale, uint32_t options,
UErrorCode *err);
/* Creates a converter from shared data
/*
* Creates a converter from shared data.
* Adopts mySharedConverterData: No matter what happens, the caller must not
* unload mySharedConverterData, except via ucnv_close(return value)
* if this function is successful.
*/
UConverter*
ucnv_createConverterFromSharedData(UConverter *myUConverter, UConverterSharedData *mySharedConverterData, const char *realName, const char *locale, uint32_t options, UErrorCode *err);
ucnv_createConverterFromSharedData(UConverter *myUConverter,
UConverterSharedData *mySharedConverterData,
UConverterLoadArgs *pArgs,
UErrorCode *err);
UConverter* ucnv_createConverterFromPackage(const char *packageName, const char *converterName,
UErrorCode *err);
typedef struct {
char cnvName[UCNV_MAX_CONVERTER_NAME_LENGTH], locale[ULOC_FULLNAME_CAPACITY];
const char *realName;
uint32_t options;
} UConverterLookupData;
/**
* Load a converter but do not create a UConverter object.
* Simply return the UConverterSharedData.
* Performs alias lookup etc.
* The UConverterNamePieces need not be initialized
* before calling this function.
* The UConverterLoadArgs must be initialized
* before calling this function.
* If the args are passed in, then the pieces must be passed in too.
* In other words, the following combinations are allowed:
* - pieces==NULL && args==NULL
* - pieces!=NULL && args==NULL
* - pieces!=NULL && args!=NULL
* @internal
*/
UConverterSharedData *
ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UErrorCode * err);
ucnv_loadSharedData(const char *converterName,
UConverterNamePieces *pieces,
UConverterLoadArgs *pArgs,
UErrorCode * err);
/**
* This may unload the shared data in a thread safe manner.

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2000-2007, International Business Machines
* Copyright (C) 2000-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnv_lmb.cpp
@ -519,6 +519,7 @@ typedef struct
}
UConverterDataLMBCS;
static void _LMBCSClose(UConverter * _this);
#define DECLARE_LMBCS_DATA(n) \
static const UConverterImpl _LMBCSImpl##n={\
@ -556,53 +557,53 @@ optimization group. So, we put the common stuff into a worker function,
and set up another macro to stamp out the 12 open functions:*/
#define DEFINE_LMBCS_OPEN(n) \
static void \
_LMBCSOpen##n(UConverter* _this,const char* name,const char* locale,uint32_t options,UErrorCode* err) \
{ _LMBCSOpenWorker(_this, name,locale,options, err, n);}
_LMBCSOpen##n(UConverter* _this, UConverterLoadArgs* pArgs, UErrorCode* err) \
{ _LMBCSOpenWorker(_this, pArgs, err, n); }
/* Here's the open worker & the common close function */
static void
_LMBCSOpenWorker(UConverter* _this,
const char* name,
const char* locale,
uint32_t options,
UErrorCode* err,
ulmbcs_byte_t OptGroup
)
_LMBCSOpenWorker(UConverter* _this,
UConverterLoadArgs *pArgs,
UErrorCode* err,
ulmbcs_byte_t OptGroup)
{
UConverterDataLMBCS * extraInfo = (UConverterDataLMBCS*)uprv_malloc (sizeof (UConverterDataLMBCS));
UConverterDataLMBCS * extraInfo = _this->extraInfo =
(UConverterDataLMBCS*)uprv_malloc (sizeof (UConverterDataLMBCS));
if(extraInfo != NULL)
{
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs={ (int32_t)sizeof(UConverterLoadArgs) };
ulmbcs_byte_t i;
uprv_memset(extraInfo, 0, sizeof(UConverterDataLMBCS));
stackArgs.onlyTestIsLoadable = pArgs->onlyTestIsLoadable;
for (i=0; i <= ULMBCS_GRP_LAST && U_SUCCESS(*err); i++)
{
if(OptGroupByteToCPName[i] != NULL) {
extraInfo->OptGrpConverter[i] = ucnv_loadSharedData(OptGroupByteToCPName[i], NULL, err);
extraInfo->OptGrpConverter[i] = ucnv_loadSharedData(OptGroupByteToCPName[i], &stackPieces, &stackArgs, err);
}
}
if(U_SUCCESS(*err)) {
extraInfo->OptGroup = OptGroup;
extraInfo->localeConverterIndex = FindLMBCSLocale(locale);
} else {
/* one of the subconverters could not be loaded, unload the previous ones */
while(i > 0) {
if(extraInfo->OptGrpConverter[--i] != NULL) {
ucnv_unloadSharedDataIfReady(extraInfo->OptGrpConverter[i]);
extraInfo->OptGrpConverter[i] = NULL;
}
}
if(U_FAILURE(*err)) {
_LMBCSClose(_this);
return;
}
if(pArgs->onlyTestIsLoadable) {
_LMBCSClose(_this);
pArgs->isLoadable=TRUE;
return;
}
extraInfo->OptGroup = OptGroup;
extraInfo->localeConverterIndex = FindLMBCSLocale(pArgs->locale);
}
else
{
*err = U_MEMORY_ALLOCATION_ERROR;
}
_this->extraInfo = extraInfo;
}
static void
@ -620,6 +621,7 @@ _LMBCSClose(UConverter * _this)
}
if (!_this->isExtraLocal) {
uprv_free (_this->extraInfo);
_this->extraInfo = NULL;
}
}
}

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2002-2008, International Business Machines
* Copyright (C) 2002-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnv_u16.c
@ -1179,11 +1179,13 @@ _UTF16Reset(UConverter *cnv, UConverterResetChoice choice) {
static void
_UTF16Open(UConverter *cnv,
const char *name,
const char *locale,
uint32_t options,
UConverterLoadArgs *pArgs,
UErrorCode *pErrorCode) {
_UTF16Reset(cnv, UCNV_RESET_BOTH);
if(pArgs->onlyTestIsLoadable) {
pArgs->isLoadable=TRUE;
} else {
_UTF16Reset(cnv, UCNV_RESET_BOTH);
}
}
static const char utf16BOM[8]={ (char)0xfe, (char)0xff, 0, 0, (char)0xff, (char)0xfe, 0, 0 };

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2002-2006, International Business Machines
* Copyright (C) 2002-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnv_u32.c
@ -1033,11 +1033,13 @@ _UTF32Reset(UConverter *cnv, UConverterResetChoice choice) {
static void
_UTF32Open(UConverter *cnv,
const char *name,
const char *locale,
uint32_t options,
UConverterLoadArgs *pArgs,
UErrorCode *pErrorCode) {
_UTF32Reset(cnv, UCNV_RESET_BOTH);
if(pArgs->onlyTestIsLoadable) {
pArgs->isLoadable=TRUE;
} else {
_UTF32Reset(cnv, UCNV_RESET_BOTH);
}
}
static const char utf32BOM[8]={ 0, 0, (char)0xfe, (char)0xff, (char)0xff, (char)0xfe, 0, 0 };

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2002-2004, International Business Machines
* Copyright (C) 2002-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnv_u7.c
@ -190,12 +190,12 @@ _UTF7Reset(UConverter *cnv, UConverterResetChoice choice) {
static void
_UTF7Open(UConverter *cnv,
const char *name,
const char *locale,
uint32_t options,
UConverterLoadArgs *pArgs,
UErrorCode *pErrorCode) {
if((options&0xf)<=1) {
cnv->fromUnicodeStatus=(options&0xf)<<28;
if(pArgs->onlyTestIsLoadable) {
pArgs->isLoadable=TRUE;
} else if((pArgs->options&0xf)<=1) {
cnv->fromUnicodeStatus=(pArgs->options&0xf)<<28;
_UTF7Reset(cnv, UCNV_RESET_BOTH);
} else {
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2000-2008, International Business Machines
* Copyright (C) 2000-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnvhz.c
@ -24,6 +24,7 @@
#include "unicode/uset.h"
#include "ucnv_bld.h"
#include "ucnv_cnv.h"
#include "ucnv_imp.h"
#define UCNV_TILDE 0x7E /* ~ */
#define UCNV_OPEN_BRACE 0x7B /* { */
@ -65,7 +66,17 @@ typedef struct{
static void
_HZOpen(UConverter *cnv, const char *name,const char *locale,uint32_t options, UErrorCode *errorCode){
_HZOpen(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode){
UConverter *gbConverter;
if(pArgs->onlyTestIsLoadable) {
UErrorCode localStatus = U_ZERO_ERROR;
pArgs->isLoadable = ucnv_canCreateConverter("GBK", &localStatus);
return;
}
gbConverter = ucnv_open("GBK", errorCode);
if(U_FAILURE(*errorCode)) {
return;
}
cnv->toUnicodeStatus = 0;
cnv->fromUnicodeStatus= 0;
cnv->mode=0;
@ -73,9 +84,10 @@ _HZOpen(UConverter *cnv, const char *name,const char *locale,uint32_t options, U
cnv->extraInfo = uprv_malloc(sizeof(UConverterDataHZ));
if(cnv->extraInfo != NULL){
uprv_memset(cnv->extraInfo, 0, sizeof(UConverterDataHZ));
((UConverterDataHZ*)cnv->extraInfo)->gbConverter = ucnv_open("GBK",errorCode);
((UConverterDataHZ*)cnv->extraInfo)->gbConverter = gbConverter;
}
else {
ucnv_close(gbConverter);
*errorCode = U_MEMORY_ALLOCATION_ERROR;
return;
}

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2000-2008, International Business Machines
* Copyright (C) 2000-2009, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnvisci.c
@ -152,9 +152,10 @@ static const LookupDataStruct lookupInitialData[]={
};
static void initializeSets() {
/* TODO: Replace the following two lines with PNJ_CONSONANT_SET = uset_openEmpty(); */
PNJ_CONSONANT_SET = uset_open(0,0);
uset_clear(PNJ_CONSONANT_SET);
uset_addRange(PNJ_CONSONANT_SET, 0x0A15, 0x0A28);
uset_addRange(PNJ_CONSONANT_SET, 0x0A2A, 0x0A30);
uset_addRange(PNJ_CONSONANT_SET, 0x0A35, 0x0A36);
@ -170,8 +171,12 @@ static void initializeSets() {
uset_compact(PNJ_BINDI_TIPPI_SET);
}
static void _ISCIIOpen(UConverter *cnv, const char *name, const char *locale,
uint32_t options, UErrorCode *errorCode) {
static void _ISCIIOpen(UConverter *cnv, UConverterLoadArgs *pArgs, UErrorCode *errorCode) {
if(pArgs->onlyTestIsLoadable) {
pArgs->isLoadable=TRUE;
return;
}
/* Ensure that the sets used in special handling of certain Gurmukhi characters are initialized. */
initializeSets();
@ -186,20 +191,20 @@ static void _ISCIIOpen(UConverter *cnv, const char *name, const char *locale,
converterData->contextCharFromUnicode=0x0000;
converterData->resetToDefaultToUnicode=FALSE;
/* check if the version requested is supported */
if ((options & UCNV_OPTIONS_VERSION_MASK) < 9) {
if ((pArgs->options & UCNV_OPTIONS_VERSION_MASK) < 9) {
/* initialize state variables */
converterData->currentDeltaFromUnicode
= converterData->currentDeltaToUnicode
= converterData->defDeltaToUnicode = (uint16_t)(lookupInitialData[options & UCNV_OPTIONS_VERSION_MASK].uniLang * DELTA);
= converterData->defDeltaToUnicode = (uint16_t)(lookupInitialData[pArgs->options & UCNV_OPTIONS_VERSION_MASK].uniLang * DELTA);
converterData->currentMaskFromUnicode
= converterData->currentMaskToUnicode
= converterData->defMaskToUnicode = lookupInitialData[options & UCNV_OPTIONS_VERSION_MASK].maskEnum;
= converterData->defMaskToUnicode = lookupInitialData[pArgs->options & UCNV_OPTIONS_VERSION_MASK].maskEnum;
converterData->isFirstBuffer=TRUE;
(void)uprv_strcpy(converterData->name, ISCII_CNV_PREFIX);
len = (int32_t)uprv_strlen(converterData->name);
converterData->name[len]= (char)((options & UCNV_OPTIONS_VERSION_MASK) + '0');
converterData->name[len]= (char)((pArgs->options & UCNV_OPTIONS_VERSION_MASK) + '0');
converterData->name[len+1]=0;
converterData->prevToUnicodeStatus = 0x0000;

View file

@ -1,7 +1,7 @@
/*
******************************************************************************
*
* Copyright (C) 2000-2008, International Business Machines
* Copyright (C) 2000-2009, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
@ -1400,6 +1400,8 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData,
/* 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.onlyTestIsLoadable=pArgs->onlyTestIsLoadable;
args.isLoadable=pArgs->isLoadable;
args.reserved=pArgs->reserved;
args.options=pArgs->options;
args.pkg=pArgs->pkg;
@ -1415,6 +1417,15 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData,
*pErrorCode=U_INVALID_TABLE_FORMAT;
return;
}
if(pArgs->onlyTestIsLoadable) {
/*
* Exit as soon as we know that we can load the converter
* and the format is valid and supported.
* The worst that can happen in the following code is a memory
* allocation error.
*/
return;
}
/* copy the base table data */
uprv_memcpy(mbcsTable, &baseSharedData->mbcs, sizeof(UConverterMBCSTable));
@ -1529,6 +1540,15 @@ ucnv_MBCSLoad(UConverterSharedData *sharedData,
*pErrorCode=U_INVALID_TABLE_FORMAT;
return;
}
if(pArgs->onlyTestIsLoadable) {
/*
* Exit as soon as we know that we can load the converter
* and the format is valid and supported.
* The worst that can happen in the following code is a memory
* allocation error.
*/
return;
}
mbcsTable->countStates=(uint8_t)header->countStates;
mbcsTable->countToUFallbacks=header->countToUFallbacks;
@ -1660,24 +1680,27 @@ ucnv_MBCSUnload(UConverterSharedData *sharedData) {
static void
ucnv_MBCSOpen(UConverter *cnv,
const char *name,
const char *locale,
uint32_t options,
UErrorCode *pErrorCode) {
UConverterLoadArgs *pArgs,
UErrorCode *pErrorCode) {
UConverterMBCSTable *mbcsTable;
const int32_t *extIndexes;
uint8_t outputType;
int8_t maxBytesPerUChar;
if(pArgs->onlyTestIsLoadable) {
pArgs->isLoadable=TRUE;
return;
}
mbcsTable=&cnv->sharedData->mbcs;
outputType=mbcsTable->outputType;
if(outputType==MBCS_OUTPUT_DBCS_ONLY) {
/* the swaplfnl option does not apply, remove it */
cnv->options=options&=~UCNV_OPTION_SWAP_LFNL;
cnv->options=pArgs->options&=~UCNV_OPTION_SWAP_LFNL;
}
if((options&UCNV_OPTION_SWAP_LFNL)!=0) {
if((pArgs->options&UCNV_OPTION_SWAP_LFNL)!=0) {
/* do this because double-checked locking is broken */
UBool isCached;
@ -1692,13 +1715,13 @@ ucnv_MBCSOpen(UConverter *cnv,
}
/* the option does not apply, remove it */
cnv->options=options&=~UCNV_OPTION_SWAP_LFNL;
cnv->options=pArgs->options&=~UCNV_OPTION_SWAP_LFNL;
}
}
}
if(uprv_strstr(name, "18030")!=NULL) {
if(uprv_strstr(name, "gb18030")!=NULL || uprv_strstr(name, "GB18030")!=NULL) {
if(uprv_strstr(pArgs->name, "18030")!=NULL) {
if(uprv_strstr(pArgs->name, "gb18030")!=NULL || uprv_strstr(pArgs->name, "GB18030")!=NULL) {
/* set a flag for GB 18030 mode, which changes the callback behavior */
cnv->options|=_MBCS_OPTION_GB18030;
}

View file

@ -1,7 +1,7 @@
/*
******************************************************************************
*
* Copyright (C) 2000-2006, International Business Machines
* Copyright (C) 2000-2009, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
@ -190,10 +190,13 @@ _SCSUReset(UConverter *cnv, UConverterResetChoice choice) {
static void
_SCSUOpen(UConverter *cnv,
const char *name,
const char *locale,
uint32_t options,
UConverterLoadArgs *pArgs,
UErrorCode *pErrorCode) {
const char *locale=pArgs->locale;
if(pArgs->onlyTestIsLoadable) {
pArgs->isLoadable=TRUE;
return;
}
cnv->extraInfo=uprv_malloc(sizeof(SCSUData));
if(cnv->extraInfo!=NULL) {
if(locale!=NULL && locale[0]=='j' && locale[1]=='a' && (locale[2]==0 || locale[2]=='_')) {