Home | History | Annotate | Download | only in common
      1 /*
      2  ********************************************************************
      3  * COPYRIGHT:
      4  * Copyright (c) 1996-2015, International Business Machines Corporation and
      5  * others. All Rights Reserved.
      6  ********************************************************************
      7  *
      8  *  ucnv_bld.cpp:
      9  *
     10  *  Defines functions that are used in the creation/initialization/deletion
     11  *  of converters and related structures.
     12  *  uses uconv_io.h routines to access disk information
     13  *  is used by ucnv.h to implement public API create/delete/flushCache routines
     14  * Modification History:
     15  *
     16  *   Date        Name        Description
     17  *
     18  *   06/20/2000  helena      OS/400 port changes; mostly typecast.
     19  *   06/29/2000  helena      Major rewrite of the callback interface.
     20 */
     21 
     22 #include "unicode/utypes.h"
     23 
     24 #if !UCONFIG_NO_CONVERSION
     25 
     26 #include "unicode/putil.h"
     27 #include "unicode/udata.h"
     28 #include "unicode/ucnv.h"
     29 #include "unicode/uloc.h"
     30 #include "mutex.h"
     31 #include "putilimp.h"
     32 #include "uassert.h"
     33 #include "utracimp.h"
     34 #include "ucnv_io.h"
     35 #include "ucnv_bld.h"
     36 #include "ucnvmbcs.h"
     37 #include "ucnv_ext.h"
     38 #include "ucnv_cnv.h"
     39 #include "ucnv_imp.h"
     40 #include "uhash.h"
     41 #include "umutex.h"
     42 #include "cstring.h"
     43 #include "cmemory.h"
     44 #include "ucln_cmn.h"
     45 #include "ustr_cnv.h"
     46 
     47 
     48 #if 0
     49 #include <stdio.h>
     50 extern void UCNV_DEBUG_LOG(char *what, char *who, void *p, int l);
     51 #define UCNV_DEBUG_LOG(x,y,z) UCNV_DEBUG_LOG(x,y,z,__LINE__)
     52 #else
     53 # define UCNV_DEBUG_LOG(x,y,z)
     54 #endif
     55 
     56 static const UConverterSharedData * const
     57 converterData[UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES]={
     58     NULL, NULL,
     59 
     60 #if UCONFIG_NO_LEGACY_CONVERSION
     61     NULL,
     62 #else
     63     &_MBCSData,
     64 #endif
     65 
     66     &_Latin1Data,
     67     &_UTF8Data, &_UTF16BEData, &_UTF16LEData,
     68 #if UCONFIG_ONLY_HTML_CONVERSION
     69     NULL, NULL,
     70 #else
     71     &_UTF32BEData, &_UTF32LEData,
     72 #endif
     73     NULL,
     74 
     75 #if UCONFIG_NO_LEGACY_CONVERSION
     76     NULL,
     77 #else
     78     &_ISO2022Data,
     79 #endif
     80 
     81 #if UCONFIG_NO_LEGACY_CONVERSION || UCONFIG_ONLY_HTML_CONVERSION
     82     NULL, NULL, NULL, NULL, NULL, NULL,
     83     NULL, NULL, NULL, NULL, NULL, NULL,
     84     NULL,
     85 #else
     86     &_LMBCSData1,&_LMBCSData2, &_LMBCSData3, &_LMBCSData4, &_LMBCSData5, &_LMBCSData6,
     87     &_LMBCSData8,&_LMBCSData11,&_LMBCSData16,&_LMBCSData17,&_LMBCSData18,&_LMBCSData19,
     88     &_HZData,
     89 #endif
     90 
     91 #if UCONFIG_ONLY_HTML_CONVERSION
     92     NULL,
     93 #else
     94     &_SCSUData,
     95 #endif
     96 
     97 
     98 #if UCONFIG_NO_LEGACY_CONVERSION || UCONFIG_ONLY_HTML_CONVERSION
     99     NULL,
    100 #else
    101     &_ISCIIData,
    102 #endif
    103 
    104     &_ASCIIData,
    105 #if UCONFIG_ONLY_HTML_CONVERSION
    106     NULL, NULL, &_UTF16Data, NULL, NULL, NULL,
    107 #else
    108     &_UTF7Data, &_Bocu1Data, &_UTF16Data, &_UTF32Data, &_CESU8Data, &_IMAPData,
    109 #endif
    110 
    111 #if UCONFIG_NO_LEGACY_CONVERSION || UCONFIG_ONLY_HTML_CONVERSION
    112     NULL,
    113 #else
    114     &_CompoundTextData
    115 #endif
    116 };
    117 
    118 /* Please keep this in binary sorted order for getAlgorithmicTypeFromName.
    119    Also the name should be in lower case and all spaces, dashes and underscores
    120    removed
    121 */
    122 static struct {
    123   const char *name;
    124   const UConverterType type;
    125 } const cnvNameType[] = {
    126 #if !UCONFIG_ONLY_HTML_CONVERSION
    127   { "bocu1", UCNV_BOCU1 },
    128   { "cesu8", UCNV_CESU8 },
    129 #endif
    130 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
    131   { "hz",UCNV_HZ },
    132 #endif
    133 #if !UCONFIG_ONLY_HTML_CONVERSION
    134   { "imapmailboxname", UCNV_IMAP_MAILBOX },
    135 #endif
    136 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
    137   { "iscii", UCNV_ISCII },
    138 #endif
    139 #if !UCONFIG_NO_LEGACY_CONVERSION
    140   { "iso2022", UCNV_ISO_2022 },
    141 #endif
    142   { "iso88591", UCNV_LATIN_1 },
    143 #if !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION
    144   { "lmbcs1", UCNV_LMBCS_1 },
    145   { "lmbcs11",UCNV_LMBCS_11 },
    146   { "lmbcs16",UCNV_LMBCS_16 },
    147   { "lmbcs17",UCNV_LMBCS_17 },
    148   { "lmbcs18",UCNV_LMBCS_18 },
    149   { "lmbcs19",UCNV_LMBCS_19 },
    150   { "lmbcs2", UCNV_LMBCS_2 },
    151   { "lmbcs3", UCNV_LMBCS_3 },
    152   { "lmbcs4", UCNV_LMBCS_4 },
    153   { "lmbcs5", UCNV_LMBCS_5 },
    154   { "lmbcs6", UCNV_LMBCS_6 },
    155   { "lmbcs8", UCNV_LMBCS_8 },
    156 #endif
    157 #if !UCONFIG_ONLY_HTML_CONVERSION
    158   { "scsu", UCNV_SCSU },
    159 #endif
    160   { "usascii", UCNV_US_ASCII },
    161   { "utf16", UCNV_UTF16 },
    162   { "utf16be", UCNV_UTF16_BigEndian },
    163   { "utf16le", UCNV_UTF16_LittleEndian },
    164 #if U_IS_BIG_ENDIAN
    165   { "utf16oppositeendian", UCNV_UTF16_LittleEndian },
    166   { "utf16platformendian", UCNV_UTF16_BigEndian },
    167 #else
    168   { "utf16oppositeendian", UCNV_UTF16_BigEndian},
    169   { "utf16platformendian", UCNV_UTF16_LittleEndian },
    170 #endif
    171 #if !UCONFIG_ONLY_HTML_CONVERSION
    172   { "utf32", UCNV_UTF32 },
    173   { "utf32be", UCNV_UTF32_BigEndian },
    174   { "utf32le", UCNV_UTF32_LittleEndian },
    175 #if U_IS_BIG_ENDIAN
    176   { "utf32oppositeendian", UCNV_UTF32_LittleEndian },
    177   { "utf32platformendian", UCNV_UTF32_BigEndian },
    178 #else
    179   { "utf32oppositeendian", UCNV_UTF32_BigEndian },
    180   { "utf32platformendian", UCNV_UTF32_LittleEndian },
    181 #endif
    182 #endif
    183 #if !UCONFIG_ONLY_HTML_CONVERSION
    184   { "utf7", UCNV_UTF7 },
    185 #endif
    186   { "utf8", UCNV_UTF8 },
    187 #if !UCONFIG_ONLY_HTML_CONVERSION
    188   { "x11compoundtext", UCNV_COMPOUND_TEXT}
    189 #endif
    190 };
    191 
    192 
    193 /*initializes some global variables */
    194 static UHashtable *SHARED_DATA_HASHTABLE = NULL;
    195 static UMutex cnvCacheMutex = U_MUTEX_INITIALIZER;  /* Mutex for synchronizing cnv cache access. */
    196                                                     /*  Note:  the global mutex is used for      */
    197                                                     /*         reference count updates.          */
    198 
    199 static const char **gAvailableConverters = NULL;
    200 static uint16_t gAvailableConverterCount = 0;
    201 static icu::UInitOnce gAvailableConvertersInitOnce = U_INITONCE_INITIALIZER;
    202 
    203 #if !U_CHARSET_IS_UTF8
    204 
    205 /* This contains the resolved converter name. So no further alias lookup is needed again. */
    206 static char gDefaultConverterNameBuffer[UCNV_MAX_CONVERTER_NAME_LENGTH + 1]; /* +1 for NULL */
    207 static const char *gDefaultConverterName = NULL;
    208 
    209 /*
    210 If the default converter is an algorithmic converter, this is the cached value.
    211 We don't cache a full UConverter and clone it because ucnv_clone doesn't have
    212 less overhead than an algorithmic open. We don't cache non-algorithmic converters
    213 because ucnv_flushCache must be able to unload the default converter and its table.
    214 */
    215 static const UConverterSharedData *gDefaultAlgorithmicSharedData = NULL;
    216 
    217 /* Does gDefaultConverterName have a converter option and require extra parsing? */
    218 static UBool gDefaultConverterContainsOption;
    219 
    220 #endif  /* !U_CHARSET_IS_UTF8 */
    221 
    222 static const char DATA_TYPE[] = "cnv";
    223 
    224 /* ucnv_flushAvailableConverterCache. This is only called from ucnv_cleanup().
    225  *                       If it is ever to be called from elsewhere, synchronization
    226  *                       will need to be considered.
    227  */
    228 static void
    229 ucnv_flushAvailableConverterCache() {
    230     gAvailableConverterCount = 0;
    231     if (gAvailableConverters) {
    232         uprv_free((char **)gAvailableConverters);
    233         gAvailableConverters = NULL;
    234     }
    235     gAvailableConvertersInitOnce.reset();
    236 }
    237 
    238 /* ucnv_cleanup - delete all storage held by the converter cache, except any  */
    239 /*                in use by open converters.                                  */
    240 /*                Not thread safe.                                            */
    241 /*                Not supported API.                                          */
    242 static UBool U_CALLCONV ucnv_cleanup(void) {
    243     ucnv_flushCache();
    244     if (SHARED_DATA_HASHTABLE != NULL && uhash_count(SHARED_DATA_HASHTABLE) == 0) {
    245         uhash_close(SHARED_DATA_HASHTABLE);
    246         SHARED_DATA_HASHTABLE = NULL;
    247     }
    248 
    249     /* Isn't called from flushCache because other threads may have preexisting references to the table. */
    250     ucnv_flushAvailableConverterCache();
    251 
    252 #if !U_CHARSET_IS_UTF8
    253     gDefaultConverterName = NULL;
    254     gDefaultConverterNameBuffer[0] = 0;
    255     gDefaultConverterContainsOption = FALSE;
    256     gDefaultAlgorithmicSharedData = NULL;
    257 #endif
    258 
    259     return (SHARED_DATA_HASHTABLE == NULL);
    260 }
    261 
    262 static UBool U_CALLCONV
    263 isCnvAcceptable(void * /*context*/,
    264                 const char * /*type*/, const char * /*name*/,
    265                 const UDataInfo *pInfo) {
    266     return (UBool)(
    267         pInfo->size>=20 &&
    268         pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
    269         pInfo->charsetFamily==U_CHARSET_FAMILY &&
    270         pInfo->sizeofUChar==U_SIZEOF_UCHAR &&
    271         pInfo->dataFormat[0]==0x63 &&   /* dataFormat="cnvt" */
    272         pInfo->dataFormat[1]==0x6e &&
    273         pInfo->dataFormat[2]==0x76 &&
    274         pInfo->dataFormat[3]==0x74 &&
    275         pInfo->formatVersion[0]==6);  /* Everything will be version 6 */
    276 }
    277 
    278 /**
    279  * Un flatten shared data from a UDATA..
    280  */
    281 static UConverterSharedData*
    282 ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCode *status)
    283 {
    284     /* UDataInfo info; -- necessary only if some converters have different formatVersion */
    285     const uint8_t *raw = (const uint8_t *)udata_getMemory(pData);
    286     const UConverterStaticData *source = (const UConverterStaticData *) raw;
    287     UConverterSharedData *data;
    288     UConverterType type = (UConverterType)source->conversionType;
    289 
    290     if(U_FAILURE(*status))
    291         return NULL;
    292 
    293     if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES ||
    294         converterData[type] == NULL ||
    295         converterData[type]->referenceCounter != 1 ||
    296         source->structSize != sizeof(UConverterStaticData))
    297     {
    298         *status = U_INVALID_TABLE_FORMAT;
    299         return NULL;
    300     }
    301 
    302     data = (UConverterSharedData *)uprv_malloc(sizeof(UConverterSharedData));
    303     if(data == NULL) {
    304         *status = U_MEMORY_ALLOCATION_ERROR;
    305         return NULL;
    306     }
    307 
    308     /* copy initial values from the static structure for this type */
    309     uprv_memcpy(data, converterData[type], sizeof(UConverterSharedData));
    310 
    311 #if 0 /* made UConverterMBCSTable part of UConverterSharedData -- markus 20031107 */
    312     /*
    313      * It would be much more efficient if the table were a direct member, not a pointer.
    314      * However, that would add to the size of all UConverterSharedData objects
    315      * even if they do not use this table (especially algorithmic ones).
    316      * If this changes, then the static templates from converterData[type]
    317      * need more entries.
    318      *
    319      * In principle, it would be cleaner if the load() function below
    320      * allocated the table.
    321      */
    322     data->table = (UConverterTable *)uprv_malloc(sizeof(UConverterTable));
    323     if(data->table == NULL) {
    324         uprv_free(data);
    325         *status = U_MEMORY_ALLOCATION_ERROR;
    326         return NULL;
    327     }
    328     uprv_memset(data->table, 0, sizeof(UConverterTable));
    329 #endif
    330 
    331     data->staticData = source;
    332 
    333     data->sharedDataCached = FALSE;
    334 
    335     /* fill in fields from the loaded data */
    336     data->dataMemory = (void*)pData; /* for future use */
    337 
    338     if(data->impl->load != NULL) {
    339         data->impl->load(data, pArgs, raw + source->structSize, status);
    340         if(U_FAILURE(*status)) {
    341             uprv_free(data->table);
    342             uprv_free(data);
    343             return NULL;
    344         }
    345     }
    346     return data;
    347 }
    348 
    349 /*Takes an alias name gets an actual converter file name
    350  *goes to disk and opens it.
    351  *allocates the memory and returns a new UConverter object
    352  */
    353 static UConverterSharedData *createConverterFromFile(UConverterLoadArgs *pArgs, UErrorCode * err)
    354 {
    355     UDataMemory *data;
    356     UConverterSharedData *sharedData;
    357 
    358     UTRACE_ENTRY_OC(UTRACE_UCNV_LOAD);
    359 
    360     if (U_FAILURE (*err)) {
    361         UTRACE_EXIT_STATUS(*err);
    362         return NULL;
    363     }
    364 
    365     UTRACE_DATA2(UTRACE_OPEN_CLOSE, "load converter %s from package %s", pArgs->name, pArgs->pkg);
    366 
    367     data = udata_openChoice(pArgs->pkg, DATA_TYPE, pArgs->name, isCnvAcceptable, NULL, err);
    368     if(U_FAILURE(*err))
    369     {
    370         UTRACE_EXIT_STATUS(*err);
    371         return NULL;
    372     }
    373 
    374     sharedData = ucnv_data_unFlattenClone(pArgs, data, err);
    375     if(U_FAILURE(*err))
    376     {
    377         udata_close(data);
    378         UTRACE_EXIT_STATUS(*err);
    379         return NULL;
    380     }
    381 
    382     /*
    383      * TODO Store pkg in a field in the shared data so that delta-only converters
    384      * can load base converters from the same package.
    385      * If the pkg name is longer than the field, then either do not load the converter
    386      * in the first place, or just set the pkg field to "".
    387      */
    388 
    389     UTRACE_EXIT_PTR_STATUS(sharedData, *err);
    390     return sharedData;
    391 }
    392 
    393 /*returns a converter type from a string
    394  */
    395 static const UConverterSharedData *
    396 getAlgorithmicTypeFromName(const char *realName)
    397 {
    398     uint32_t mid, start, limit;
    399     uint32_t lastMid;
    400     int result;
    401     char strippedName[UCNV_MAX_CONVERTER_NAME_LENGTH];
    402 
    403     /* Lower case and remove ignoreable characters. */
    404     ucnv_io_stripForCompare(strippedName, realName);
    405 
    406     /* do a binary search for the alias */
    407     start = 0;
    408     limit = sizeof(cnvNameType)/sizeof(cnvNameType[0]);
    409     mid = limit;
    410     lastMid = UINT32_MAX;
    411 
    412     for (;;) {
    413         mid = (uint32_t)((start + limit) / 2);
    414         if (lastMid == mid) {   /* Have we moved? */
    415             break;  /* We haven't moved, and it wasn't found. */
    416         }
    417         lastMid = mid;
    418         result = uprv_strcmp(strippedName, cnvNameType[mid].name);
    419 
    420         if (result < 0) {
    421             limit = mid;
    422         } else if (result > 0) {
    423             start = mid;
    424         } else {
    425             return converterData[cnvNameType[mid].type];
    426         }
    427     }
    428 
    429     return NULL;
    430 }
    431 
    432 /*
    433 * Based on the number of known converters, this determines how many times larger
    434 * the shared data hash table should be. When on small platforms, or just a couple
    435 * of converters are used, this number should be 2. When memory is plentiful, or
    436 * when ucnv_countAvailable is ever used with a lot of available converters,
    437 * this should be 4.
    438 * Larger numbers reduce the number of hash collisions, but use more memory.
    439 */
    440 #define UCNV_CACHE_LOAD_FACTOR 2
    441 
    442 /* Puts the shared data in the static hashtable SHARED_DATA_HASHTABLE */
    443 /*   Will always be called with the cnvCacheMutex alrady being held   */
    444 /*     by the calling function.                                       */
    445 /* Stores the shared data in the SHARED_DATA_HASHTABLE
    446  * @param data The shared data
    447  */
    448 static void
    449 ucnv_shareConverterData(UConverterSharedData * data)
    450 {
    451     UErrorCode err = U_ZERO_ERROR;
    452     /*Lazy evaluates the Hashtable itself */
    453     /*void *sanity = NULL;*/
    454 
    455     if (SHARED_DATA_HASHTABLE == NULL)
    456     {
    457         SHARED_DATA_HASHTABLE = uhash_openSize(uhash_hashChars, uhash_compareChars, NULL,
    458                             ucnv_io_countKnownConverters(&err)*UCNV_CACHE_LOAD_FACTOR,
    459                             &err);
    460         ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
    461 
    462         if (U_FAILURE(err))
    463             return;
    464     }
    465 
    466     /* ### check to see if the element is not already there! */
    467 
    468     /*
    469     sanity =   ucnv_getSharedConverterData (data->staticData->name);
    470     if(sanity != NULL)
    471     {
    472     UCNV_DEBUG_LOG("put:overwrite!",data->staticData->name,sanity);
    473     }
    474     UCNV_DEBUG_LOG("put:chk",data->staticData->name,sanity);
    475     */
    476 
    477     /* Mark it shared */
    478     data->sharedDataCached = TRUE;
    479 
    480     uhash_put(SHARED_DATA_HASHTABLE,
    481             (void*) data->staticData->name, /* Okay to cast away const as long as
    482             keyDeleter == NULL */
    483             data,
    484             &err);
    485     UCNV_DEBUG_LOG("put", data->staticData->name,data);
    486 
    487 }
    488 
    489 /*  Look up a converter name in the shared data cache.                    */
    490 /*    cnvCacheMutex must be held by the caller to protect the hash table. */
    491 /* gets the shared data from the SHARED_DATA_HASHTABLE (might return NULL if it isn't there)
    492  * @param name The name of the shared data
    493  * @return the shared data from the SHARED_DATA_HASHTABLE
    494  */
    495 static UConverterSharedData *
    496 ucnv_getSharedConverterData(const char *name)
    497 {
    498     /*special case when no Table has yet been created we return NULL */
    499     if (SHARED_DATA_HASHTABLE == NULL)
    500     {
    501         return NULL;
    502     }
    503     else
    504     {
    505         UConverterSharedData *rc;
    506 
    507         rc = (UConverterSharedData*)uhash_get(SHARED_DATA_HASHTABLE, name);
    508         UCNV_DEBUG_LOG("get",name,rc);
    509         return rc;
    510     }
    511 }
    512 
    513 /*frees the string of memory blocks associates with a sharedConverter
    514  *if and only if the referenceCounter == 0
    515  */
    516 /* Deletes (frees) the Shared data it's passed. first it checks the referenceCounter to
    517  * see if anyone is using it, if not it frees all the memory stemming from sharedConverterData and
    518  * returns TRUE,
    519  * otherwise returns FALSE
    520  * @param sharedConverterData The shared data
    521  * @return if not it frees all the memory stemming from sharedConverterData and
    522  * returns TRUE, otherwise returns FALSE
    523  */
    524 static UBool
    525 ucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
    526 {
    527     UTRACE_ENTRY_OC(UTRACE_UCNV_UNLOAD);
    528     UTRACE_DATA2(UTRACE_OPEN_CLOSE, "unload converter %s shared data %p", deadSharedData->staticData->name, deadSharedData);
    529 
    530     if (deadSharedData->referenceCounter > 0) {
    531         UTRACE_EXIT_VALUE((int32_t)FALSE);
    532         return FALSE;
    533     }
    534 
    535     if (deadSharedData->impl->unload != NULL) {
    536         deadSharedData->impl->unload(deadSharedData);
    537     }
    538 
    539     if(deadSharedData->dataMemory != NULL)
    540     {
    541         UDataMemory *data = (UDataMemory*)deadSharedData->dataMemory;
    542         udata_close(data);
    543     }
    544 
    545     if(deadSharedData->table != NULL)
    546     {
    547         uprv_free(deadSharedData->table);
    548     }
    549 
    550 #if 0
    551     /* if the static data is actually owned by the shared data */
    552     /* enable if we ever have this situation. */
    553     if(deadSharedData->staticDataOwned == TRUE) /* see ucnv_bld.h */
    554     {
    555         uprv_free((void*)deadSharedData->staticData);
    556     }
    557 #endif
    558 
    559 #if 0
    560     /* Zap it ! */
    561     uprv_memset(deadSharedData->0, sizeof(*deadSharedData));
    562 #endif
    563 
    564     uprv_free(deadSharedData);
    565 
    566     UTRACE_EXIT_VALUE((int32_t)TRUE);
    567     return TRUE;
    568 }
    569 
    570 /**
    571  * Load a non-algorithmic converter.
    572  * If pkg==NULL, then this function must be called inside umtx_lock(&cnvCacheMutex).
    573  */
    574 UConverterSharedData *
    575 ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
    576     UConverterSharedData *mySharedConverterData;
    577 
    578     if(err == NULL || U_FAILURE(*err)) {
    579         return NULL;
    580     }
    581 
    582     if(pArgs->pkg != NULL && *pArgs->pkg != 0) {
    583         /* application-provided converters are not currently cached */
    584         return createConverterFromFile(pArgs, err);
    585     }
    586 
    587     mySharedConverterData = ucnv_getSharedConverterData(pArgs->name);
    588     if (mySharedConverterData == NULL)
    589     {
    590         /*Not cached, we need to stream it in from file */
    591         mySharedConverterData = createConverterFromFile(pArgs, err);
    592         if (U_FAILURE (*err) || (mySharedConverterData == NULL))
    593         {
    594             return NULL;
    595         }
    596         else if (!pArgs->onlyTestIsLoadable)
    597         {
    598             /* share it with other library clients */
    599             ucnv_shareConverterData(mySharedConverterData);
    600         }
    601     }
    602     else
    603     {
    604         /* The data for this converter was already in the cache.            */
    605         /* Update the reference counter on the shared data: one more client */
    606         mySharedConverterData->referenceCounter++;
    607     }
    608 
    609     return mySharedConverterData;
    610 }
    611 
    612 /**
    613  * Unload a non-algorithmic converter.
    614  * It must be sharedData->referenceCounter != ~0
    615  * and this function must be called inside umtx_lock(&cnvCacheMutex).
    616  */
    617 U_CAPI void
    618 ucnv_unload(UConverterSharedData *sharedData) {
    619     if(sharedData != NULL) {
    620         if (sharedData->referenceCounter > 0) {
    621             sharedData->referenceCounter--;
    622         }
    623 
    624         if((sharedData->referenceCounter <= 0)&&(sharedData->sharedDataCached == FALSE)) {
    625             ucnv_deleteSharedConverterData(sharedData);
    626         }
    627     }
    628 }
    629 
    630 U_CFUNC void
    631 ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
    632 {
    633     /*
    634     Checking whether it's an algorithic converter is okay
    635     in multithreaded applications because the value never changes.
    636     Don't check referenceCounter for any other value.
    637     */
    638     if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
    639         umtx_lock(&cnvCacheMutex);
    640         ucnv_unload(sharedData);
    641         umtx_unlock(&cnvCacheMutex);
    642     }
    643 }
    644 
    645 U_CFUNC void
    646 ucnv_incrementRefCount(UConverterSharedData *sharedData)
    647 {
    648     /*
    649     Checking whether it's an algorithic converter is okay
    650     in multithreaded applications because the value never changes.
    651     Don't check referenceCounter for any other value.
    652     */
    653     if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
    654         umtx_lock(&cnvCacheMutex);
    655         sharedData->referenceCounter++;
    656         umtx_unlock(&cnvCacheMutex);
    657     }
    658 }
    659 
    660 /*
    661  * *pPieces must be initialized.
    662  * The name without options will be copied to pPieces->cnvName.
    663  * The locale and options will be copied to pPieces only if present in inName,
    664  * otherwise the existing values in pPieces remain.
    665  * *pArgs will be set to the pPieces values.
    666  */
    667 static void
    668 parseConverterOptions(const char *inName,
    669                       UConverterNamePieces *pPieces,
    670                       UConverterLoadArgs *pArgs,
    671                       UErrorCode *err)
    672 {
    673     char *cnvName = pPieces->cnvName;
    674     char c;
    675     int32_t len = 0;
    676 
    677     pArgs->name=inName;
    678     pArgs->locale=pPieces->locale;
    679     pArgs->options=pPieces->options;
    680 
    681     /* copy the converter name itself to cnvName */
    682     while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
    683         if (++len>=UCNV_MAX_CONVERTER_NAME_LENGTH) {
    684             *err = U_ILLEGAL_ARGUMENT_ERROR;    /* bad name */
    685             pPieces->cnvName[0]=0;
    686             return;
    687         }
    688         *cnvName++=c;
    689         inName++;
    690     }
    691     *cnvName=0;
    692     pArgs->name=pPieces->cnvName;
    693 
    694     /* parse options. No more name copying should occur. */
    695     while((c=*inName)!=0) {
    696         if(c==UCNV_OPTION_SEP_CHAR) {
    697             ++inName;
    698         }
    699 
    700         /* inName is behind an option separator */
    701         if(uprv_strncmp(inName, "locale=", 7)==0) {
    702             /* do not modify locale itself in case we have multiple locale options */
    703             char *dest=pPieces->locale;
    704 
    705             /* copy the locale option value */
    706             inName+=7;
    707             len=0;
    708             while((c=*inName)!=0 && c!=UCNV_OPTION_SEP_CHAR) {
    709                 ++inName;
    710 
    711                 if(++len>=ULOC_FULLNAME_CAPACITY) {
    712                     *err=U_ILLEGAL_ARGUMENT_ERROR;    /* bad name */
    713                     pPieces->locale[0]=0;
    714                     return;
    715                 }
    716 
    717                 *dest++=c;
    718             }
    719             *dest=0;
    720         } else if(uprv_strncmp(inName, "version=", 8)==0) {
    721             /* copy the version option value into bits 3..0 of pPieces->options */
    722             inName+=8;
    723             c=*inName;
    724             if(c==0) {
    725                 pArgs->options=(pPieces->options&=~UCNV_OPTION_VERSION);
    726                 return;
    727             } else if((uint8_t)(c-'0')<10) {
    728                 pArgs->options=pPieces->options=(pPieces->options&~UCNV_OPTION_VERSION)|(uint32_t)(c-'0');
    729                 ++inName;
    730             }
    731         } else if(uprv_strncmp(inName, "swaplfnl", 8)==0) {
    732             inName+=8;
    733             pArgs->options=(pPieces->options|=UCNV_OPTION_SWAP_LFNL);
    734         /* add processing for new options here with another } else if(uprv_strncmp(inName, "option-name=", XX)==0) { */
    735         } else {
    736             /* ignore any other options until we define some */
    737             while(((c = *inName++) != 0) && (c != UCNV_OPTION_SEP_CHAR)) {
    738             }
    739             if(c==0) {
    740                 return;
    741             }
    742         }
    743     }
    744 }
    745 
    746 /*Logic determines if the converter is Algorithmic AND/OR cached
    747  *depending on that:
    748  * -we either go to get data from disk and cache it (Data=TRUE, Cached=False)
    749  * -Get it from a Hashtable (Data=X, Cached=TRUE)
    750  * -Call dataConverter initializer (Data=TRUE, Cached=TRUE)
    751  * -Call AlgorithmicConverter initializer (Data=FALSE, Cached=TRUE)
    752  */
    753 U_CFUNC UConverterSharedData *
    754 ucnv_loadSharedData(const char *converterName,
    755                     UConverterNamePieces *pPieces,
    756                     UConverterLoadArgs *pArgs,
    757                     UErrorCode * err) {
    758     UConverterNamePieces stackPieces;
    759     UConverterLoadArgs stackArgs;
    760     UConverterSharedData *mySharedConverterData = NULL;
    761     UErrorCode internalErrorCode = U_ZERO_ERROR;
    762     UBool mayContainOption = TRUE;
    763     UBool checkForAlgorithmic = TRUE;
    764 
    765     if (U_FAILURE (*err)) {
    766         return NULL;
    767     }
    768 
    769     if(pPieces == NULL) {
    770         if(pArgs != NULL) {
    771             /*
    772              * Bad: We may set pArgs pointers to stackPieces fields
    773              * which will be invalid after this function returns.
    774              */
    775             *err = U_INTERNAL_PROGRAM_ERROR;
    776             return NULL;
    777         }
    778         pPieces = &stackPieces;
    779     }
    780     if(pArgs == NULL) {
    781         uprv_memset(&stackArgs, 0, sizeof(stackArgs));
    782         stackArgs.size = (int32_t)sizeof(stackArgs);
    783         pArgs = &stackArgs;
    784     }
    785 
    786     pPieces->cnvName[0] = 0;
    787     pPieces->locale[0] = 0;
    788     pPieces->options = 0;
    789 
    790     pArgs->name = converterName;
    791     pArgs->locale = pPieces->locale;
    792     pArgs->options = pPieces->options;
    793 
    794     /* In case "name" is NULL we want to open the default converter. */
    795     if (converterName == NULL) {
    796 #if U_CHARSET_IS_UTF8
    797         pArgs->name = "UTF-8";
    798         return (UConverterSharedData *)converterData[UCNV_UTF8];
    799 #else
    800         /* Call ucnv_getDefaultName first to query the name from the OS. */
    801         pArgs->name = ucnv_getDefaultName();
    802         if (pArgs->name == NULL) {
    803             *err = U_MISSING_RESOURCE_ERROR;
    804             return NULL;
    805         }
    806         mySharedConverterData = (UConverterSharedData *)gDefaultAlgorithmicSharedData;
    807         checkForAlgorithmic = FALSE;
    808         mayContainOption = gDefaultConverterContainsOption;
    809         /* the default converter name is already canonical */
    810 #endif
    811     }
    812     else if(UCNV_FAST_IS_UTF8(converterName)) {
    813         /* fastpath for UTF-8 */
    814         pArgs->name = "UTF-8";
    815         return (UConverterSharedData *)converterData[UCNV_UTF8];
    816     }
    817     else {
    818         /* separate the converter name from the options */
    819         parseConverterOptions(converterName, pPieces, pArgs, err);
    820         if (U_FAILURE(*err)) {
    821             /* Very bad name used. */
    822             return NULL;
    823         }
    824 
    825         /* get the canonical converter name */
    826         pArgs->name = ucnv_io_getConverterName(pArgs->name, &mayContainOption, &internalErrorCode);
    827         if (U_FAILURE(internalErrorCode) || pArgs->name == NULL) {
    828             /*
    829             * set the input name in case the converter was added
    830             * without updating the alias table, or when there is no alias table
    831             */
    832             pArgs->name = pPieces->cnvName;
    833         } else if (internalErrorCode == U_AMBIGUOUS_ALIAS_WARNING) {
    834             *err = U_AMBIGUOUS_ALIAS_WARNING;
    835         }
    836     }
    837 
    838     /* separate the converter name from the options */
    839     if(mayContainOption && pArgs->name != pPieces->cnvName) {
    840         parseConverterOptions(pArgs->name, pPieces, pArgs, err);
    841     }
    842 
    843     /* get the shared data for an algorithmic converter, if it is one */
    844     if (checkForAlgorithmic) {
    845         mySharedConverterData = (UConverterSharedData *)getAlgorithmicTypeFromName(pArgs->name);
    846     }
    847     if (mySharedConverterData == NULL)
    848     {
    849         /* it is a data-based converter, get its shared data.               */
    850         /* Hold the cnvCacheMutex through the whole process of checking the */
    851         /*   converter data cache, and adding new entries to the cache      */
    852         /*   to prevent other threads from modifying the cache during the   */
    853         /*   process.                                                       */
    854         pArgs->nestedLoads=1;
    855         pArgs->pkg=NULL;
    856 
    857         umtx_lock(&cnvCacheMutex);
    858         mySharedConverterData = ucnv_load(pArgs, err);
    859         umtx_unlock(&cnvCacheMutex);
    860         if (U_FAILURE (*err) || (mySharedConverterData == NULL))
    861         {
    862             return NULL;
    863         }
    864     }
    865 
    866     return mySharedConverterData;
    867 }
    868 
    869 U_CAPI UConverter *
    870 ucnv_createConverter(UConverter *myUConverter, const char *converterName, UErrorCode * err)
    871 {
    872     UConverterNamePieces stackPieces;
    873     UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
    874     UConverterSharedData *mySharedConverterData;
    875 
    876     UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
    877 
    878     if(U_SUCCESS(*err)) {
    879         UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open converter %s", converterName);
    880 
    881         mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
    882 
    883         myUConverter = ucnv_createConverterFromSharedData(
    884             myUConverter, mySharedConverterData,
    885             &stackArgs,
    886             err);
    887 
    888         if(U_SUCCESS(*err)) {
    889             UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
    890             return myUConverter;
    891         }
    892     }
    893 
    894     /* exit with error */
    895     UTRACE_EXIT_STATUS(*err);
    896     return NULL;
    897 }
    898 
    899 U_CFUNC UBool
    900 ucnv_canCreateConverter(const char *converterName, UErrorCode *err) {
    901     UConverter myUConverter;
    902     UConverterNamePieces stackPieces;
    903     UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
    904     UConverterSharedData *mySharedConverterData;
    905 
    906     UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN);
    907 
    908     if(U_SUCCESS(*err)) {
    909         UTRACE_DATA1(UTRACE_OPEN_CLOSE, "test if can open converter %s", converterName);
    910 
    911         stackArgs.onlyTestIsLoadable=TRUE;
    912         mySharedConverterData = ucnv_loadSharedData(converterName, &stackPieces, &stackArgs, err);
    913         ucnv_createConverterFromSharedData(
    914             &myUConverter, mySharedConverterData,
    915             &stackArgs,
    916             err);
    917         ucnv_unloadSharedDataIfReady(mySharedConverterData);
    918     }
    919 
    920     UTRACE_EXIT_STATUS(*err);
    921     return U_SUCCESS(*err);
    922 }
    923 
    924 UConverter *
    925 ucnv_createAlgorithmicConverter(UConverter *myUConverter,
    926                                 UConverterType type,
    927                                 const char *locale, uint32_t options,
    928                                 UErrorCode *err) {
    929     UConverter *cnv;
    930     const UConverterSharedData *sharedData;
    931     UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
    932 
    933     UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_ALGORITHMIC);
    934     UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open algorithmic converter type %d", (int32_t)type);
    935 
    936     if(type<0 || UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES<=type) {
    937         *err = U_ILLEGAL_ARGUMENT_ERROR;
    938         UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
    939         return NULL;
    940     }
    941 
    942     sharedData = converterData[type];
    943     /*
    944     Checking whether it's an algorithic converter is okay
    945     in multithreaded applications because the value never changes.
    946     Don't check referenceCounter for any other value.
    947     */
    948     if(sharedData == NULL || sharedData->referenceCounter != (uint32_t)~0) {
    949         /* not a valid type, or not an algorithmic converter */
    950         *err = U_ILLEGAL_ARGUMENT_ERROR;
    951         UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
    952         return NULL;
    953     }
    954 
    955     stackArgs.name = "";
    956     stackArgs.options = options;
    957     stackArgs.locale=locale;
    958     cnv = ucnv_createConverterFromSharedData(
    959             myUConverter, (UConverterSharedData *)sharedData,
    960             &stackArgs, err);
    961 
    962     UTRACE_EXIT_PTR_STATUS(cnv, *err);
    963     return cnv;
    964 }
    965 
    966 U_CFUNC UConverter*
    967 ucnv_createConverterFromPackage(const char *packageName, const char *converterName, UErrorCode * err)
    968 {
    969     UConverter *myUConverter;
    970     UConverterSharedData *mySharedConverterData;
    971     UConverterNamePieces stackPieces;
    972     UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
    973 
    974     UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_PACKAGE);
    975 
    976     if(U_FAILURE(*err)) {
    977         UTRACE_EXIT_STATUS(*err);
    978         return NULL;
    979     }
    980 
    981     UTRACE_DATA2(UTRACE_OPEN_CLOSE, "open converter %s from package %s", converterName, packageName);
    982 
    983     /* first, get the options out of the converterName string */
    984     stackPieces.cnvName[0] = 0;
    985     stackPieces.locale[0] = 0;
    986     stackPieces.options = 0;
    987     parseConverterOptions(converterName, &stackPieces, &stackArgs, err);
    988     if (U_FAILURE(*err)) {
    989         /* Very bad name used. */
    990         UTRACE_EXIT_STATUS(*err);
    991         return NULL;
    992     }
    993     stackArgs.nestedLoads=1;
    994     stackArgs.pkg=packageName;
    995 
    996     /* open the data, unflatten the shared structure */
    997     mySharedConverterData = createConverterFromFile(&stackArgs, err);
    998 
    999     if (U_FAILURE(*err)) {
   1000         UTRACE_EXIT_STATUS(*err);
   1001         return NULL;
   1002     }
   1003 
   1004     /* create the actual converter */
   1005     myUConverter = ucnv_createConverterFromSharedData(NULL, mySharedConverterData, &stackArgs, err);
   1006 
   1007     if (U_FAILURE(*err)) {
   1008         ucnv_close(myUConverter);
   1009         UTRACE_EXIT_STATUS(*err);
   1010         return NULL;
   1011     }
   1012 
   1013     UTRACE_EXIT_PTR_STATUS(myUConverter, *err);
   1014     return myUConverter;
   1015 }
   1016 
   1017 
   1018 U_CFUNC UConverter*
   1019 ucnv_createConverterFromSharedData(UConverter *myUConverter,
   1020                                    UConverterSharedData *mySharedConverterData,
   1021                                    UConverterLoadArgs *pArgs,
   1022                                    UErrorCode *err)
   1023 {
   1024     UBool isCopyLocal;
   1025 
   1026     if(U_FAILURE(*err)) {
   1027         ucnv_unloadSharedDataIfReady(mySharedConverterData);
   1028         return myUConverter;
   1029     }
   1030     if(myUConverter == NULL)
   1031     {
   1032         myUConverter = (UConverter *) uprv_malloc (sizeof (UConverter));
   1033         if(myUConverter == NULL)
   1034         {
   1035             *err = U_MEMORY_ALLOCATION_ERROR;
   1036             ucnv_unloadSharedDataIfReady(mySharedConverterData);
   1037             return NULL;
   1038         }
   1039         isCopyLocal = FALSE;
   1040     } else {
   1041         isCopyLocal = TRUE;
   1042     }
   1043 
   1044     /* initialize the converter */
   1045     uprv_memset(myUConverter, 0, sizeof(UConverter));
   1046     myUConverter->isCopyLocal = isCopyLocal;
   1047     /*myUConverter->isExtraLocal = FALSE;*/ /* Set by the memset call */
   1048     myUConverter->sharedData = mySharedConverterData;
   1049     myUConverter->options = pArgs->options;
   1050     if(!pArgs->onlyTestIsLoadable) {
   1051         myUConverter->preFromUFirstCP = U_SENTINEL;
   1052         myUConverter->fromCharErrorBehaviour = UCNV_TO_U_DEFAULT_CALLBACK;
   1053         myUConverter->fromUCharErrorBehaviour = UCNV_FROM_U_DEFAULT_CALLBACK;
   1054         myUConverter->toUnicodeStatus = mySharedConverterData->toUnicodeStatus;
   1055         myUConverter->maxBytesPerUChar = mySharedConverterData->staticData->maxBytesPerChar;
   1056         myUConverter->subChar1 = mySharedConverterData->staticData->subChar1;
   1057         myUConverter->subCharLen = mySharedConverterData->staticData->subCharLen;
   1058         myUConverter->subChars = (uint8_t *)myUConverter->subUChars;
   1059         uprv_memcpy(myUConverter->subChars, mySharedConverterData->staticData->subChar, myUConverter->subCharLen);
   1060         myUConverter->toUCallbackReason = UCNV_ILLEGAL; /* default reason to invoke (*fromCharErrorBehaviour) */
   1061     }
   1062 
   1063     if(mySharedConverterData->impl->open != NULL) {
   1064         mySharedConverterData->impl->open(myUConverter, pArgs, err);
   1065         if(U_FAILURE(*err) && !pArgs->onlyTestIsLoadable) {
   1066             /* don't ucnv_close() if onlyTestIsLoadable because not fully initialized */
   1067             ucnv_close(myUConverter);
   1068             return NULL;
   1069         }
   1070     }
   1071 
   1072     return myUConverter;
   1073 }
   1074 
   1075 /*Frees all shared immutable objects that aren't referred to (reference count = 0)
   1076  */
   1077 U_CAPI int32_t U_EXPORT2
   1078 ucnv_flushCache ()
   1079 {
   1080     UConverterSharedData *mySharedData = NULL;
   1081     int32_t pos;
   1082     int32_t tableDeletedNum = 0;
   1083     const UHashElement *e;
   1084     /*UErrorCode status = U_ILLEGAL_ARGUMENT_ERROR;*/
   1085     int32_t i, remaining;
   1086 
   1087     UTRACE_ENTRY_OC(UTRACE_UCNV_FLUSH_CACHE);
   1088 
   1089     /* Close the default converter without creating a new one so that everything will be flushed. */
   1090     u_flushDefaultConverter();
   1091 
   1092     /*if shared data hasn't even been lazy evaluated yet
   1093     * return 0
   1094     */
   1095     if (SHARED_DATA_HASHTABLE == NULL) {
   1096         UTRACE_EXIT_VALUE((int32_t)0);
   1097         return 0;
   1098     }
   1099 
   1100     /*creates an enumeration to iterate through every element in the
   1101     * table
   1102     *
   1103     * Synchronization:  holding cnvCacheMutex will prevent any other thread from
   1104     *                   accessing or modifying the hash table during the iteration.
   1105     *                   The reference count of an entry may be decremented by
   1106     *                   ucnv_close while the iteration is in process, but this is
   1107     *                   benign.  It can't be incremented (in ucnv_createConverter())
   1108     *                   because the sequence of looking up in the cache + incrementing
   1109     *                   is protected by cnvCacheMutex.
   1110     */
   1111     umtx_lock(&cnvCacheMutex);
   1112     /*
   1113      * double loop: A delta/extension-only converter has a pointer to its base table's
   1114      * shared data; the first iteration of the outer loop may see the delta converter
   1115      * before the base converter, and unloading the delta converter may get the base
   1116      * converter's reference counter down to 0.
   1117      */
   1118     i = 0;
   1119     do {
   1120         remaining = 0;
   1121         pos = UHASH_FIRST;
   1122         while ((e = uhash_nextElement (SHARED_DATA_HASHTABLE, &pos)) != NULL)
   1123         {
   1124             mySharedData = (UConverterSharedData *) e->value.pointer;
   1125             /*deletes only if reference counter == 0 */
   1126             if (mySharedData->referenceCounter == 0)
   1127             {
   1128                 tableDeletedNum++;
   1129 
   1130                 UCNV_DEBUG_LOG("del",mySharedData->staticData->name,mySharedData);
   1131 
   1132                 uhash_removeElement(SHARED_DATA_HASHTABLE, e);
   1133                 mySharedData->sharedDataCached = FALSE;
   1134                 ucnv_deleteSharedConverterData (mySharedData);
   1135             } else {
   1136                 ++remaining;
   1137             }
   1138         }
   1139     } while(++i == 1 && remaining > 0);
   1140     umtx_unlock(&cnvCacheMutex);
   1141 
   1142     UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining);
   1143 
   1144     UTRACE_EXIT_VALUE(tableDeletedNum);
   1145     return tableDeletedNum;
   1146 }
   1147 
   1148 /* available converters list --------------------------------------------------- */
   1149 
   1150 static void U_CALLCONV initAvailableConvertersList(UErrorCode &errCode) {
   1151     U_ASSERT(gAvailableConverterCount == 0);
   1152     U_ASSERT(gAvailableConverters == NULL);
   1153 
   1154     ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
   1155     UEnumeration *allConvEnum = ucnv_openAllNames(&errCode);
   1156     int32_t allConverterCount = uenum_count(allConvEnum, &errCode);
   1157     if (U_FAILURE(errCode)) {
   1158         return;
   1159     }
   1160 
   1161     /* We can't have more than "*converterTable" converters to open */
   1162     gAvailableConverters = (const char **) uprv_malloc(allConverterCount * sizeof(char*));
   1163     if (!gAvailableConverters) {
   1164         errCode = U_MEMORY_ALLOCATION_ERROR;
   1165         return;
   1166     }
   1167 
   1168     /* Open the default converter to make sure that it has first dibs in the hash table. */
   1169     UErrorCode localStatus = U_ZERO_ERROR;
   1170     UConverter tempConverter;
   1171     ucnv_close(ucnv_createConverter(&tempConverter, NULL, &localStatus));
   1172 
   1173     gAvailableConverterCount = 0;
   1174 
   1175     for (int32_t idx = 0; idx < allConverterCount; idx++) {
   1176         localStatus = U_ZERO_ERROR;
   1177         const char *converterName = uenum_next(allConvEnum, NULL, &localStatus);
   1178         if (ucnv_canCreateConverter(converterName, &localStatus)) {
   1179             gAvailableConverters[gAvailableConverterCount++] = converterName;
   1180         }
   1181     }
   1182 
   1183     uenum_close(allConvEnum);
   1184 }
   1185 
   1186 
   1187 static UBool haveAvailableConverterList(UErrorCode *pErrorCode) {
   1188     umtx_initOnce(gAvailableConvertersInitOnce, &initAvailableConvertersList, *pErrorCode);
   1189     return U_SUCCESS(*pErrorCode);
   1190 }
   1191 
   1192 U_CFUNC uint16_t
   1193 ucnv_bld_countAvailableConverters(UErrorCode *pErrorCode) {
   1194     if (haveAvailableConverterList(pErrorCode)) {
   1195         return gAvailableConverterCount;
   1196     }
   1197     return 0;
   1198 }
   1199 
   1200 U_CFUNC const char *
   1201 ucnv_bld_getAvailableConverter(uint16_t n, UErrorCode *pErrorCode) {
   1202     if (haveAvailableConverterList(pErrorCode)) {
   1203         if (n < gAvailableConverterCount) {
   1204             return gAvailableConverters[n];
   1205         }
   1206         *pErrorCode = U_INDEX_OUTOFBOUNDS_ERROR;
   1207     }
   1208     return NULL;
   1209 }
   1210 
   1211 /* default converter name --------------------------------------------------- */
   1212 
   1213 #if !U_CHARSET_IS_UTF8
   1214 /*
   1215 Copy the canonical converter name.
   1216 ucnv_getDefaultName must be thread safe, which can call this function.
   1217 
   1218 ucnv_setDefaultName calls this function and it doesn't have to be
   1219 thread safe because there is no reliable/safe way to reset the
   1220 converter in use in all threads. If you did reset the converter, you
   1221 would not be sure that retrieving a default converter for one string
   1222 would be the same type of default converter for a successive string.
   1223 Since the name is a returned via ucnv_getDefaultName without copying,
   1224 you shouldn't be modifying or deleting the string from a separate thread.
   1225 */
   1226 static inline void
   1227 internalSetName(const char *name, UErrorCode *status) {
   1228     UConverterNamePieces stackPieces;
   1229     UConverterLoadArgs stackArgs=UCNV_LOAD_ARGS_INITIALIZER;
   1230     int32_t length=(int32_t)(uprv_strlen(name));
   1231     UBool containsOption = (UBool)(uprv_strchr(name, UCNV_OPTION_SEP_CHAR) != NULL);
   1232     const UConverterSharedData *algorithmicSharedData;
   1233 
   1234     stackArgs.name = name;
   1235     if(containsOption) {
   1236         stackPieces.cnvName[0] = 0;
   1237         stackPieces.locale[0] = 0;
   1238         stackPieces.options = 0;
   1239         parseConverterOptions(name, &stackPieces, &stackArgs, status);
   1240         if(U_FAILURE(*status)) {
   1241             return;
   1242         }
   1243     }
   1244     algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
   1245 
   1246     umtx_lock(&cnvCacheMutex);
   1247 
   1248     gDefaultAlgorithmicSharedData = algorithmicSharedData;
   1249     gDefaultConverterContainsOption = containsOption;
   1250     uprv_memcpy(gDefaultConverterNameBuffer, name, length);
   1251     gDefaultConverterNameBuffer[length]=0;
   1252 
   1253     /* gDefaultConverterName MUST be the last global var set by this function.  */
   1254     /*    It is the variable checked in ucnv_getDefaultName() to see if initialization is required. */
   1255     //    But there is nothing here preventing that from being reordered, either by the compiler
   1256     //             or hardware. I'm adding the mutex to ucnv_getDefaultName for now. UMTX_CHECK is not enough.
   1257     //             -- Andy
   1258     gDefaultConverterName = gDefaultConverterNameBuffer;
   1259 
   1260     ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
   1261 
   1262     umtx_unlock(&cnvCacheMutex);
   1263 }
   1264 #endif
   1265 
   1266 /*
   1267  * In order to be really thread-safe, the get function would have to take
   1268  * a buffer parameter and copy the current string inside a mutex block.
   1269  * This implementation only tries to be really thread-safe while
   1270  * setting the name.
   1271  * It assumes that setting a pointer is atomic.
   1272  */
   1273 
   1274 U_CAPI const char*  U_EXPORT2
   1275 ucnv_getDefaultName() {
   1276 #if U_CHARSET_IS_UTF8
   1277     return "UTF-8";
   1278 #else
   1279     /* local variable to be thread-safe */
   1280     const char *name;
   1281 
   1282     /*
   1283     Concurrent calls to ucnv_getDefaultName must be thread safe,
   1284     but ucnv_setDefaultName is not thread safe.
   1285     */
   1286     {
   1287         icu::Mutex lock(&cnvCacheMutex);
   1288         name = gDefaultConverterName;
   1289     }
   1290     if(name==NULL) {
   1291         UErrorCode errorCode = U_ZERO_ERROR;
   1292         UConverter *cnv = NULL;
   1293 
   1294         name = uprv_getDefaultCodepage();
   1295 
   1296         /* if the name is there, test it out and get the canonical name with options */
   1297         if(name != NULL) {
   1298             cnv = ucnv_open(name, &errorCode);
   1299             if(U_SUCCESS(errorCode) && cnv != NULL) {
   1300                 name = ucnv_getName(cnv, &errorCode);
   1301             }
   1302         }
   1303 
   1304         if(name == NULL || name[0] == 0
   1305             || U_FAILURE(errorCode) || cnv == NULL
   1306             || uprv_strlen(name)>=sizeof(gDefaultConverterNameBuffer))
   1307         {
   1308             /* Panic time, let's use a fallback. */
   1309 #if (U_CHARSET_FAMILY == U_ASCII_FAMILY)
   1310             name = "US-ASCII";
   1311             /* there is no 'algorithmic' converter for EBCDIC */
   1312 #elif U_PLATFORM == U_PF_OS390
   1313             name = "ibm-1047_P100-1995" UCNV_SWAP_LFNL_OPTION_STRING;
   1314 #else
   1315             name = "ibm-37_P100-1995";
   1316 #endif
   1317         }
   1318 
   1319         internalSetName(name, &errorCode);
   1320 
   1321         /* The close may make the current name go away. */
   1322         ucnv_close(cnv);
   1323     }
   1324 
   1325     return name;
   1326 #endif
   1327 }
   1328 
   1329 #if U_CHARSET_IS_UTF8
   1330 U_CAPI void U_EXPORT2 ucnv_setDefaultName(const char *) {}
   1331 #else
   1332 /*
   1333 This function is not thread safe, and it can't be thread safe.
   1334 See internalSetName or the API reference for details.
   1335 */
   1336 U_CAPI void U_EXPORT2
   1337 ucnv_setDefaultName(const char *converterName) {
   1338     if(converterName==NULL) {
   1339         /* reset to the default codepage */
   1340         gDefaultConverterName=NULL;
   1341     } else {
   1342         UErrorCode errorCode = U_ZERO_ERROR;
   1343         UConverter *cnv = NULL;
   1344         const char *name = NULL;
   1345 
   1346         /* if the name is there, test it out and get the canonical name with options */
   1347         cnv = ucnv_open(converterName, &errorCode);
   1348         if(U_SUCCESS(errorCode) && cnv != NULL) {
   1349             name = ucnv_getName(cnv, &errorCode);
   1350         }
   1351 
   1352         if(U_SUCCESS(errorCode) && name!=NULL) {
   1353             internalSetName(name, &errorCode);
   1354         }
   1355         /* else this converter is bad to use. Don't change it to a bad value. */
   1356 
   1357         /* The close may make the current name go away. */
   1358         ucnv_close(cnv);
   1359 
   1360         /* reset the converter cache */
   1361         u_flushDefaultConverter();
   1362     }
   1363 }
   1364 #endif
   1365 
   1366 /* data swapping ------------------------------------------------------------ */
   1367 
   1368 /* most of this might belong more properly into ucnvmbcs.c, but that is so large */
   1369 
   1370 #if !UCONFIG_NO_LEGACY_CONVERSION
   1371 
   1372 U_CAPI int32_t U_EXPORT2
   1373 ucnv_swap(const UDataSwapper *ds,
   1374           const void *inData, int32_t length, void *outData,
   1375           UErrorCode *pErrorCode) {
   1376     const UDataInfo *pInfo;
   1377     int32_t headerSize;
   1378 
   1379     const uint8_t *inBytes;
   1380     uint8_t *outBytes;
   1381 
   1382     uint32_t offset, count, staticDataSize;
   1383     int32_t size;
   1384 
   1385     const UConverterStaticData *inStaticData;
   1386     UConverterStaticData *outStaticData;
   1387 
   1388     const _MBCSHeader *inMBCSHeader;
   1389     _MBCSHeader *outMBCSHeader;
   1390     _MBCSHeader mbcsHeader;
   1391     uint32_t mbcsHeaderLength;
   1392     UBool noFromU=FALSE;
   1393 
   1394     uint8_t outputType;
   1395 
   1396     int32_t maxFastUChar, mbcsIndexLength;
   1397 
   1398     const int32_t *inExtIndexes;
   1399     int32_t extOffset;
   1400 
   1401     /* udata_swapDataHeader checks the arguments */
   1402     headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
   1403     if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
   1404         return 0;
   1405     }
   1406 
   1407     /* check data format and format version */
   1408     pInfo=(const UDataInfo *)((const char *)inData+4);
   1409     if(!(
   1410         pInfo->dataFormat[0]==0x63 &&   /* dataFormat="cnvt" */
   1411         pInfo->dataFormat[1]==0x6e &&
   1412         pInfo->dataFormat[2]==0x76 &&
   1413         pInfo->dataFormat[3]==0x74 &&
   1414         pInfo->formatVersion[0]==6 &&
   1415         pInfo->formatVersion[1]>=2
   1416     )) {
   1417         udata_printError(ds, "ucnv_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not recognized as an ICU .cnv conversion table\n",
   1418                          pInfo->dataFormat[0], pInfo->dataFormat[1],
   1419                          pInfo->dataFormat[2], pInfo->dataFormat[3],
   1420                          pInfo->formatVersion[0], pInfo->formatVersion[1]);
   1421         *pErrorCode=U_UNSUPPORTED_ERROR;
   1422         return 0;
   1423     }
   1424 
   1425     inBytes=(const uint8_t *)inData+headerSize;
   1426     outBytes=(uint8_t *)outData+headerSize;
   1427 
   1428     /* read the initial UConverterStaticData structure after the UDataInfo header */
   1429     inStaticData=(const UConverterStaticData *)inBytes;
   1430     outStaticData=(UConverterStaticData *)outBytes;
   1431 
   1432     if(length<0) {
   1433         staticDataSize=ds->readUInt32(inStaticData->structSize);
   1434     } else {
   1435         length-=headerSize;
   1436         if( length<(int32_t)sizeof(UConverterStaticData) ||
   1437             (uint32_t)length<(staticDataSize=ds->readUInt32(inStaticData->structSize))
   1438         ) {
   1439             udata_printError(ds, "ucnv_swap(): too few bytes (%d after header) for an ICU .cnv conversion table\n",
   1440                              length);
   1441             *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
   1442             return 0;
   1443         }
   1444     }
   1445 
   1446     if(length>=0) {
   1447         /* swap the static data */
   1448         if(inStaticData!=outStaticData) {
   1449             uprv_memcpy(outStaticData, inStaticData, staticDataSize);
   1450         }
   1451 
   1452         ds->swapArray32(ds, &inStaticData->structSize, 4,
   1453                            &outStaticData->structSize, pErrorCode);
   1454         ds->swapArray32(ds, &inStaticData->codepage, 4,
   1455                            &outStaticData->codepage, pErrorCode);
   1456 
   1457         ds->swapInvChars(ds, inStaticData->name, (int32_t)uprv_strlen(inStaticData->name),
   1458                             outStaticData->name, pErrorCode);
   1459         if(U_FAILURE(*pErrorCode)) {
   1460             udata_printError(ds, "ucnv_swap(): error swapping converter name\n");
   1461             return 0;
   1462         }
   1463     }
   1464 
   1465     inBytes+=staticDataSize;
   1466     outBytes+=staticDataSize;
   1467     if(length>=0) {
   1468         length-=(int32_t)staticDataSize;
   1469     }
   1470 
   1471     /* check for supported conversionType values */
   1472     if(inStaticData->conversionType==UCNV_MBCS) {
   1473         /* swap MBCS data */
   1474         inMBCSHeader=(const _MBCSHeader *)inBytes;
   1475         outMBCSHeader=(_MBCSHeader *)outBytes;
   1476 
   1477         if(0<=length && length<(int32_t)sizeof(_MBCSHeader)) {
   1478             udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table\n",
   1479                                 length);
   1480             *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
   1481             return 0;
   1482         }
   1483         if(inMBCSHeader->version[0]==4 && inMBCSHeader->version[1]>=1) {
   1484             mbcsHeaderLength=MBCS_HEADER_V4_LENGTH;
   1485         } else if(inMBCSHeader->version[0]==5 && inMBCSHeader->version[1]>=3 &&
   1486                   ((mbcsHeader.options=ds->readUInt32(inMBCSHeader->options))&
   1487                    MBCS_OPT_UNKNOWN_INCOMPATIBLE_MASK)==0
   1488         ) {
   1489             mbcsHeaderLength=mbcsHeader.options&MBCS_OPT_LENGTH_MASK;
   1490             noFromU=(UBool)((mbcsHeader.options&MBCS_OPT_NO_FROM_U)!=0);
   1491         } else {
   1492             udata_printError(ds, "ucnv_swap(): unsupported _MBCSHeader.version %d.%d\n",
   1493                              inMBCSHeader->version[0], inMBCSHeader->version[1]);
   1494             *pErrorCode=U_UNSUPPORTED_ERROR;
   1495             return 0;
   1496         }
   1497 
   1498         uprv_memcpy(mbcsHeader.version, inMBCSHeader->version, 4);
   1499         mbcsHeader.countStates=         ds->readUInt32(inMBCSHeader->countStates);
   1500         mbcsHeader.countToUFallbacks=   ds->readUInt32(inMBCSHeader->countToUFallbacks);
   1501         mbcsHeader.offsetToUCodeUnits=  ds->readUInt32(inMBCSHeader->offsetToUCodeUnits);
   1502         mbcsHeader.offsetFromUTable=    ds->readUInt32(inMBCSHeader->offsetFromUTable);
   1503         mbcsHeader.offsetFromUBytes=    ds->readUInt32(inMBCSHeader->offsetFromUBytes);
   1504         mbcsHeader.flags=               ds->readUInt32(inMBCSHeader->flags);
   1505         mbcsHeader.fromUBytesLength=    ds->readUInt32(inMBCSHeader->fromUBytesLength);
   1506         /* mbcsHeader.options have been read above */
   1507 
   1508         extOffset=(int32_t)(mbcsHeader.flags>>8);
   1509         outputType=(uint8_t)mbcsHeader.flags;
   1510         if(noFromU && outputType==MBCS_OUTPUT_1) {
   1511             udata_printError(ds, "ucnv_swap(): unsupported combination of makeconv --small with SBCS\n");
   1512             *pErrorCode=U_UNSUPPORTED_ERROR;
   1513             return 0;
   1514         }
   1515 
   1516         /* make sure that the output type is known */
   1517         switch(outputType) {
   1518         case MBCS_OUTPUT_1:
   1519         case MBCS_OUTPUT_2:
   1520         case MBCS_OUTPUT_3:
   1521         case MBCS_OUTPUT_4:
   1522         case MBCS_OUTPUT_3_EUC:
   1523         case MBCS_OUTPUT_4_EUC:
   1524         case MBCS_OUTPUT_2_SISO:
   1525         case MBCS_OUTPUT_EXT_ONLY:
   1526             /* OK */
   1527             break;
   1528         default:
   1529             udata_printError(ds, "ucnv_swap(): unsupported MBCS output type 0x%x\n",
   1530                              outputType);
   1531             *pErrorCode=U_UNSUPPORTED_ERROR;
   1532             return 0;
   1533         }
   1534 
   1535         /* calculate the length of the MBCS data */
   1536 
   1537         /*
   1538          * utf8Friendly MBCS files (mbcsHeader.version 4.3)
   1539          * contain an additional mbcsIndex table:
   1540          *   uint16_t[(maxFastUChar+1)>>6];
   1541          * where maxFastUChar=((mbcsHeader.version[2]<<8)|0xff).
   1542          */
   1543         maxFastUChar=0;
   1544         mbcsIndexLength=0;
   1545         if( outputType!=MBCS_OUTPUT_EXT_ONLY && outputType!=MBCS_OUTPUT_1 &&
   1546             mbcsHeader.version[1]>=3 && (maxFastUChar=mbcsHeader.version[2])!=0
   1547         ) {
   1548             maxFastUChar=(maxFastUChar<<8)|0xff;
   1549             mbcsIndexLength=((maxFastUChar+1)>>6)*2;  /* number of bytes */
   1550         }
   1551 
   1552         if(extOffset==0) {
   1553             size=(int32_t)(mbcsHeader.offsetFromUBytes+mbcsIndexLength);
   1554             if(!noFromU) {
   1555                 size+=(int32_t)mbcsHeader.fromUBytesLength;
   1556             }
   1557 
   1558             /* avoid compiler warnings - not otherwise necessary, and the value does not matter */
   1559             inExtIndexes=NULL;
   1560         } else {
   1561             /* there is extension data after the base data, see ucnv_ext.h */
   1562             if(length>=0 && length<(extOffset+UCNV_EXT_INDEXES_MIN_LENGTH*4)) {
   1563                 udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table with extension data\n",
   1564                                  length);
   1565                 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
   1566                 return 0;
   1567             }
   1568 
   1569             inExtIndexes=(const int32_t *)(inBytes+extOffset);
   1570             size=extOffset+udata_readInt32(ds, inExtIndexes[UCNV_EXT_SIZE]);
   1571         }
   1572 
   1573         if(length>=0) {
   1574             if(length<size) {
   1575                 udata_printError(ds, "ucnv_swap(): too few bytes (%d after headers) for an ICU MBCS .cnv conversion table\n",
   1576                                  length);
   1577                 *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
   1578                 return 0;
   1579             }
   1580 
   1581             /* copy the data for inaccessible bytes */
   1582             if(inBytes!=outBytes) {
   1583                 uprv_memcpy(outBytes, inBytes, size);
   1584             }
   1585 
   1586             /* swap the MBCSHeader, except for the version field */
   1587             count=mbcsHeaderLength*4;
   1588             ds->swapArray32(ds, &inMBCSHeader->countStates, count-4,
   1589                                &outMBCSHeader->countStates, pErrorCode);
   1590 
   1591             if(outputType==MBCS_OUTPUT_EXT_ONLY) {
   1592                 /*
   1593                  * extension-only file,
   1594                  * contains a base name instead of normal base table data
   1595                  */
   1596 
   1597                 /* swap the base name, between the header and the extension data */
   1598                 const char *inBaseName=(const char *)inBytes+count;
   1599                 char *outBaseName=(char *)outBytes+count;
   1600                 ds->swapInvChars(ds, inBaseName, (int32_t)uprv_strlen(inBaseName),
   1601                                     outBaseName, pErrorCode);
   1602             } else {
   1603                 /* normal file with base table data */
   1604 
   1605                 /* swap the state table, 1kB per state */
   1606                 offset=count;
   1607                 count=mbcsHeader.countStates*1024;
   1608                 ds->swapArray32(ds, inBytes+offset, (int32_t)count,
   1609                                    outBytes+offset, pErrorCode);
   1610 
   1611                 /* swap the toUFallbacks[] */
   1612                 offset+=count;
   1613                 count=mbcsHeader.countToUFallbacks*8;
   1614                 ds->swapArray32(ds, inBytes+offset, (int32_t)count,
   1615                                    outBytes+offset, pErrorCode);
   1616 
   1617                 /* swap the unicodeCodeUnits[] */
   1618                 offset=mbcsHeader.offsetToUCodeUnits;
   1619                 count=mbcsHeader.offsetFromUTable-offset;
   1620                 ds->swapArray16(ds, inBytes+offset, (int32_t)count,
   1621                                    outBytes+offset, pErrorCode);
   1622 
   1623                 /* offset to the stage 1 table, independent of the outputType */
   1624                 offset=mbcsHeader.offsetFromUTable;
   1625 
   1626                 if(outputType==MBCS_OUTPUT_1) {
   1627                     /* SBCS: swap the fromU tables, all 16 bits wide */
   1628                     count=(mbcsHeader.offsetFromUBytes-offset)+mbcsHeader.fromUBytesLength;
   1629                     ds->swapArray16(ds, inBytes+offset, (int32_t)count,
   1630                                        outBytes+offset, pErrorCode);
   1631                 } else {
   1632                     /* otherwise: swap the stage tables separately */
   1633 
   1634                     /* stage 1 table: uint16_t[0x440 or 0x40] */
   1635                     if(inStaticData->unicodeMask&UCNV_HAS_SUPPLEMENTARY) {
   1636                         count=0x440*2; /* for all of Unicode */
   1637                     } else {
   1638                         count=0x40*2; /* only BMP */
   1639                     }
   1640                     ds->swapArray16(ds, inBytes+offset, (int32_t)count,
   1641                                        outBytes+offset, pErrorCode);
   1642 
   1643                     /* stage 2 table: uint32_t[] */
   1644                     offset+=count;
   1645                     count=mbcsHeader.offsetFromUBytes-offset;
   1646                     ds->swapArray32(ds, inBytes+offset, (int32_t)count,
   1647                                        outBytes+offset, pErrorCode);
   1648 
   1649                     /* stage 3/result bytes: sometimes uint16_t[] or uint32_t[] */
   1650                     offset=mbcsHeader.offsetFromUBytes;
   1651                     count= noFromU ? 0 : mbcsHeader.fromUBytesLength;
   1652                     switch(outputType) {
   1653                     case MBCS_OUTPUT_2:
   1654                     case MBCS_OUTPUT_3_EUC:
   1655                     case MBCS_OUTPUT_2_SISO:
   1656                         ds->swapArray16(ds, inBytes+offset, (int32_t)count,
   1657                                            outBytes+offset, pErrorCode);
   1658                         break;
   1659                     case MBCS_OUTPUT_4:
   1660                         ds->swapArray32(ds, inBytes+offset, (int32_t)count,
   1661                                            outBytes+offset, pErrorCode);
   1662                         break;
   1663                     default:
   1664                         /* just uint8_t[], nothing to swap */
   1665                         break;
   1666                     }
   1667 
   1668                     if(mbcsIndexLength!=0) {
   1669                         offset+=count;
   1670                         count=mbcsIndexLength;
   1671                         ds->swapArray16(ds, inBytes+offset, (int32_t)count,
   1672                                            outBytes+offset, pErrorCode);
   1673                     }
   1674                 }
   1675             }
   1676 
   1677             if(extOffset!=0) {
   1678                 /* swap the extension data */
   1679                 inBytes+=extOffset;
   1680                 outBytes+=extOffset;
   1681 
   1682                 /* swap toUTable[] */
   1683                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_INDEX]);
   1684                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_LENGTH]);
   1685                 ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
   1686 
   1687                 /* swap toUUChars[] */
   1688                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_INDEX]);
   1689                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_TO_U_UCHARS_LENGTH]);
   1690                 ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
   1691 
   1692                 /* swap fromUTableUChars[] */
   1693                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_UCHARS_INDEX]);
   1694                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_LENGTH]);
   1695                 ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
   1696 
   1697                 /* swap fromUTableValues[] */
   1698                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_VALUES_INDEX]);
   1699                 /* same length as for fromUTableUChars[] */
   1700                 ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
   1701 
   1702                 /* no need to swap fromUBytes[] */
   1703 
   1704                 /* swap fromUStage12[] */
   1705                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_INDEX]);
   1706                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_12_LENGTH]);
   1707                 ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
   1708 
   1709                 /* swap fromUStage3[] */
   1710                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_INDEX]);
   1711                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3_LENGTH]);
   1712                 ds->swapArray16(ds, inBytes+offset, length*2, outBytes+offset, pErrorCode);
   1713 
   1714                 /* swap fromUStage3b[] */
   1715                 offset=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_INDEX]);
   1716                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_FROM_U_STAGE_3B_LENGTH]);
   1717                 ds->swapArray32(ds, inBytes+offset, length*4, outBytes+offset, pErrorCode);
   1718 
   1719                 /* swap indexes[] */
   1720                 length=udata_readInt32(ds, inExtIndexes[UCNV_EXT_INDEXES_LENGTH]);
   1721                 ds->swapArray32(ds, inBytes, length*4, outBytes, pErrorCode);
   1722             }
   1723         }
   1724     } else {
   1725         udata_printError(ds, "ucnv_swap(): unknown conversionType=%d!=UCNV_MBCS\n",
   1726                          inStaticData->conversionType);
   1727         *pErrorCode=U_UNSUPPORTED_ERROR;
   1728         return 0;
   1729     }
   1730 
   1731     return headerSize+(int32_t)staticDataSize+size;
   1732 }
   1733 
   1734 #endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */
   1735 
   1736 #endif
   1737