| OLD | NEW |
| 1 /* | 1 /* |
| 2 ********************************************************************** | 2 ********************************************************************** |
| 3 * Copyright (C) 1997-2012, International Business Machines | 3 * Copyright (C) 1997-2014, International Business Machines |
| 4 * Corporation and others. All Rights Reserved. | 4 * Corporation and others. All Rights Reserved. |
| 5 ********************************************************************** | 5 ********************************************************************** |
| 6 * | 6 * |
| 7 * File locid.cpp | 7 * File locid.cpp |
| 8 * | 8 * |
| 9 * Created by: Richard Gillam | 9 * Created by: Richard Gillam |
| 10 * | 10 * |
| 11 * Modification History: | 11 * Modification History: |
| 12 * | 12 * |
| 13 * Date Name Description | 13 * Date Name Description |
| (...skipping 21 matching lines...) Expand all Loading... |
| 35 #include "putilimp.h" | 35 #include "putilimp.h" |
| 36 #include "mutex.h" | 36 #include "mutex.h" |
| 37 #include "umutex.h" | 37 #include "umutex.h" |
| 38 #include "uassert.h" | 38 #include "uassert.h" |
| 39 #include "cmemory.h" | 39 #include "cmemory.h" |
| 40 #include "cstring.h" | 40 #include "cstring.h" |
| 41 #include "uhash.h" | 41 #include "uhash.h" |
| 42 #include "ucln_cmn.h" | 42 #include "ucln_cmn.h" |
| 43 #include "ustr_imp.h" | 43 #include "ustr_imp.h" |
| 44 | 44 |
| 45 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) | |
| 46 | |
| 47 U_CDECL_BEGIN | 45 U_CDECL_BEGIN |
| 48 static UBool U_CALLCONV locale_cleanup(void); | 46 static UBool U_CALLCONV locale_cleanup(void); |
| 49 U_CDECL_END | 47 U_CDECL_END |
| 50 | 48 |
| 51 U_NAMESPACE_BEGIN | 49 U_NAMESPACE_BEGIN |
| 52 | 50 |
| 53 static Locale *gLocaleCache = NULL; | 51 static Locale *gLocaleCache = NULL; |
| 52 static UInitOnce gLocaleCacheInitOnce = U_INITONCE_INITIALIZER; |
| 54 | 53 |
| 55 // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultL
ocale. | 54 // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultL
ocale. |
| 56 static UMutex gDefaultLocaleMutex = U_MUTEX_INITIALIZER; | 55 static UMutex gDefaultLocaleMutex = U_MUTEX_INITIALIZER; |
| 57 static UHashtable *gDefaultLocalesHashT = NULL; | 56 static UHashtable *gDefaultLocalesHashT = NULL; |
| 58 static Locale *gDefaultLocale = NULL; | 57 static Locale *gDefaultLocale = NULL; |
| 59 | 58 |
| 60 U_NAMESPACE_END | 59 U_NAMESPACE_END |
| 61 | 60 |
| 62 typedef enum ELocalePos { | 61 typedef enum ELocalePos { |
| 63 eENGLISH, | 62 eENGLISH, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 // | 98 // |
| 100 static void U_CALLCONV | 99 static void U_CALLCONV |
| 101 deleteLocale(void *obj) { | 100 deleteLocale(void *obj) { |
| 102 delete (icu::Locale *) obj; | 101 delete (icu::Locale *) obj; |
| 103 } | 102 } |
| 104 | 103 |
| 105 static UBool U_CALLCONV locale_cleanup(void) | 104 static UBool U_CALLCONV locale_cleanup(void) |
| 106 { | 105 { |
| 107 U_NAMESPACE_USE | 106 U_NAMESPACE_USE |
| 108 | 107 |
| 109 if (gLocaleCache) { | 108 delete [] gLocaleCache; |
| 110 delete [] gLocaleCache; | 109 gLocaleCache = NULL; |
| 111 gLocaleCache = NULL; | 110 gLocaleCacheInitOnce.reset(); |
| 112 } | |
| 113 | 111 |
| 114 if (gDefaultLocalesHashT) { | 112 if (gDefaultLocalesHashT) { |
| 115 uhash_close(gDefaultLocalesHashT); // Automatically deletes all elemen
ts, using deleter func. | 113 uhash_close(gDefaultLocalesHashT); // Automatically deletes all elemen
ts, using deleter func. |
| 116 gDefaultLocalesHashT = NULL; | 114 gDefaultLocalesHashT = NULL; |
| 117 gDefaultLocale = NULL; | |
| 118 } | 115 } |
| 119 | 116 gDefaultLocale = NULL; |
| 120 return TRUE; | 117 return TRUE; |
| 121 } | 118 } |
| 119 |
| 120 |
| 121 static void U_CALLCONV locale_init(UErrorCode &status) { |
| 122 U_NAMESPACE_USE |
| 123 |
| 124 U_ASSERT(gLocaleCache == NULL); |
| 125 gLocaleCache = new Locale[(int)eMAX_LOCALES]; |
| 126 if (gLocaleCache == NULL) { |
| 127 status = U_MEMORY_ALLOCATION_ERROR; |
| 128 return; |
| 129 } |
| 130 ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); |
| 131 gLocaleCache[eROOT] = Locale(""); |
| 132 gLocaleCache[eENGLISH] = Locale("en"); |
| 133 gLocaleCache[eFRENCH] = Locale("fr"); |
| 134 gLocaleCache[eGERMAN] = Locale("de"); |
| 135 gLocaleCache[eITALIAN] = Locale("it"); |
| 136 gLocaleCache[eJAPANESE] = Locale("ja"); |
| 137 gLocaleCache[eKOREAN] = Locale("ko"); |
| 138 gLocaleCache[eCHINESE] = Locale("zh"); |
| 139 gLocaleCache[eFRANCE] = Locale("fr", "FR"); |
| 140 gLocaleCache[eGERMANY] = Locale("de", "DE"); |
| 141 gLocaleCache[eITALY] = Locale("it", "IT"); |
| 142 gLocaleCache[eJAPAN] = Locale("ja", "JP"); |
| 143 gLocaleCache[eKOREA] = Locale("ko", "KR"); |
| 144 gLocaleCache[eCHINA] = Locale("zh", "CN"); |
| 145 gLocaleCache[eTAIWAN] = Locale("zh", "TW"); |
| 146 gLocaleCache[eUK] = Locale("en", "GB"); |
| 147 gLocaleCache[eUS] = Locale("en", "US"); |
| 148 gLocaleCache[eCANADA] = Locale("en", "CA"); |
| 149 gLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA"); |
| 150 } |
| 151 |
| 122 U_CDECL_END | 152 U_CDECL_END |
| 123 | 153 |
| 124 U_NAMESPACE_BEGIN | 154 U_NAMESPACE_BEGIN |
| 125 | 155 |
| 126 Locale *locale_set_default_internal(const char *id, UErrorCode& status) { | 156 Locale *locale_set_default_internal(const char *id, UErrorCode& status) { |
| 127 // Synchronize this entire function. | 157 // Synchronize this entire function. |
| 128 Mutex lock(&gDefaultLocaleMutex); | 158 Mutex lock(&gDefaultLocaleMutex); |
| 129 | 159 |
| 130 UBool canonicalize = FALSE; | 160 UBool canonicalize = FALSE; |
| 131 | 161 |
| 132 // If given a NULL string for the locale id, grab the default | 162 // If given a NULL string for the locale id, grab the default |
| 133 // name from the system. | 163 // name from the system. |
| 134 // (Different from most other locale APIs, where a null name means use | 164 // (Different from most other locale APIs, where a null name means use |
| 135 // the current ICU default locale.) | 165 // the current ICU default locale.) |
| 136 if (id == NULL) { | 166 if (id == NULL) { |
| 137 id = uprv_getDefaultLocaleID(); // This function not thread safe? TODO
: verify. | 167 id = uprv_getDefaultLocaleID(); // This function not thread safe? TODO
: verify. |
| 138 canonicalize = TRUE; // always canonicalize host ID | 168 canonicalize = TRUE; // always canonicalize host ID |
| 139 } | 169 } |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 { | 413 { |
| 384 *this = other; | 414 *this = other; |
| 385 } | 415 } |
| 386 | 416 |
| 387 Locale &Locale::operator=(const Locale &other) | 417 Locale &Locale::operator=(const Locale &other) |
| 388 { | 418 { |
| 389 if (this == &other) { | 419 if (this == &other) { |
| 390 return *this; | 420 return *this; |
| 391 } | 421 } |
| 392 | 422 |
| 393 if (&other == NULL) { | |
| 394 this->setToBogus(); | |
| 395 return *this; | |
| 396 } | |
| 397 | |
| 398 /* Free our current storage */ | 423 /* Free our current storage */ |
| 399 if(fullName != fullNameBuffer) { | 424 if(fullName != fullNameBuffer) { |
| 400 uprv_free(fullName); | 425 uprv_free(fullName); |
| 401 fullName = fullNameBuffer; | 426 fullName = fullNameBuffer; |
| 402 } | 427 } |
| 403 | 428 |
| 404 /* Allocate the full name if necessary */ | 429 /* Allocate the full name if necessary */ |
| 405 if(other.fullName != other.fullNameBuffer) { | 430 if(other.fullName != other.fullNameBuffer) { |
| 406 fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)
+1)); | 431 fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)
+1)); |
| 407 if (fullName == NULL) { | 432 if (fullName == NULL) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 UErrorCode err; | 502 UErrorCode err; |
| 478 | 503 |
| 479 if(localeID == NULL) { | 504 if(localeID == NULL) { |
| 480 // not an error, just set the default locale | 505 // not an error, just set the default locale |
| 481 return *this = getDefault(); | 506 return *this = getDefault(); |
| 482 } | 507 } |
| 483 | 508 |
| 484 /* preset all fields to empty */ | 509 /* preset all fields to empty */ |
| 485 language[0] = script[0] = country[0] = 0; | 510 language[0] = script[0] = country[0] = 0; |
| 486 | 511 |
| 487 // Need to reset baseName. Otherwise, when a Locale object created with | |
| 488 // the default constructor is changed with setFromPOSIXID() later | |
| 489 // (e.g. locales obtained with getAvailableLocales()), | |
| 490 // baseName will be still that of the default locale instead of one | |
| 491 // corresponding to localeID. | |
| 492 baseName = NULL; | |
| 493 | |
| 494 // "canonicalize" the locale ID to ICU/Java format | 512 // "canonicalize" the locale ID to ICU/Java format |
| 495 err = U_ZERO_ERROR; | 513 err = U_ZERO_ERROR; |
| 496 length = canonicalize ? | 514 length = canonicalize ? |
| 497 uloc_canonicalize(localeID, fullName, sizeof(fullNameBuffer), &err)
: | 515 uloc_canonicalize(localeID, fullName, sizeof(fullNameBuffer), &err)
: |
| 498 uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err); | 516 uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err); |
| 499 | 517 |
| 500 if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameB
uffer)) { | 518 if(err == U_BUFFER_OVERFLOW_ERROR || length >= (int32_t)sizeof(fullNameB
uffer)) { |
| 501 /*Go to heap for the fullName if necessary*/ | 519 /*Go to heap for the fullName if necessary*/ |
| 502 fullName = (char *)uprv_malloc(sizeof(char)*(length + 1)); | 520 fullName = (char *)uprv_malloc(sizeof(char)*(length + 1)); |
| 503 if(fullName == 0) { | 521 if(fullName == 0) { |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 return localeCache[locid]; /*operating on NULL*/ | 860 return localeCache[locid]; /*operating on NULL*/ |
| 843 } | 861 } |
| 844 | 862 |
| 845 /* | 863 /* |
| 846 This function is defined this way in order to get around static | 864 This function is defined this way in order to get around static |
| 847 initialization and static destruction. | 865 initialization and static destruction. |
| 848 */ | 866 */ |
| 849 Locale * | 867 Locale * |
| 850 Locale::getLocaleCache(void) | 868 Locale::getLocaleCache(void) |
| 851 { | 869 { |
| 852 umtx_lock(NULL); | 870 UErrorCode status = U_ZERO_ERROR; |
| 853 UBool needInit = (gLocaleCache == NULL); | 871 umtx_initOnce(gLocaleCacheInitOnce, locale_init, status); |
| 854 umtx_unlock(NULL); | |
| 855 | |
| 856 if (needInit) { | |
| 857 Locale *tLocaleCache = new Locale[(int)eMAX_LOCALES]; | |
| 858 if (tLocaleCache == NULL) { | |
| 859 return NULL; | |
| 860 } | |
| 861 » tLocaleCache[eROOT] = Locale(""); | |
| 862 tLocaleCache[eENGLISH] = Locale("en"); | |
| 863 tLocaleCache[eFRENCH] = Locale("fr"); | |
| 864 tLocaleCache[eGERMAN] = Locale("de"); | |
| 865 tLocaleCache[eITALIAN] = Locale("it"); | |
| 866 tLocaleCache[eJAPANESE] = Locale("ja"); | |
| 867 tLocaleCache[eKOREAN] = Locale("ko"); | |
| 868 tLocaleCache[eCHINESE] = Locale("zh"); | |
| 869 tLocaleCache[eFRANCE] = Locale("fr", "FR"); | |
| 870 tLocaleCache[eGERMANY] = Locale("de", "DE"); | |
| 871 tLocaleCache[eITALY] = Locale("it", "IT"); | |
| 872 tLocaleCache[eJAPAN] = Locale("ja", "JP"); | |
| 873 tLocaleCache[eKOREA] = Locale("ko", "KR"); | |
| 874 tLocaleCache[eCHINA] = Locale("zh", "CN"); | |
| 875 tLocaleCache[eTAIWAN] = Locale("zh", "TW"); | |
| 876 tLocaleCache[eUK] = Locale("en", "GB"); | |
| 877 tLocaleCache[eUS] = Locale("en", "US"); | |
| 878 tLocaleCache[eCANADA] = Locale("en", "CA"); | |
| 879 tLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA"); | |
| 880 | |
| 881 umtx_lock(NULL); | |
| 882 if (gLocaleCache == NULL) { | |
| 883 gLocaleCache = tLocaleCache; | |
| 884 tLocaleCache = NULL; | |
| 885 ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); | |
| 886 } | |
| 887 umtx_unlock(NULL); | |
| 888 if (tLocaleCache) { | |
| 889 delete [] tLocaleCache; // Fancy array delete will destruct each me
mber. | |
| 890 } | |
| 891 } | |
| 892 return gLocaleCache; | 872 return gLocaleCache; |
| 893 } | 873 } |
| 894 | 874 |
| 895 class KeywordEnumeration : public StringEnumeration { | 875 class KeywordEnumeration : public StringEnumeration { |
| 896 private: | 876 private: |
| 897 char *keywords; | 877 char *keywords; |
| 898 char *current; | 878 char *current; |
| 899 int32_t length; | 879 int32_t length; |
| 900 UnicodeString currUSKey; | 880 UnicodeString currUSKey; |
| 901 static const char fgClassID;/* Warning this is used beyond the typical RTTI
usage. */ | 881 static const char fgClassID;/* Warning this is used beyond the typical RTTI
usage. */ |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 // the length of the baseName. Patch around this for now. | 1015 // the length of the baseName. Patch around this for now. |
| 1036 if (variantBegin == (int32_t)uprv_strlen(fullName)) { | 1016 if (variantBegin == (int32_t)uprv_strlen(fullName)) { |
| 1037 ((Locale*)this)->variantBegin = baseNameSize; | 1017 ((Locale*)this)->variantBegin = baseNameSize; |
| 1038 } | 1018 } |
| 1039 } | 1019 } |
| 1040 return baseName; | 1020 return baseName; |
| 1041 } | 1021 } |
| 1042 | 1022 |
| 1043 //eof | 1023 //eof |
| 1044 U_NAMESPACE_END | 1024 U_NAMESPACE_END |
| OLD | NEW |