|
1 /* |
|
2 ******************************************************************************* |
|
3 * |
|
4 * Copyright (C) 1997-2013, International Business Machines |
|
5 * Corporation and others. All Rights Reserved. |
|
6 * |
|
7 ******************************************************************************* |
|
8 * file name: locavailable.cpp |
|
9 * encoding: US-ASCII |
|
10 * tab size: 8 (not used) |
|
11 * indentation:4 |
|
12 * |
|
13 * created on: 2010feb25 |
|
14 * created by: Markus W. Scherer |
|
15 * |
|
16 * Code for available locales, separated out from other .cpp files |
|
17 * that then do not depend on resource bundle code and res_index bundles. |
|
18 */ |
|
19 |
|
20 #include "unicode/utypes.h" |
|
21 #include "unicode/locid.h" |
|
22 #include "unicode/uloc.h" |
|
23 #include "unicode/ures.h" |
|
24 #include "cmemory.h" |
|
25 #include "ucln_cmn.h" |
|
26 #include "uassert.h" |
|
27 #include "umutex.h" |
|
28 #include "uresimp.h" |
|
29 |
|
30 // C++ API ----------------------------------------------------------------- *** |
|
31 |
|
32 U_NAMESPACE_BEGIN |
|
33 |
|
34 static icu::Locale* availableLocaleList = NULL; |
|
35 static int32_t availableLocaleListCount; |
|
36 static icu::UInitOnce gInitOnce = U_INITONCE_INITIALIZER; |
|
37 |
|
38 U_NAMESPACE_END |
|
39 |
|
40 U_CDECL_BEGIN |
|
41 |
|
42 static UBool U_CALLCONV locale_available_cleanup(void) |
|
43 { |
|
44 U_NAMESPACE_USE |
|
45 |
|
46 if (availableLocaleList) { |
|
47 delete []availableLocaleList; |
|
48 availableLocaleList = NULL; |
|
49 } |
|
50 availableLocaleListCount = 0; |
|
51 gInitOnce.reset(); |
|
52 |
|
53 return TRUE; |
|
54 } |
|
55 |
|
56 U_CDECL_END |
|
57 |
|
58 U_NAMESPACE_BEGIN |
|
59 |
|
60 void U_CALLCONV locale_available_init() { |
|
61 // This function is a friend of class Locale. |
|
62 // This function is only invoked via umtx_initOnce(). |
|
63 |
|
64 // for now, there is a hardcoded list, so just walk through that list and set it up. |
|
65 // Note: this function is a friend of class Locale. |
|
66 availableLocaleListCount = uloc_countAvailable(); |
|
67 if(availableLocaleListCount) { |
|
68 availableLocaleList = new Locale[availableLocaleListCount]; |
|
69 } |
|
70 if (availableLocaleList == NULL) { |
|
71 availableLocaleListCount= 0; |
|
72 } |
|
73 for (int32_t locCount=availableLocaleListCount-1; locCount>=0; --locCount) { |
|
74 availableLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount)); |
|
75 } |
|
76 ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup); |
|
77 } |
|
78 |
|
79 const Locale* U_EXPORT2 |
|
80 Locale::getAvailableLocales(int32_t& count) |
|
81 { |
|
82 umtx_initOnce(gInitOnce, &locale_available_init); |
|
83 count = availableLocaleListCount; |
|
84 return availableLocaleList; |
|
85 } |
|
86 |
|
87 |
|
88 U_NAMESPACE_END |
|
89 |
|
90 // C API ------------------------------------------------------------------- *** |
|
91 |
|
92 U_NAMESPACE_USE |
|
93 |
|
94 /* ### Constants **************************************************/ |
|
95 |
|
96 /* These strings describe the resources we attempt to load from |
|
97 the locale ResourceBundle data file.*/ |
|
98 static const char _kIndexLocaleName[] = "res_index"; |
|
99 static const char _kIndexTag[] = "InstalledLocales"; |
|
100 |
|
101 static char** _installedLocales = NULL; |
|
102 static int32_t _installedLocalesCount = 0; |
|
103 static icu::UInitOnce _installedLocalesInitOnce; |
|
104 |
|
105 /* ### Get available **************************************************/ |
|
106 |
|
107 static UBool U_CALLCONV uloc_cleanup(void) { |
|
108 char ** temp; |
|
109 |
|
110 if (_installedLocales) { |
|
111 temp = _installedLocales; |
|
112 _installedLocales = NULL; |
|
113 |
|
114 _installedLocalesCount = 0; |
|
115 _installedLocalesInitOnce.reset(); |
|
116 |
|
117 uprv_free(temp); |
|
118 } |
|
119 return TRUE; |
|
120 } |
|
121 |
|
122 // Load Installed Locales. This function will be called exactly once |
|
123 // via the initOnce mechanism. |
|
124 |
|
125 static void U_CALLCONV loadInstalledLocales() { |
|
126 UResourceBundle *indexLocale = NULL; |
|
127 UResourceBundle installed; |
|
128 UErrorCode status = U_ZERO_ERROR; |
|
129 int32_t i = 0; |
|
130 int32_t localeCount; |
|
131 |
|
132 U_ASSERT(_installedLocales == NULL); |
|
133 U_ASSERT(_installedLocalesCount == 0); |
|
134 |
|
135 _installedLocalesCount = 0; |
|
136 ures_initStackObject(&installed); |
|
137 indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status); |
|
138 ures_getByKey(indexLocale, _kIndexTag, &installed, &status); |
|
139 |
|
140 if(U_SUCCESS(status)) { |
|
141 localeCount = ures_getSize(&installed); |
|
142 _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1)); |
|
143 if (_installedLocales != NULL) { |
|
144 ures_resetIterator(&installed); |
|
145 while(ures_hasNext(&installed)) { |
|
146 ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status); |
|
147 } |
|
148 _installedLocales[i] = NULL; |
|
149 _installedLocalesCount = localeCount; |
|
150 ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); |
|
151 } |
|
152 } |
|
153 ures_close(&installed); |
|
154 ures_close(indexLocale); |
|
155 } |
|
156 |
|
157 static void _load_installedLocales() |
|
158 { |
|
159 umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales); |
|
160 } |
|
161 |
|
162 U_CAPI const char* U_EXPORT2 |
|
163 uloc_getAvailable(int32_t offset) |
|
164 { |
|
165 |
|
166 _load_installedLocales(); |
|
167 |
|
168 if (offset > _installedLocalesCount) |
|
169 return NULL; |
|
170 return _installedLocales[offset]; |
|
171 } |
|
172 |
|
173 U_CAPI int32_t U_EXPORT2 |
|
174 uloc_countAvailable() |
|
175 { |
|
176 _load_installedLocales(); |
|
177 return _installedLocalesCount; |
|
178 } |
|
179 |