16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 1997-2013, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  locavailable.cpp
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 2010feb25
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Code for available locales, separated out from other .cpp files
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   that then do not depend on resource bundle code and res_index bundles.
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/locid.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uloc.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ures.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucln_cmn.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "umutex.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uresimp.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// C++ API ----------------------------------------------------------------- ***
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic icu::Locale*  availableLocaleList = NULL;
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t  availableLocaleListCount;
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic icu::UInitOnce gInitOnce = U_INITONCE_INITIALIZER;
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CDECL_BEGIN
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV locale_available_cleanup(void)
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_NAMESPACE_USE
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (availableLocaleList) {
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete []availableLocaleList;
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        availableLocaleList = NULL;
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    availableLocaleListCount = 0;
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    gInitOnce.reset();
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CDECL_END
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid U_CALLCONV locale_available_init() {
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // This function is a friend of class Locale.
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // This function is only invoked via umtx_initOnce().
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // for now, there is a hardcoded list, so just walk through that list and set it up.
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    //  Note: this function is a friend of class Locale.
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    availableLocaleListCount = uloc_countAvailable();
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(availableLocaleListCount) {
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org       availableLocaleList = new Locale[availableLocaleListCount];
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (availableLocaleList == NULL) {
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        availableLocaleListCount= 0;
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (int32_t locCount=availableLocaleListCount-1; locCount>=0; --locCount) {
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        availableLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup);
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst Locale* U_EXPORT2
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocale::getAvailableLocales(int32_t& count)
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    umtx_initOnce(gInitOnce, &locale_available_init);
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    count = availableLocaleListCount;
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return availableLocaleList;
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// C API ------------------------------------------------------------------- ***
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_USE
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ### Constants **************************************************/
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* These strings describe the resources we attempt to load from
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org the locale ResourceBundle data file.*/
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char _kIndexLocaleName[] = "res_index";
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char _kIndexTag[]        = "InstalledLocales";
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic char** _installedLocales = NULL;
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t _installedLocalesCount = 0;
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic icu::UInitOnce _installedLocalesInitOnce;
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* ### Get available **************************************************/
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV uloc_cleanup(void) {
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char ** temp;
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (_installedLocales) {
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        temp = _installedLocales;
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        _installedLocales = NULL;
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        _installedLocalesCount = 0;
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        _installedLocalesInitOnce.reset();
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(temp);
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return TRUE;
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Load Installed Locales. This function will be called exactly once
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//   via the initOnce mechanism.
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void U_CALLCONV loadInstalledLocales() {
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UResourceBundle *indexLocale = NULL;
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UResourceBundle installed;
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode status = U_ZERO_ERROR;
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t i = 0;
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t localeCount;
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(_installedLocales == NULL);
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(_installedLocalesCount == 0);
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _installedLocalesCount = 0;
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ures_initStackObject(&installed);
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status);
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ures_getByKey(indexLocale, _kIndexTag, &installed, &status);
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_SUCCESS(status)) {
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        localeCount = ures_getSize(&installed);
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (_installedLocales != NULL) {
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ures_resetIterator(&installed);
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while(ures_hasNext(&installed)) {
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status);
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            _installedLocales[i] = NULL;
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            _installedLocalesCount = localeCount;
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ures_close(&installed);
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ures_close(indexLocale);
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void _load_installedLocales()
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales);
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const char* U_EXPORT2
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguloc_getAvailable(int32_t offset)
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _load_installedLocales();
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (offset > _installedLocalesCount)
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return _installedLocales[offset];
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t  U_EXPORT2
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguloc_countAvailable()
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    _load_installedLocales();
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return _installedLocalesCount;
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
180