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