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