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 |