LCOV - code coverage report
Current view: top level - intl/icu/source/common - uloc_keytype.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 336 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             : **********************************************************************
       5             : *   Copyright (C) 2014-2016, International Business Machines
       6             : *   Corporation and others.  All Rights Reserved.
       7             : **********************************************************************
       8             : */
       9             : #include "unicode/utypes.h"
      10             : 
      11             : #include "cstring.h"
      12             : #include "uassert.h"
      13             : #include "ucln_cmn.h"
      14             : #include "uhash.h"
      15             : #include "umutex.h"
      16             : #include "uresimp.h"
      17             : #include "uvector.h"
      18             : #include "udataswp.h" /* for InvChar functions */
      19             : 
      20             : static UHashtable* gLocExtKeyMap = NULL;
      21             : static icu::UInitOnce gLocExtKeyMapInitOnce = U_INITONCE_INITIALIZER;
      22             : static icu::UVector* gKeyTypeStringPool = NULL;
      23             : static icu::UVector* gLocExtKeyDataEntries = NULL;
      24             : static icu::UVector* gLocExtTypeEntries = NULL;
      25             : 
      26             : // bit flags for special types
      27             : typedef enum {
      28             :     SPECIALTYPE_NONE = 0,
      29             :     SPECIALTYPE_CODEPOINTS = 1,
      30             :     SPECIALTYPE_REORDER_CODE = 2,
      31             :     SPECIALTYPE_RG_KEY_VALUE = 4
      32             : } SpecialType;
      33             : 
      34             : typedef struct LocExtKeyData {
      35             :     const char*     legacyId;
      36             :     const char*     bcpId;
      37             :     UHashtable*     typeMap;
      38             :     uint32_t        specialTypes;
      39             : } LocExtKeyData;
      40             : 
      41             : typedef struct LocExtType {
      42             :     const char*     legacyId;
      43             :     const char*     bcpId;
      44             : } LocExtType;
      45             : 
      46             : U_CDECL_BEGIN
      47             : 
      48             : static UBool U_CALLCONV
      49           0 : uloc_key_type_cleanup(void) {
      50           0 :     if (gLocExtKeyMap != NULL) {
      51           0 :         uhash_close(gLocExtKeyMap);
      52           0 :         gLocExtKeyMap = NULL;
      53             :     }
      54             : 
      55           0 :     delete gLocExtKeyDataEntries;
      56           0 :     gLocExtKeyDataEntries = NULL;
      57             : 
      58           0 :     delete gLocExtTypeEntries;
      59           0 :     gLocExtTypeEntries = NULL;
      60             : 
      61           0 :     delete gKeyTypeStringPool;
      62           0 :     gKeyTypeStringPool = NULL;
      63             : 
      64           0 :     gLocExtKeyMapInitOnce.reset();
      65           0 :     return TRUE;
      66             : }
      67             : 
      68             : static void U_CALLCONV
      69           0 : uloc_deleteKeyTypeStringPoolEntry(void* obj) {
      70           0 :     uprv_free(obj);
      71           0 : }
      72             : 
      73             : static void U_CALLCONV
      74           0 : uloc_deleteKeyDataEntry(void* obj) {
      75           0 :     LocExtKeyData* keyData = (LocExtKeyData*)obj;
      76           0 :     if (keyData->typeMap != NULL) {
      77           0 :         uhash_close(keyData->typeMap);
      78             :     }
      79           0 :     uprv_free(keyData);
      80           0 : }
      81             : 
      82             : static void U_CALLCONV
      83           0 : uloc_deleteTypeEntry(void* obj) {
      84           0 :     uprv_free(obj);
      85           0 : }
      86             : 
      87             : U_CDECL_END
      88             : 
      89             : 
      90             : static void U_CALLCONV
      91           0 : initFromResourceBundle(UErrorCode& sts) {
      92             :     U_NAMESPACE_USE
      93           0 :     ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup);
      94             : 
      95           0 :     gLocExtKeyMap = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &sts);
      96             : 
      97           0 :     LocalUResourceBundlePointer keyTypeDataRes(ures_openDirect(NULL, "keyTypeData", &sts));
      98           0 :     LocalUResourceBundlePointer keyMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "keyMap", NULL, &sts));
      99           0 :     LocalUResourceBundlePointer typeMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "typeMap", NULL, &sts));
     100             : 
     101           0 :     if (U_FAILURE(sts)) {
     102           0 :         return;
     103             :     }
     104             : 
     105           0 :     UErrorCode tmpSts = U_ZERO_ERROR;
     106           0 :     LocalUResourceBundlePointer typeAliasRes(ures_getByKey(keyTypeDataRes.getAlias(), "typeAlias", NULL, &tmpSts));
     107           0 :     tmpSts = U_ZERO_ERROR;
     108           0 :     LocalUResourceBundlePointer bcpTypeAliasRes(ures_getByKey(keyTypeDataRes.getAlias(), "bcpTypeAlias", NULL, &tmpSts));
     109             : 
     110             :     // initialize vectors storing dynamically allocated objects
     111           0 :     gKeyTypeStringPool = new UVector(uloc_deleteKeyTypeStringPoolEntry, NULL, sts);
     112           0 :     if (gKeyTypeStringPool == NULL) {
     113           0 :         if (U_SUCCESS(sts)) {
     114           0 :             sts = U_MEMORY_ALLOCATION_ERROR;
     115             :         }
     116             :     }
     117           0 :     if (U_FAILURE(sts)) {
     118           0 :         return;
     119             :     }
     120           0 :     gLocExtKeyDataEntries = new UVector(uloc_deleteKeyDataEntry, NULL, sts);
     121           0 :     if (gLocExtKeyDataEntries == NULL) {
     122           0 :         if (U_SUCCESS(sts)) {
     123           0 :             sts = U_MEMORY_ALLOCATION_ERROR;
     124             :         }
     125             :     }
     126           0 :     if (U_FAILURE(sts)) {
     127           0 :         return;
     128             :     }
     129           0 :     gLocExtTypeEntries = new UVector(uloc_deleteTypeEntry, NULL, sts);
     130           0 :     if (gLocExtTypeEntries == NULL) {
     131           0 :         if (U_SUCCESS(sts)) {
     132           0 :             sts = U_MEMORY_ALLOCATION_ERROR;
     133             :         }
     134             :     }
     135           0 :     if (U_FAILURE(sts)) {
     136           0 :         return;
     137             :     }
     138             : 
     139             :     // iterate through keyMap resource
     140           0 :     LocalUResourceBundlePointer keyMapEntry;
     141             : 
     142           0 :     while (ures_hasNext(keyMapRes.getAlias())) {
     143           0 :         keyMapEntry.adoptInstead(ures_getNextResource(keyMapRes.getAlias(), keyMapEntry.orphan(), &sts));
     144           0 :         if (U_FAILURE(sts)) {
     145           0 :             break;
     146             :         }
     147           0 :         const char* legacyKeyId = ures_getKey(keyMapEntry.getAlias());
     148           0 :         int32_t bcpKeyIdLen = 0;
     149           0 :         const UChar* uBcpKeyId = ures_getString(keyMapEntry.getAlias(), &bcpKeyIdLen, &sts);
     150           0 :         if (U_FAILURE(sts)) {
     151           0 :             break;
     152             :         }
     153             : 
     154             :         // empty value indicates that BCP key is same with the legacy key.
     155           0 :         const char* bcpKeyId = legacyKeyId;
     156           0 :         if (bcpKeyIdLen > 0) {
     157           0 :             char* bcpKeyIdBuf = (char*)uprv_malloc(bcpKeyIdLen + 1);
     158           0 :             if (bcpKeyIdBuf == NULL) {
     159           0 :                 sts = U_MEMORY_ALLOCATION_ERROR;
     160           0 :                 break;
     161             :             }
     162           0 :             u_UCharsToChars(uBcpKeyId, bcpKeyIdBuf, bcpKeyIdLen);
     163           0 :             bcpKeyIdBuf[bcpKeyIdLen] = 0;
     164           0 :             gKeyTypeStringPool->addElement(bcpKeyIdBuf, sts);
     165           0 :             if (U_FAILURE(sts)) {
     166           0 :                 break;
     167             :             }
     168           0 :             bcpKeyId = bcpKeyIdBuf;
     169             :         }
     170             : 
     171           0 :         UBool isTZ = uprv_strcmp(legacyKeyId, "timezone") == 0;
     172             : 
     173           0 :         UHashtable* typeDataMap = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &sts);
     174           0 :         if (U_FAILURE(sts)) {
     175           0 :             break;
     176             :         }
     177           0 :         uint32_t specialTypes = SPECIALTYPE_NONE;
     178             : 
     179           0 :         LocalUResourceBundlePointer typeAliasResByKey;
     180           0 :         LocalUResourceBundlePointer bcpTypeAliasResByKey;
     181             : 
     182           0 :         if (typeAliasRes.isValid()) {
     183           0 :             tmpSts = U_ZERO_ERROR;
     184           0 :             typeAliasResByKey.adoptInstead(ures_getByKey(typeAliasRes.getAlias(), legacyKeyId, NULL, &tmpSts));
     185           0 :             if (U_FAILURE(tmpSts)) {
     186           0 :                 typeAliasResByKey.orphan();
     187             :             }
     188             :         }
     189           0 :         if (bcpTypeAliasRes.isValid()) {
     190           0 :             tmpSts = U_ZERO_ERROR;
     191           0 :             bcpTypeAliasResByKey.adoptInstead(ures_getByKey(bcpTypeAliasRes.getAlias(), bcpKeyId, NULL, &tmpSts));
     192           0 :             if (U_FAILURE(tmpSts)) {
     193           0 :                 bcpTypeAliasResByKey.orphan();
     194             :             }
     195             :         }
     196             : 
     197             :         // look up type map for the key, and walk through the mapping data
     198           0 :         tmpSts = U_ZERO_ERROR;
     199           0 :         LocalUResourceBundlePointer typeMapResByKey(ures_getByKey(typeMapRes.getAlias(), legacyKeyId, NULL, &tmpSts));
     200           0 :         if (U_FAILURE(tmpSts)) {
     201             :             // type map for each key must exist
     202           0 :             U_ASSERT(FALSE);
     203             :         } else {
     204           0 :             LocalUResourceBundlePointer typeMapEntry;
     205             : 
     206           0 :             while (ures_hasNext(typeMapResByKey.getAlias())) {
     207           0 :                 typeMapEntry.adoptInstead(ures_getNextResource(typeMapResByKey.getAlias(), typeMapEntry.orphan(), &sts));
     208           0 :                 if (U_FAILURE(sts)) {
     209           0 :                     break;
     210             :                 }
     211           0 :                 const char* legacyTypeId = ures_getKey(typeMapEntry.getAlias());
     212             : 
     213             :                 // special types
     214           0 :                 if (uprv_strcmp(legacyTypeId, "CODEPOINTS") == 0) {
     215           0 :                     specialTypes |= SPECIALTYPE_CODEPOINTS;
     216           0 :                     continue;
     217             :                 }
     218           0 :                 if (uprv_strcmp(legacyTypeId, "REORDER_CODE") == 0) {
     219           0 :                     specialTypes |= SPECIALTYPE_REORDER_CODE;
     220           0 :                     continue;
     221             :                 }
     222           0 :                 if (uprv_strcmp(legacyTypeId, "RG_KEY_VALUE") == 0) {
     223           0 :                     specialTypes |= SPECIALTYPE_RG_KEY_VALUE;
     224           0 :                     continue;
     225             :                 }
     226             : 
     227           0 :                 if (isTZ) {
     228             :                     // a timezone key uses a colon instead of a slash in the resource.
     229             :                     // e.g. America:Los_Angeles
     230           0 :                     if (uprv_strchr(legacyTypeId, ':') != NULL) {
     231           0 :                         int32_t legacyTypeIdLen = uprv_strlen(legacyTypeId);
     232           0 :                         char* legacyTypeIdBuf = (char*)uprv_malloc(legacyTypeIdLen + 1);
     233           0 :                         if (legacyTypeIdBuf == NULL) {
     234           0 :                             sts = U_MEMORY_ALLOCATION_ERROR;
     235           0 :                             break;
     236             :                         }
     237           0 :                         const char* p = legacyTypeId;
     238           0 :                         char* q = legacyTypeIdBuf;
     239           0 :                         while (*p) {
     240           0 :                             if (*p == ':') {
     241           0 :                                 *q++ = '/';
     242             :                             } else {
     243           0 :                                 *q++ = *p;
     244             :                             }
     245           0 :                             p++;
     246             :                         }
     247           0 :                         *q = 0;
     248             : 
     249           0 :                         gKeyTypeStringPool->addElement(legacyTypeIdBuf, sts);
     250           0 :                         if (U_FAILURE(sts)) {
     251           0 :                             break;
     252             :                         }
     253           0 :                         legacyTypeId = legacyTypeIdBuf;
     254             :                     }
     255             :                 }
     256             : 
     257           0 :                 int32_t bcpTypeIdLen = 0;
     258           0 :                 const UChar* uBcpTypeId = ures_getString(typeMapEntry.getAlias(), &bcpTypeIdLen, &sts);
     259           0 :                 if (U_FAILURE(sts)) {
     260           0 :                     break;
     261             :                 }
     262             : 
     263             :                 // empty value indicates that BCP type is same with the legacy type.
     264           0 :                 const char* bcpTypeId = legacyTypeId;
     265           0 :                 if (bcpTypeIdLen > 0) {
     266           0 :                     char* bcpTypeIdBuf = (char*)uprv_malloc(bcpTypeIdLen + 1);
     267           0 :                     if (bcpTypeIdBuf == NULL) {
     268           0 :                         sts = U_MEMORY_ALLOCATION_ERROR;
     269           0 :                         break;
     270             :                     }
     271           0 :                     u_UCharsToChars(uBcpTypeId, bcpTypeIdBuf, bcpTypeIdLen);
     272           0 :                     bcpTypeIdBuf[bcpTypeIdLen] = 0;
     273           0 :                     gKeyTypeStringPool->addElement(bcpTypeIdBuf, sts);
     274           0 :                     if (U_FAILURE(sts)) {
     275           0 :                         break;
     276             :                     }
     277           0 :                     bcpTypeId = bcpTypeIdBuf;
     278             :                 }
     279             : 
     280             :                 // Note: legacy type value should never be
     281             :                 // equivalent to bcp type value of a different
     282             :                 // type under the same key. So we use a single
     283             :                 // map for lookup.
     284           0 :                 LocExtType* t = (LocExtType*)uprv_malloc(sizeof(LocExtType));
     285           0 :                 if (t == NULL) {
     286           0 :                     sts = U_MEMORY_ALLOCATION_ERROR;
     287           0 :                     break;
     288             :                 }
     289           0 :                 t->bcpId = bcpTypeId;
     290           0 :                 t->legacyId = legacyTypeId;
     291           0 :                 gLocExtTypeEntries->addElement((void*)t, sts);
     292           0 :                 if (U_FAILURE(sts)) {
     293           0 :                     break;
     294             :                 }
     295             : 
     296           0 :                 uhash_put(typeDataMap, (void*)legacyTypeId, t, &sts);
     297           0 :                 if (bcpTypeId != legacyTypeId) {
     298             :                     // different type value
     299           0 :                     uhash_put(typeDataMap, (void*)bcpTypeId, t, &sts);
     300             :                 }
     301           0 :                 if (U_FAILURE(sts)) {
     302           0 :                     break;
     303             :                 }
     304             : 
     305             :                 // also put aliases in the map
     306           0 :                 if (typeAliasResByKey.isValid()) {
     307           0 :                     LocalUResourceBundlePointer typeAliasDataEntry;
     308             : 
     309           0 :                     ures_resetIterator(typeAliasResByKey.getAlias());
     310           0 :                     while (ures_hasNext(typeAliasResByKey.getAlias()) && U_SUCCESS(sts)) {
     311             :                         int32_t toLen;
     312           0 :                         typeAliasDataEntry.adoptInstead(ures_getNextResource(typeAliasResByKey.getAlias(), typeAliasDataEntry.orphan(), &sts));
     313           0 :                         const UChar* to = ures_getString(typeAliasDataEntry.getAlias(), &toLen, &sts);
     314           0 :                         if (U_FAILURE(sts)) {
     315           0 :                             break;
     316             :                         }
     317             :                         // check if this is an alias of canoncal legacy type
     318           0 :                         if (uprv_compareInvWithUChar(NULL, legacyTypeId, -1, to, toLen) == 0) {
     319           0 :                             const char* from = ures_getKey(typeAliasDataEntry.getAlias());
     320           0 :                             if (isTZ) {
     321             :                                 // replace colon with slash if necessary
     322           0 :                                 if (uprv_strchr(from, ':') != NULL) {
     323           0 :                                     int32_t fromLen = uprv_strlen(from);
     324           0 :                                     char* fromBuf = (char*)uprv_malloc(fromLen + 1);
     325           0 :                                     if (fromBuf == NULL) {
     326           0 :                                         sts = U_MEMORY_ALLOCATION_ERROR;
     327           0 :                                         break;
     328             :                                     }
     329           0 :                                     const char* p = from;
     330           0 :                                     char* q = fromBuf;
     331           0 :                                     while (*p) {
     332           0 :                                         if (*p == ':') {
     333           0 :                                             *q++ = '/';
     334             :                                         } else {
     335           0 :                                             *q++ = *p;
     336             :                                         }
     337           0 :                                         p++;
     338             :                                     }
     339           0 :                                     *q = 0;
     340             : 
     341           0 :                                     gKeyTypeStringPool->addElement(fromBuf, sts);
     342           0 :                                     if (U_FAILURE(sts)) {
     343           0 :                                         break;
     344             :                                     }
     345           0 :                                     from = fromBuf;
     346             :                                 }
     347             :                             }
     348           0 :                             uhash_put(typeDataMap, (void*)from, t, &sts);
     349             :                         }
     350             :                     }
     351           0 :                     if (U_FAILURE(sts)) {
     352           0 :                         break;
     353             :                     }
     354             :                 }
     355             : 
     356           0 :                 if (bcpTypeAliasResByKey.isValid()) {
     357           0 :                     LocalUResourceBundlePointer bcpTypeAliasDataEntry;
     358             : 
     359           0 :                     ures_resetIterator(bcpTypeAliasResByKey.getAlias());
     360           0 :                     while (ures_hasNext(bcpTypeAliasResByKey.getAlias()) && U_SUCCESS(sts)) {
     361             :                         int32_t toLen;
     362           0 :                         bcpTypeAliasDataEntry.adoptInstead(ures_getNextResource(bcpTypeAliasResByKey.getAlias(), bcpTypeAliasDataEntry.orphan(), &sts));
     363           0 :                         const UChar* to = ures_getString(bcpTypeAliasDataEntry.getAlias(), &toLen, &sts);
     364           0 :                         if (U_FAILURE(sts)) {
     365           0 :                             break;
     366             :                         }
     367             :                         // check if this is an alias of bcp type
     368           0 :                         if (uprv_compareInvWithUChar(NULL, bcpTypeId, -1, to, toLen) == 0) {
     369           0 :                             const char* from = ures_getKey(bcpTypeAliasDataEntry.getAlias());
     370           0 :                             uhash_put(typeDataMap, (void*)from, t, &sts);
     371             :                         }
     372             :                     }
     373           0 :                     if (U_FAILURE(sts)) {
     374           0 :                         break;
     375             :                     }
     376             :                 }
     377             :             }
     378             :         }
     379           0 :         if (U_FAILURE(sts)) {
     380           0 :             break;
     381             :         }
     382             : 
     383           0 :         LocExtKeyData* keyData = (LocExtKeyData*)uprv_malloc(sizeof(LocExtKeyData));
     384           0 :         if (keyData == NULL) {
     385           0 :             sts = U_MEMORY_ALLOCATION_ERROR;
     386           0 :             break;
     387             :         }
     388           0 :         keyData->bcpId = bcpKeyId;
     389           0 :         keyData->legacyId = legacyKeyId;
     390           0 :         keyData->specialTypes = specialTypes;
     391           0 :         keyData->typeMap = typeDataMap;
     392             : 
     393           0 :         gLocExtKeyDataEntries->addElement((void*)keyData, sts);
     394           0 :         if (U_FAILURE(sts)) {
     395           0 :             break;
     396             :         }
     397             : 
     398           0 :         uhash_put(gLocExtKeyMap, (void*)legacyKeyId, keyData, &sts);
     399           0 :         if (legacyKeyId != bcpKeyId) {
     400             :             // different key value
     401           0 :             uhash_put(gLocExtKeyMap, (void*)bcpKeyId, keyData, &sts);
     402             :         }
     403           0 :         if (U_FAILURE(sts)) {
     404           0 :             break;
     405             :         }
     406             :     }
     407             : }
     408             : 
     409             : static UBool
     410           0 : init() {
     411           0 :     UErrorCode sts = U_ZERO_ERROR;
     412           0 :     umtx_initOnce(gLocExtKeyMapInitOnce, &initFromResourceBundle, sts);
     413           0 :     if (U_FAILURE(sts)) {
     414           0 :         return FALSE;
     415             :     }
     416           0 :     return TRUE;
     417             : }
     418             : 
     419             : static UBool
     420           0 : isSpecialTypeCodepoints(const char* val) {
     421           0 :     int32_t subtagLen = 0;
     422           0 :     const char* p = val;
     423           0 :     while (*p) {
     424           0 :         if (*p == '-') {
     425           0 :             if (subtagLen < 4 || subtagLen > 6) {
     426           0 :                 return FALSE;
     427             :             }
     428           0 :             subtagLen = 0;
     429           0 :         } else if ((*p >= '0' && *p <= '9') ||
     430           0 :                     (*p >= 'A' && *p <= 'F') || // A-F/a-f are contiguous
     431           0 :                     (*p >= 'a' && *p <= 'f')) { // also in EBCDIC
     432           0 :             subtagLen++;
     433             :         } else {
     434           0 :             return FALSE;
     435             :         }
     436           0 :         p++;
     437             :     }
     438           0 :     return (subtagLen >= 4 && subtagLen <= 6);
     439             : }
     440             : 
     441             : static UBool
     442           0 : isSpecialTypeReorderCode(const char* val) {
     443           0 :     int32_t subtagLen = 0;
     444           0 :     const char* p = val;
     445           0 :     while (*p) {
     446           0 :         if (*p == '-') {
     447           0 :             if (subtagLen < 3 || subtagLen > 8) {
     448           0 :                 return FALSE;
     449             :             }
     450           0 :             subtagLen = 0;
     451           0 :         } else if (uprv_isASCIILetter(*p)) {
     452           0 :             subtagLen++;
     453             :         } else {
     454           0 :             return FALSE;
     455             :         }
     456           0 :         p++;
     457             :     }
     458           0 :     return (subtagLen >=3 && subtagLen <=8);
     459             : }
     460             : 
     461             : static UBool
     462           0 : isSpecialTypeRgKeyValue(const char* val) {
     463           0 :     int32_t subtagLen = 0;
     464           0 :     const char* p = val;
     465           0 :     while (*p) {
     466           0 :         if ( (subtagLen < 2 && uprv_isASCIILetter(*p)) ||
     467           0 :                     (subtagLen >= 2 && (*p == 'Z' || *p == 'z')) ) {
     468           0 :             subtagLen++;
     469             :         } else {
     470           0 :             return FALSE;
     471             :         }
     472           0 :         p++;
     473             :     }
     474           0 :     return (subtagLen == 6);
     475             :     return TRUE;
     476             : }
     477             : 
     478             : U_CFUNC const char*
     479           0 : ulocimp_toBcpKey(const char* key) {
     480           0 :     if (!init()) {
     481           0 :         return NULL;
     482             :     }
     483             : 
     484           0 :     LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key);
     485           0 :     if (keyData != NULL) {
     486           0 :         return keyData->bcpId;
     487             :     }
     488           0 :     return NULL;
     489             : }
     490             : 
     491             : U_CFUNC const char*
     492           0 : ulocimp_toLegacyKey(const char* key) {
     493           0 :     if (!init()) {
     494           0 :         return NULL;
     495             :     }
     496             : 
     497           0 :     LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key);
     498           0 :     if (keyData != NULL) {
     499           0 :         return keyData->legacyId;
     500             :     }
     501           0 :     return NULL;
     502             : }
     503             : 
     504             : U_CFUNC const char*
     505           0 : ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType) {
     506           0 :     if (isKnownKey != NULL) {
     507           0 :         *isKnownKey = FALSE;
     508             :     }
     509           0 :     if (isSpecialType != NULL) {
     510           0 :         *isSpecialType = FALSE;
     511             :     }
     512             : 
     513           0 :     if (!init()) {
     514           0 :         return NULL;
     515             :     }
     516             : 
     517           0 :     LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key);
     518           0 :     if (keyData != NULL) {
     519           0 :         if (isKnownKey != NULL) {
     520           0 :             *isKnownKey = TRUE;
     521             :         }
     522           0 :         LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap, type);
     523           0 :         if (t != NULL) {
     524           0 :             return t->bcpId;
     525             :         }
     526           0 :         if (keyData->specialTypes != SPECIALTYPE_NONE) {
     527           0 :             UBool matched = FALSE;
     528           0 :             if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) {
     529           0 :                 matched = isSpecialTypeCodepoints(type);
     530             :             }
     531           0 :             if (!matched && keyData->specialTypes & SPECIALTYPE_REORDER_CODE) {
     532           0 :                 matched = isSpecialTypeReorderCode(type);
     533             :             }
     534           0 :             if (!matched && keyData->specialTypes & SPECIALTYPE_RG_KEY_VALUE) {
     535           0 :                 matched = isSpecialTypeRgKeyValue(type);
     536             :             }
     537           0 :             if (matched) {
     538           0 :                 if (isSpecialType != NULL) {
     539           0 :                     *isSpecialType = TRUE;
     540             :                 }
     541           0 :                 return type;
     542             :             }
     543             :         }
     544             :     }
     545           0 :     return NULL;
     546             : }
     547             : 
     548             : 
     549             : U_CFUNC const char*
     550           0 : ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool* isSpecialType) {
     551           0 :     if (isKnownKey != NULL) {
     552           0 :         *isKnownKey = FALSE;
     553             :     }
     554           0 :     if (isSpecialType != NULL) {
     555           0 :         *isSpecialType = FALSE;
     556             :     }
     557             : 
     558           0 :     if (!init()) {
     559           0 :         return NULL;
     560             :     }
     561             : 
     562           0 :     LocExtKeyData* keyData = (LocExtKeyData*)uhash_get(gLocExtKeyMap, key);
     563           0 :     if (keyData != NULL) {
     564           0 :         if (isKnownKey != NULL) {
     565           0 :             *isKnownKey = TRUE;
     566             :         }
     567           0 :         LocExtType* t = (LocExtType*)uhash_get(keyData->typeMap, type);
     568           0 :         if (t != NULL) {
     569           0 :             return t->legacyId;
     570             :         }
     571           0 :         if (keyData->specialTypes != SPECIALTYPE_NONE) {
     572           0 :             UBool matched = FALSE;
     573           0 :             if (keyData->specialTypes & SPECIALTYPE_CODEPOINTS) {
     574           0 :                 matched = isSpecialTypeCodepoints(type);
     575             :             }
     576           0 :             if (!matched && keyData->specialTypes & SPECIALTYPE_REORDER_CODE) {
     577           0 :                 matched = isSpecialTypeReorderCode(type);
     578             :             }
     579           0 :             if (!matched && keyData->specialTypes & SPECIALTYPE_RG_KEY_VALUE) {
     580           0 :                 matched = isSpecialTypeRgKeyValue(type);
     581             :             }
     582           0 :             if (matched) {
     583           0 :                 if (isSpecialType != NULL) {
     584           0 :                     *isSpecialType = TRUE;
     585             :                 }
     586           0 :                 return type;
     587             :             }
     588             :         }
     589             :     }
     590           0 :     return NULL;
     591             : }
     592             : 

Generated by: LCOV version 1.13