summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/common/locavailable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/icu/source/common/locavailable.cpp')
-rw-r--r--intl/icu/source/common/locavailable.cpp181
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;
+}
+