16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* 26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ******************************************************************************* 36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Copyright (C) 2002-2011, International Business Machines Corporation and 46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * others. All Rights Reserved. 56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ******************************************************************************* 66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h" 86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_SERVICE || !UCONFIG_NO_TRANSLITERATION 106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/resbund.h" 126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h" 136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ustrfmt.h" 146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "locutil.h" 156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "charstr.h" 166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucln_cmn.h" 176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h" 186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "umutex.h" 196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// see LocaleUtility::getAvailableLocaleNames 216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic icu::Hashtable * LocaleUtility_cache = NULL; 226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define UNDERSCORE_CHAR ((UChar)0x005f) 246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define AT_SIGN_CHAR ((UChar)64) 256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define PERIOD_CHAR ((UChar)46) 266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* 286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ****************************************************************** 296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/** 326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Release all static memory held by Locale Utility. 336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CDECL_BEGIN 356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV service_cleanup(void) { 366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (LocaleUtility_cache) { 376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org delete LocaleUtility_cache; 386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org LocaleUtility_cache = NULL; 396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return TRUE; 416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CDECL_END 436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN 456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString& 476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocaleUtility::canonicalLocaleString(const UnicodeString* id, UnicodeString& result) 486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (id == NULL) { 506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.setToBogus(); 516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Fix case only (no other changes) up to the first '@' or '.' or 536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // end of string, whichever comes first. In 3.0 I changed this to 546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // stop at first '@' or '.'. It used to run out to the end of 556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // string. My fix makes the tests pass but is probably 566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // structurally incorrect. See below. [alan 3.0] 576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // TODO: Doug, you might want to revise this... 596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result = *id; 606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t i = 0; 616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t end = result.indexOf(AT_SIGN_CHAR); 626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t n = result.indexOf(PERIOD_CHAR); 636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (n >= 0 && n < end) { 646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org end = n; 656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (end < 0) { 676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org end = result.length(); 686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org n = result.indexOf(UNDERSCORE_CHAR); 706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (n < 0) { 716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org n = end; 726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org for (; i < n; ++i) { 746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UChar c = result.charAt(i); 756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (c >= 0x0041 && c <= 0x005a) { 766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org c += 0x20; 776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.setCharAt(i, c); 786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org for (n = end; i < n; ++i) { 816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UChar c = result.charAt(i); 826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (c >= 0x0061 && c <= 0x007a) { 836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org c -= 0x20; 846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.setCharAt(i, c); 856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return result; 896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if 0 916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // This code does a proper full level 2 canonicalization of id. 926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // It's nasty to go from UChar to char to char to UChar -- but 936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // that's what you have to do to use the uloc_canonicalize 946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // function on UnicodeStrings. 956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // I ended up doing the alternate fix (see above) not for 976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // performance reasons, although performance will certainly be 986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // better, but because doing a full level 2 canonicalization 996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // causes some tests to fail. [alan 3.0] 1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // TODO: Doug, you might want to revisit this... 1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.setToBogus(); 1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (id != 0) { 1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t buflen = id->length() + 8; // space for NUL 1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char* buf = (char*) uprv_malloc(buflen); 1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char* canon = (buf == 0) ? 0 : (char*) uprv_malloc(buflen); 1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (buf != 0 && canon != 0) { 1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org U_ASSERT(id->extract(0, INT32_MAX, buf, buflen) < buflen); 1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UErrorCode ec = U_ZERO_ERROR; 1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uloc_canonicalize(buf, canon, buflen, &ec); 1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (U_SUCCESS(ec)) { 1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result = UnicodeString(canon); 1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uprv_free(buf); 1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uprv_free(canon); 1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return result; 1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocale& 1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocaleUtility::initLocaleFromName(const UnicodeString& id, Locale& result) 1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org enum { BUFLEN = 128 }; // larger than ever needed 1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (id.isBogus() || id.length() >= BUFLEN) { 1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.setToBogus(); 1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* 1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * We need to convert from a UnicodeString to char * in order to 1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * create a Locale. 1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * 1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Problem: Locale ID strings may contain '@' which is a variant 1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * character and cannot be handled by invariant-character conversion. 1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * 1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Hack: Since ICU code can handle locale IDs with multiple encodings 1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * of '@' (at least for EBCDIC; it's not known to be a problem for 1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * ASCII-based systems), 1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * we use regular invariant-character conversion for everything else 1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and manually convert U+0040 into a compiler-char-constant '@'. 1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * While this compilation-time constant may not match the runtime 1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * encoding of '@', it should be one of the encodings which ICU 1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * recognizes. 1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * 1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * There should be only at most one '@' in a locale ID. 1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char buffer[BUFLEN]; 1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org int32_t prev, i; 1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org prev = 0; 1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org for(;;) { 1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org i = id.indexOf((UChar)0x40, prev); 1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(i < 0) { 1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // no @ between prev and the rest of the string 1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org id.extract(prev, INT32_MAX, buffer + prev, BUFLEN - prev, US_INV); 1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org break; // done 1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // normal invariant-character conversion for text between @s 1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org id.extract(prev, i - prev, buffer + prev, BUFLEN - prev, US_INV); 1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // manually "convert" U+0040 at id[i] into '@' at buffer[i] 1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org buffer[i] = '@'; 1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org prev = i + 1; 1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result = Locale::createFromName(buffer); 1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return result; 1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString& 1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocaleUtility::initNameFromLocale(const Locale& locale, UnicodeString& result) 1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (locale.isBogus()) { 1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.setToBogus(); 1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org result.append(UnicodeString(locale.getName(), -1, US_INV)); 1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return result; 1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst Hashtable* 1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocaleUtility::getAvailableLocaleNames(const UnicodeString& bundleID) 1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // LocaleUtility_cache is a hash-of-hashes. The top-level keys 1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // are path strings ('bundleID') passed to 1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // ures_openAvailableLocales. The top-level values are 1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // second-level hashes. The second-level keys are result strings 1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // from ures_openAvailableLocales. The second-level values are 1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // garbage ((void*)1 or other random pointer). 1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UErrorCode status = U_ZERO_ERROR; 1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Hashtable* cache; 1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_lock(NULL); 1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cache = LocaleUtility_cache; 1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_unlock(NULL); 1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (cache == NULL) { 1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cache = new Hashtable(status); 1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (cache == NULL || U_FAILURE(status)) { 2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return NULL; // catastrophic failure; e.g. out of memory 2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cache->setValueDeleter(uhash_deleteHashtable); 2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Hashtable* h; // set this to final LocaleUtility_cache value 2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_lock(NULL); 2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org h = LocaleUtility_cache; 2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (h == NULL) { 2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org LocaleUtility_cache = h = cache; 2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cache = NULL; 2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ucln_common_registerCleanup(UCLN_COMMON_SERVICE, service_cleanup); 2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_unlock(NULL); 2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if(cache != NULL) { 2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org delete cache; 2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cache = h; 2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org U_ASSERT(cache != NULL); 2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Hashtable* htp; 2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_lock(NULL); 2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org htp = (Hashtable*) cache->get(bundleID); 2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_unlock(NULL); 2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (htp == NULL) { 2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org htp = new Hashtable(status); 2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (htp && U_SUCCESS(status)) { 2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org CharString cbundleID; 2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cbundleID.appendInvariantChars(bundleID, status); 2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const char* path = cbundleID.isEmpty() ? NULL : cbundleID.data(); 2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org UEnumeration *uenum = ures_openAvailableLocales(path, &status); 2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org for (;;) { 2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const UChar* id = uenum_unext(uenum, NULL, &status); 2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (id == NULL) { 2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org break; 2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org htp->put(UnicodeString(id), (void*)htp, status); 2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uenum_close(uenum); 2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (U_FAILURE(status)) { 2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org delete htp; 2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return NULL; 2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_lock(NULL); 2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org cache->put(bundleID, (void*)htp, status); 2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org umtx_unlock(NULL); 2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return htp; 2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool 2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocaleUtility::isFallbackOf(const UnicodeString& root, const UnicodeString& child) 2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return child.indexOf(root) == 0 && 2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org (child.length() == root.length() || 2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org child.charAt(root.length()) == UNDERSCORE_CHAR); 2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END 2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* !UCONFIG_NO_SERVICE */ 2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 266