Imported Upstream version 58.1
[platform/upstream/icu.git] / source / common / locavailable.cpp
1 // Copyright (C) 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:   US-ASCII
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 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     gInitOnce.reset();
54
55     return TRUE;
56 }
57
58 U_CDECL_END
59
60 U_NAMESPACE_BEGIN
61
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
82 Locale::getAvailableLocales(int32_t& count)
83 {
84     umtx_initOnce(gInitOnce, &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
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
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
159 static void _load_installedLocales()
160 {
161     umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales);
162 }
163
164 U_CAPI const char* U_EXPORT2
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
176 uloc_countAvailable()
177 {
178     _load_installedLocales();
179     return _installedLocalesCount;
180 }
181