]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ucnv_bld.c
ICU-461.18.tar.gz
[apple/icu.git] / icuSources / common / ucnv_bld.c
index 3a30cda7f1e76be7431d1a99f6ba0059e7f372c6..a95b7b8172d8ce49e3b0731facf8e04c48531b4c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  ********************************************************************
  * COPYRIGHT:
- * Copyright (c) 1996-2008, International Business Machines Corporation and
+ * Copyright (c) 1996-2010, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************
  *
@@ -158,6 +158,8 @@ static UMTX        cnvCacheMutex = NULL;  /* Mutex for synchronizing cnv cache a
 static const char **gAvailableConverters = NULL;
 static uint16_t gAvailableConverterCount = 0;
 
+#if !U_CHARSET_IS_UTF8
+
 /* This contains the resolved converter name. So no further alias lookup is needed again. */
 static char gDefaultConverterNameBuffer[UCNV_MAX_CONVERTER_NAME_LENGTH + 1]; /* +1 for NULL */
 static const char *gDefaultConverterName = NULL;
@@ -173,6 +175,7 @@ static const UConverterSharedData *gDefaultAlgorithmicSharedData = NULL;
 /* Does gDefaultConverterName have a converter option and require extra parsing? */
 static UBool gDefaultConverterContainsOption;
 
+#endif  /* !U_CHARSET_IS_UTF8 */
 
 static const char DATA_TYPE[] = "cnv";
 
@@ -201,10 +204,12 @@ static UBool U_CALLCONV ucnv_cleanup(void) {
     /* Isn't called from flushCache because other threads may have preexisting references to the table. */
     ucnv_flushAvailableConverterCache();
 
+#if !U_CHARSET_IS_UTF8
     gDefaultConverterName = NULL;
     gDefaultConverterNameBuffer[0] = 0;
     gDefaultConverterContainsOption = FALSE;
     gDefaultAlgorithmicSharedData = NULL;
+#endif
 
     umtx_destroy(&cnvCacheMutex);    /* Don't worry about destroying the mutex even  */
                                      /*  if the hash table still exists.  The mutex  */
@@ -214,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 &&
@@ -546,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);
@@ -598,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++;
@@ -605,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) {
@@ -636,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;
@@ -646,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;
                 }
 
@@ -654,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 */
@@ -687,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;
@@ -698,18 +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;
         }
@@ -717,46 +765,40 @@ ucnv_loadSharedData(const char *converterName, UConverterLookupData *lookup, UEr
         checkForAlgorithmic = FALSE;
         mayContainOption = gDefaultConverterContainsOption;
         /* the default converter name is already canonical */
+#endif
     }
-    else if((converterName[0] == 'U' ?
-            (                           converterName[1] == 'T' && converterName[2] == 'F') :
-            (converterName[0] == 'u' && converterName[1] == 't' && converterName[2] == 'f'))
-        &&
-        (converterName[3] == '-' ?
-            (converterName[4] == '8' && converterName[5] == 0) :
-            (converterName[3] == '8' && converterName[4] == 0)))
-    {
+    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)
     {
@@ -765,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))
         {
@@ -788,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);
@@ -796,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;
         }
     }
 
@@ -823,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);
+}
+
 UConverter *
 ucnv_createAlgorithmicConverter(UConverter *myUConverter,
                                 UConverterType type,
@@ -830,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);
@@ -842,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;
@@ -862,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);
 
@@ -877,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);
@@ -899,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);
@@ -915,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;
@@ -938,21 +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(U_FAILURE(*err)) {
+        mySharedConverterData->impl->open(myUConverter, pArgs, err);
+        if(U_FAILURE(*err) && !pArgs->onlyTestIsLoadable) {
+            /* don't ucnv_close() if onlyTestIsLoadable because not fully initialized */
             ucnv_close(myUConverter);
             return NULL;
         }
@@ -970,13 +1037,13 @@ ucnv_flushCache ()
     int32_t pos;
     int32_t tableDeletedNum = 0;
     const UHashElement *e;
-    UErrorCode status = U_ILLEGAL_ARGUMENT_ERROR;
+    /*UErrorCode status = U_ILLEGAL_ARGUMENT_ERROR;*/
     int32_t i, remaining;
 
     UTRACE_ENTRY_OC(UTRACE_UCNV_FLUSH_CACHE);
 
     /* Close the default converter without creating a new one so that everything will be flushed. */
-    ucnv_close(u_getDefaultConverter(&status));
+    u_flushDefaultConverter();
 
     /*if shared data hasn't even been lazy evaluated yet
     * return 0
@@ -1071,8 +1138,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;
             }
         }
@@ -1080,8 +1146,8 @@ static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
 
         umtx_lock(&cnvCacheMutex);
         if (gAvailableConverters == NULL) {
-            gAvailableConverters = localConverterList;
             gAvailableConverterCount = localConverterCount;
+            gAvailableConverters = localConverterList;
             ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
         }
         else {
@@ -1113,6 +1179,7 @@ ucnv_bld_getAvailableConverter(uint16_t n, UErrorCode *pErrorCode) {
 
 /* default converter name --------------------------------------------------- */
 
+#if !U_CHARSET_IS_UTF8
 /*
 Copy the canonical converter name.
 ucnv_getDefaultName must be thread safe, which can call this function.
@@ -1127,19 +1194,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);
 
@@ -1147,12 +1218,16 @@ internalSetName(const char *name, UErrorCode *status) {
     gDefaultConverterContainsOption = containsOption;
     uprv_memcpy(gDefaultConverterNameBuffer, name, length);
     gDefaultConverterNameBuffer[length]=0;
+
+    /* gDefaultConverterName MUST be the last global var set by this function.  */
+    /*    It is the variable checked in ucnv_getDefaultName() to see if initialization is required. */
     gDefaultConverterName = gDefaultConverterNameBuffer;
 
     ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
 
     umtx_unlock(&cnvCacheMutex);
 }
+#endif
 
 /*
  * In order to be really thread-safe, the get function would have to take
@@ -1164,6 +1239,9 @@ internalSetName(const char *name, UErrorCode *status) {
 
 U_CAPI const char*  U_EXPORT2
 ucnv_getDefaultName() {
+#if U_CHARSET_IS_UTF8
+    return "UTF-8";
+#else
     /* local variable to be thread-safe */
     const char *name;
 
@@ -1208,6 +1286,7 @@ ucnv_getDefaultName() {
     }
 
     return name;
+#endif
 }
 
 /*
@@ -1216,6 +1295,7 @@ See internalSetName or the API reference for details.
 */
 U_CAPI void U_EXPORT2
 ucnv_setDefaultName(const char *converterName) {
+#if !U_CHARSET_IS_UTF8
     if(converterName==NULL) {
         /* reset to the default codepage */
         gDefaultConverterName=NULL;
@@ -1237,7 +1317,11 @@ ucnv_setDefaultName(const char *converterName) {
 
         /* The close may make the current name go away. */
         ucnv_close(cnv);
+  
+        /* reset the converter cache */
+        u_flushDefaultConverter();
     }
+#endif
 }
 
 /* data swapping ------------------------------------------------------------ */