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 32U_NAMESPACE_BEGIN 33 34static icu::Locale* availableLocaleList = NULL; 35static int32_t availableLocaleListCount; 36static icu::UInitOnce gInitOnce = U_INITONCE_INITIALIZER; 37 38U_NAMESPACE_END 39 40U_CDECL_BEGIN 41 42static 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 56U_CDECL_END 57 58U_NAMESPACE_BEGIN 59 60void 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 79const Locale* U_EXPORT2 80Locale::getAvailableLocales(int32_t& count) 81{ 82 umtx_initOnce(gInitOnce, &locale_available_init); 83 count = availableLocaleListCount; 84 return availableLocaleList; 85} 86 87 88U_NAMESPACE_END 89 90// C API ------------------------------------------------------------------- *** 91 92U_NAMESPACE_USE 93 94/* ### Constants **************************************************/ 95 96/* These strings describe the resources we attempt to load from 97 the locale ResourceBundle data file.*/ 98static const char _kIndexLocaleName[] = "res_index"; 99static const char _kIndexTag[] = "InstalledLocales"; 100 101static char** _installedLocales = NULL; 102static int32_t _installedLocalesCount = 0; 103static icu::UInitOnce _installedLocalesInitOnce; 104 105/* ### Get available **************************************************/ 106 107static 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 125static 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 157static void _load_installedLocales() 158{ 159 umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales); 160} 161 162U_CAPI const char* U_EXPORT2 163uloc_getAvailable(int32_t offset) 164{ 165 166 _load_installedLocales(); 167 168 if (offset > _installedLocalesCount) 169 return NULL; 170 return _installedLocales[offset]; 171} 172 173U_CAPI int32_t U_EXPORT2 174uloc_countAvailable() 175{ 176 _load_installedLocales(); 177 return _installedLocalesCount; 178} 179 180