annotate modules/javafx.web/src/main/native/Source/ThirdParty/icu/source/common/uloc_keytype.cpp @ 11038:20a8447c71c6

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