Line data Source code
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 gInitOnce = U_INITONCE_INITIALIZER;
39 :
40 : U_NAMESPACE_END
41 :
42 : U_CDECL_BEGIN
43 :
44 0 : static UBool U_CALLCONV locale_available_cleanup(void)
45 : {
46 : U_NAMESPACE_USE
47 :
48 0 : if (availableLocaleList) {
49 0 : delete []availableLocaleList;
50 0 : availableLocaleList = NULL;
51 : }
52 0 : availableLocaleListCount = 0;
53 0 : gInitOnce.reset();
54 :
55 0 : return TRUE;
56 : }
57 :
58 : U_CDECL_END
59 :
60 : U_NAMESPACE_BEGIN
61 :
62 0 : 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 0 : availableLocaleListCount = uloc_countAvailable();
69 0 : if(availableLocaleListCount) {
70 0 : availableLocaleList = new Locale[availableLocaleListCount];
71 : }
72 0 : if (availableLocaleList == NULL) {
73 0 : availableLocaleListCount= 0;
74 : }
75 0 : for (int32_t locCount=availableLocaleListCount-1; locCount>=0; --locCount) {
76 0 : availableLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
77 : }
78 0 : ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup);
79 0 : }
80 :
81 : const Locale* U_EXPORT2
82 0 : Locale::getAvailableLocales(int32_t& count)
83 : {
84 0 : umtx_initOnce(gInitOnce, &locale_available_init);
85 0 : count = availableLocaleListCount;
86 0 : 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 :
109 0 : static UBool U_CALLCONV uloc_cleanup(void) {
110 : char ** temp;
111 :
112 0 : if (_installedLocales) {
113 0 : temp = _installedLocales;
114 0 : _installedLocales = NULL;
115 :
116 0 : _installedLocalesCount = 0;
117 0 : _installedLocalesInitOnce.reset();
118 :
119 0 : uprv_free(temp);
120 : }
121 0 : return TRUE;
122 : }
123 :
124 : // Load Installed Locales. This function will be called exactly once
125 : // via the initOnce mechanism.
126 :
127 0 : static void U_CALLCONV loadInstalledLocales() {
128 0 : UResourceBundle *indexLocale = NULL;
129 : UResourceBundle installed;
130 0 : UErrorCode status = U_ZERO_ERROR;
131 0 : int32_t i = 0;
132 : int32_t localeCount;
133 :
134 0 : U_ASSERT(_installedLocales == NULL);
135 0 : U_ASSERT(_installedLocalesCount == 0);
136 :
137 0 : _installedLocalesCount = 0;
138 0 : ures_initStackObject(&installed);
139 0 : indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status);
140 0 : ures_getByKey(indexLocale, _kIndexTag, &installed, &status);
141 :
142 0 : if(U_SUCCESS(status)) {
143 0 : localeCount = ures_getSize(&installed);
144 0 : _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
145 0 : if (_installedLocales != NULL) {
146 0 : ures_resetIterator(&installed);
147 0 : while(ures_hasNext(&installed)) {
148 0 : ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status);
149 : }
150 0 : _installedLocales[i] = NULL;
151 0 : _installedLocalesCount = localeCount;
152 0 : ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
153 : }
154 : }
155 0 : ures_close(&installed);
156 0 : ures_close(indexLocale);
157 0 : }
158 :
159 0 : static void _load_installedLocales()
160 : {
161 0 : umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales);
162 0 : }
163 :
164 : U_CAPI const char* U_EXPORT2
165 0 : uloc_getAvailable(int32_t offset)
166 : {
167 :
168 0 : _load_installedLocales();
169 :
170 0 : if (offset > _installedLocalesCount)
171 0 : return NULL;
172 0 : return _installedLocales[offset];
173 : }
174 :
175 : U_CAPI int32_t U_EXPORT2
176 0 : uloc_countAvailable()
177 : {
178 0 : _load_installedLocales();
179 0 : return _installedLocalesCount;
180 : }
181 :
|