1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 1997-2013, 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 "uassert.h" 27 #include "umutex.h" 28 #include "uresimp.h" 29 30 // C++ API ----------------------------------------------------------------- *** 31 32 U_NAMESPACE_BEGIN 33 34 static icu::Locale* availableLocaleList = NULL; 35 static int32_t availableLocaleListCount; 36 static icu::UInitOnce gInitOnce = U_INITONCE_INITIALIZER; 37 38 U_NAMESPACE_END 39 40 U_CDECL_BEGIN 41 42 static UBool U_CALLCONV locale_available_cleanup(void) 43 { 44 U_NAMESPACE_USE 45 46 if (availableLocaleList) { 47 delete []availableLocaleList; 48 availableLocaleList = NULL; 49 } 50 availableLocaleListCount = 0; 51 gInitOnce.reset(); 52 53 return TRUE; 54 } 55 56 U_CDECL_END 57 58 U_NAMESPACE_BEGIN 59 60 void U_CALLCONV locale_available_init() { 61 // This function is a friend of class Locale. 62 // This function is only invoked via umtx_initOnce(). 63 64 // for now, there is a hardcoded list, so just walk through that list and set it up. 65 // Note: this function is a friend of class Locale. 66 availableLocaleListCount = uloc_countAvailable(); 67 if(availableLocaleListCount) { 68 availableLocaleList = new Locale[availableLocaleListCount]; 69 } 70 if (availableLocaleList == NULL) { 71 availableLocaleListCount= 0; 72 } 73 for (int32_t locCount=availableLocaleListCount-1; locCount>=0; --locCount) { 74 availableLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount)); 75 } 76 ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup); 77 } 78 79 const Locale* U_EXPORT2 80 Locale::getAvailableLocales(int32_t& count) 81 { 82 umtx_initOnce(gInitOnce, &locale_available_init); 83 count = availableLocaleListCount; 84 return availableLocaleList; 85 } 86 87 88 U_NAMESPACE_END 89 90 // C API ------------------------------------------------------------------- *** 91 92 U_NAMESPACE_USE 93 94 /* ### Constants **************************************************/ 95 96 /* These strings describe the resources we attempt to load from 97 the locale ResourceBundle data file.*/ 98 static const char _kIndexLocaleName[] = "res_index"; 99 static const char _kIndexTag[] = "InstalledLocales"; 100 101 static char** _installedLocales = NULL; 102 static int32_t _installedLocalesCount = 0; 103 static icu::UInitOnce _installedLocalesInitOnce; 104 105 /* ### Get available **************************************************/ 106 107 static UBool U_CALLCONV uloc_cleanup(void) { 108 char ** temp; 109 110 if (_installedLocales) { 111 temp = _installedLocales; 112 _installedLocales = NULL; 113 114 _installedLocalesCount = 0; 115 _installedLocalesInitOnce.reset(); 116 117 uprv_free(temp); 118 } 119 return TRUE; 120 } 121 122 // Load Installed Locales. This function will be called exactly once 123 // via the initOnce mechanism. 124 125 static void U_CALLCONV loadInstalledLocales() { 126 UResourceBundle *indexLocale = NULL; 127 UResourceBundle installed; 128 UErrorCode status = U_ZERO_ERROR; 129 int32_t i = 0; 130 int32_t localeCount; 131 132 U_ASSERT(_installedLocales == NULL); 133 U_ASSERT(_installedLocalesCount == 0); 134 135 _installedLocalesCount = 0; 136 ures_initStackObject(&installed); 137 indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status); 138 ures_getByKey(indexLocale, _kIndexTag, &installed, &status); 139 140 if(U_SUCCESS(status)) { 141 localeCount = ures_getSize(&installed); 142 _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1)); 143 if (_installedLocales != NULL) { 144 ures_resetIterator(&installed); 145 while(ures_hasNext(&installed)) { 146 ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status); 147 } 148 _installedLocales[i] = NULL; 149 _installedLocalesCount = localeCount; 150 ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); 151 } 152 } 153 ures_close(&installed); 154 ures_close(indexLocale); 155 } 156 157 static void _load_installedLocales() 158 { 159 umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales); 160 } 161 162 U_CAPI const char* U_EXPORT2 163 uloc_getAvailable(int32_t offset) 164 { 165 166 _load_installedLocales(); 167 168 if (offset > _installedLocalesCount) 169 return NULL; 170 return _installedLocales[offset]; 171 } 172 173 U_CAPI int32_t U_EXPORT2 174 uloc_countAvailable() 175 { 176 _load_installedLocales(); 177 return _installedLocalesCount; 178 } 179 180