• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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