michael@0: /* michael@0: ******************************************************************************* michael@0: * michael@0: * Copyright (C) 1997-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ******************************************************************************* michael@0: * file name: locavailable.cpp michael@0: * encoding: US-ASCII michael@0: * tab size: 8 (not used) michael@0: * indentation:4 michael@0: * michael@0: * created on: 2010feb25 michael@0: * created by: Markus W. Scherer michael@0: * michael@0: * Code for available locales, separated out from other .cpp files michael@0: * that then do not depend on resource bundle code and res_index bundles. michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: #include "unicode/locid.h" michael@0: #include "unicode/uloc.h" michael@0: #include "unicode/ures.h" michael@0: #include "cmemory.h" michael@0: #include "ucln_cmn.h" michael@0: #include "uassert.h" michael@0: #include "umutex.h" michael@0: #include "uresimp.h" michael@0: michael@0: // C++ API ----------------------------------------------------------------- *** michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: static icu::Locale* availableLocaleList = NULL; michael@0: static int32_t availableLocaleListCount; michael@0: static icu::UInitOnce gInitOnce = U_INITONCE_INITIALIZER; michael@0: michael@0: U_NAMESPACE_END michael@0: michael@0: U_CDECL_BEGIN michael@0: michael@0: static UBool U_CALLCONV locale_available_cleanup(void) michael@0: { michael@0: U_NAMESPACE_USE michael@0: michael@0: if (availableLocaleList) { michael@0: delete []availableLocaleList; michael@0: availableLocaleList = NULL; michael@0: } michael@0: availableLocaleListCount = 0; michael@0: gInitOnce.reset(); michael@0: michael@0: return TRUE; michael@0: } michael@0: michael@0: U_CDECL_END michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: void U_CALLCONV locale_available_init() { michael@0: // This function is a friend of class Locale. michael@0: // This function is only invoked via umtx_initOnce(). michael@0: michael@0: // for now, there is a hardcoded list, so just walk through that list and set it up. michael@0: // Note: this function is a friend of class Locale. michael@0: availableLocaleListCount = uloc_countAvailable(); michael@0: if(availableLocaleListCount) { michael@0: availableLocaleList = new Locale[availableLocaleListCount]; michael@0: } michael@0: if (availableLocaleList == NULL) { michael@0: availableLocaleListCount= 0; michael@0: } michael@0: for (int32_t locCount=availableLocaleListCount-1; locCount>=0; --locCount) { michael@0: availableLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount)); michael@0: } michael@0: ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup); michael@0: } michael@0: michael@0: const Locale* U_EXPORT2 michael@0: Locale::getAvailableLocales(int32_t& count) michael@0: { michael@0: umtx_initOnce(gInitOnce, &locale_available_init); michael@0: count = availableLocaleListCount; michael@0: return availableLocaleList; michael@0: } michael@0: michael@0: michael@0: U_NAMESPACE_END michael@0: michael@0: // C API ------------------------------------------------------------------- *** michael@0: michael@0: U_NAMESPACE_USE michael@0: michael@0: /* ### Constants **************************************************/ michael@0: michael@0: /* These strings describe the resources we attempt to load from michael@0: the locale ResourceBundle data file.*/ michael@0: static const char _kIndexLocaleName[] = "res_index"; michael@0: static const char _kIndexTag[] = "InstalledLocales"; michael@0: michael@0: static char** _installedLocales = NULL; michael@0: static int32_t _installedLocalesCount = 0; michael@0: static icu::UInitOnce _installedLocalesInitOnce; michael@0: michael@0: /* ### Get available **************************************************/ michael@0: michael@0: static UBool U_CALLCONV uloc_cleanup(void) { michael@0: char ** temp; michael@0: michael@0: if (_installedLocales) { michael@0: temp = _installedLocales; michael@0: _installedLocales = NULL; michael@0: michael@0: _installedLocalesCount = 0; michael@0: _installedLocalesInitOnce.reset(); michael@0: michael@0: uprv_free(temp); michael@0: } michael@0: return TRUE; michael@0: } michael@0: michael@0: // Load Installed Locales. This function will be called exactly once michael@0: // via the initOnce mechanism. michael@0: michael@0: static void U_CALLCONV loadInstalledLocales() { michael@0: UResourceBundle *indexLocale = NULL; michael@0: UResourceBundle installed; michael@0: UErrorCode status = U_ZERO_ERROR; michael@0: int32_t i = 0; michael@0: int32_t localeCount; michael@0: michael@0: U_ASSERT(_installedLocales == NULL); michael@0: U_ASSERT(_installedLocalesCount == 0); michael@0: michael@0: _installedLocalesCount = 0; michael@0: ures_initStackObject(&installed); michael@0: indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status); michael@0: ures_getByKey(indexLocale, _kIndexTag, &installed, &status); michael@0: michael@0: if(U_SUCCESS(status)) { michael@0: localeCount = ures_getSize(&installed); michael@0: _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1)); michael@0: if (_installedLocales != NULL) { michael@0: ures_resetIterator(&installed); michael@0: while(ures_hasNext(&installed)) { michael@0: ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status); michael@0: } michael@0: _installedLocales[i] = NULL; michael@0: _installedLocalesCount = localeCount; michael@0: ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup); michael@0: } michael@0: } michael@0: ures_close(&installed); michael@0: ures_close(indexLocale); michael@0: } michael@0: michael@0: static void _load_installedLocales() michael@0: { michael@0: umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales); michael@0: } michael@0: michael@0: U_CAPI const char* U_EXPORT2 michael@0: uloc_getAvailable(int32_t offset) michael@0: { michael@0: michael@0: _load_installedLocales(); michael@0: michael@0: if (offset > _installedLocalesCount) michael@0: return NULL; michael@0: return _installedLocales[offset]; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: uloc_countAvailable() michael@0: { michael@0: _load_installedLocales(); michael@0: return _installedLocalesCount; michael@0: } michael@0: