1 /*
2 *******************************************************************************
3 *
4 * Copyright (C) 1997-2010, 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 "umutex.h"
27 #include "uresimp.h"
28
29 // C++ API ----------------------------------------------------------------- ***
30
31 static U_NAMESPACE_QUALIFIER Locale* availableLocaleList = NULL;
32 static int32_t availableLocaleListCount;
33
34 U_CDECL_BEGIN
35
locale_available_cleanup(void)36 static UBool U_CALLCONV locale_available_cleanup(void)
37 {
38 U_NAMESPACE_USE
39
40 if (availableLocaleList) {
41 delete []availableLocaleList;
42 availableLocaleList = NULL;
43 }
44 availableLocaleListCount = 0;
45
46 return TRUE;
47 }
48
49 U_CDECL_END
50
51 U_NAMESPACE_BEGIN
52
53 const Locale* U_EXPORT2
getAvailableLocales(int32_t & count)54 Locale::getAvailableLocales(int32_t& count)
55 {
56 // for now, there is a hardcoded list, so just walk through that list and set it up.
57 UBool needInit;
58 UMTX_CHECK(NULL, availableLocaleList == NULL, needInit);
59
60 if (needInit) {
61 int32_t locCount = uloc_countAvailable();
62 Locale *newLocaleList = 0;
63 if(locCount) {
64 newLocaleList = new Locale[locCount];
65 }
66 if (newLocaleList == NULL) {
67 count = 0;
68 return NULL;
69 }
70
71 count = locCount;
72
73 while(--locCount >= 0) {
74 newLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
75 }
76
77 umtx_lock(NULL);
78 if(availableLocaleList == 0) {
79 availableLocaleListCount = count;
80 availableLocaleList = newLocaleList;
81 newLocaleList = NULL;
82 ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup);
83 }
84 umtx_unlock(NULL);
85 delete []newLocaleList;
86 }
87 count = availableLocaleListCount;
88 return availableLocaleList;
89 }
90
91
92 U_NAMESPACE_END
93
94 // C API ------------------------------------------------------------------- ***
95
96 U_NAMESPACE_USE
97
98 /* ### Constants **************************************************/
99
100 /* These strings describe the resources we attempt to load from
101 the locale ResourceBundle data file.*/
102 static const char _kIndexLocaleName[] = "res_index";
103 static const char _kIndexTag[] = "InstalledLocales";
104
105 static char** _installedLocales = NULL;
106 static int32_t _installedLocalesCount = 0;
107
108 /* ### Get available **************************************************/
109
uloc_cleanup(void)110 static UBool U_CALLCONV uloc_cleanup(void) {
111 char ** temp;
112
113 if (_installedLocales) {
114 temp = _installedLocales;
115 _installedLocales = NULL;
116
117 _installedLocalesCount = 0;
118
119 uprv_free(temp);
120 }
121 return TRUE;
122 }
123
_load_installedLocales()124 static void _load_installedLocales()
125 {
126 UBool localesLoaded;
127
128 UMTX_CHECK(NULL, _installedLocales != NULL, localesLoaded);
129
130 if (localesLoaded == FALSE) {
131 UResourceBundle *indexLocale = NULL;
132 UResourceBundle installed;
133 UErrorCode status = U_ZERO_ERROR;
134 char ** temp;
135 int32_t i = 0;
136 int32_t localeCount;
137
138 ures_initStackObject(&installed);
139 indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status);
140 ures_getByKey(indexLocale, _kIndexTag, &installed, &status);
141
142 if(U_SUCCESS(status)) {
143 localeCount = ures_getSize(&installed);
144 temp = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
145 /* Check for null pointer */
146 if (temp != NULL) {
147 ures_resetIterator(&installed);
148 while(ures_hasNext(&installed)) {
149 ures_getNextString(&installed, NULL, (const char **)&temp[i++], &status);
150 }
151 temp[i] = NULL;
152
153 umtx_lock(NULL);
154 if (_installedLocales == NULL)
155 {
156 _installedLocalesCount = localeCount;
157 _installedLocales = temp;
158 temp = NULL;
159 ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
160 }
161 umtx_unlock(NULL);
162
163 uprv_free(temp);
164 }
165 }
166 ures_close(&installed);
167 ures_close(indexLocale);
168 }
169 }
170
171 U_CAPI const char* U_EXPORT2
uloc_getAvailable(int32_t offset)172 uloc_getAvailable(int32_t offset)
173 {
174
175 _load_installedLocales();
176
177 if (offset > _installedLocalesCount)
178 return NULL;
179 return _installedLocales[offset];
180 }
181
182 U_CAPI int32_t U_EXPORT2
uloc_countAvailable()183 uloc_countAvailable()
184 {
185 _load_installedLocales();
186 return _installedLocalesCount;
187 }
188