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