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 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 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(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 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 182