Home | History | Annotate | Download | only in common
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 *
      6 *   Copyright (C) 1997-2013, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 *******************************************************************************
     10 *   file name:  locavailable.cpp
     11 *   encoding:   UTF-8
     12 *   tab size:   8 (not used)
     13 *   indentation:4
     14 *
     15 *   created on: 2010feb25
     16 *   created by: Markus W. Scherer
     17 *
     18 *   Code for available locales, separated out from other .cpp files
     19 *   that then do not depend on resource bundle code and res_index bundles.
     20 */
     21 
     22 #include "unicode/utypes.h"
     23 #include "unicode/locid.h"
     24 #include "unicode/uloc.h"
     25 #include "unicode/ures.h"
     26 #include "cmemory.h"
     27 #include "ucln_cmn.h"
     28 #include "uassert.h"
     29 #include "umutex.h"
     30 #include "uresimp.h"
     31 
     32 // C++ API ----------------------------------------------------------------- ***
     33 
     34 U_NAMESPACE_BEGIN
     35 
     36 static icu::Locale*  availableLocaleList = NULL;
     37 static int32_t  availableLocaleListCount;
     38 static icu::UInitOnce gInitOnceLocale = U_INITONCE_INITIALIZER;
     39 
     40 U_NAMESPACE_END
     41 
     42 U_CDECL_BEGIN
     43 
     44 static UBool U_CALLCONV locale_available_cleanup(void)
     45 {
     46     U_NAMESPACE_USE
     47 
     48     if (availableLocaleList) {
     49         delete []availableLocaleList;
     50         availableLocaleList = NULL;
     51     }
     52     availableLocaleListCount = 0;
     53     gInitOnceLocale.reset();
     54 
     55     return TRUE;
     56 }
     57 
     58 U_CDECL_END
     59 
     60 U_NAMESPACE_BEGIN
     61 
     62 void U_CALLCONV locale_available_init() {
     63     // This function is a friend of class Locale.
     64     // This function is only invoked via umtx_initOnce().
     65 
     66     // for now, there is a hardcoded list, so just walk through that list and set it up.
     67     //  Note: this function is a friend of class Locale.
     68     availableLocaleListCount = uloc_countAvailable();
     69     if(availableLocaleListCount) {
     70        availableLocaleList = new Locale[availableLocaleListCount];
     71     }
     72     if (availableLocaleList == NULL) {
     73         availableLocaleListCount= 0;
     74     }
     75     for (int32_t locCount=availableLocaleListCount-1; locCount>=0; --locCount) {
     76         availableLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
     77     }
     78     ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup);
     79 }
     80 
     81 const Locale* U_EXPORT2
     82 Locale::getAvailableLocales(int32_t& count)
     83 {
     84     umtx_initOnce(gInitOnceLocale, &locale_available_init);
     85     count = availableLocaleListCount;
     86     return availableLocaleList;
     87 }
     88 
     89 
     90 U_NAMESPACE_END
     91 
     92 // C API ------------------------------------------------------------------- ***
     93 
     94 U_NAMESPACE_USE
     95 
     96 /* ### Constants **************************************************/
     97 
     98 /* These strings describe the resources we attempt to load from
     99  the locale ResourceBundle data file.*/
    100 static const char _kIndexLocaleName[] = "res_index";
    101 static const char _kIndexTag[]        = "InstalledLocales";
    102 
    103 static char** _installedLocales = NULL;
    104 static int32_t _installedLocalesCount = 0;
    105 static icu::UInitOnce _installedLocalesInitOnce;
    106 
    107 /* ### Get available **************************************************/
    108 
    109 static UBool U_CALLCONV uloc_cleanup(void) {
    110     char ** temp;
    111 
    112     if (_installedLocales) {
    113         temp = _installedLocales;
    114         _installedLocales = NULL;
    115 
    116         _installedLocalesCount = 0;
    117         _installedLocalesInitOnce.reset();
    118 
    119         uprv_free(temp);
    120     }
    121     return TRUE;
    122 }
    123 
    124 // Load Installed Locales. This function will be called exactly once
    125 //   via the initOnce mechanism.
    126 
    127 static void U_CALLCONV loadInstalledLocales() {
    128     UResourceBundle *indexLocale = NULL;
    129     UResourceBundle installed;
    130     UErrorCode status = U_ZERO_ERROR;
    131     int32_t i = 0;
    132     int32_t localeCount;
    133 
    134     U_ASSERT(_installedLocales == NULL);
    135     U_ASSERT(_installedLocalesCount == 0);
    136 
    137     _installedLocalesCount = 0;
    138     ures_initStackObject(&installed);
    139     indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status);
    140     ures_getByKey(indexLocale, _kIndexTag, &installed, &status);
    141 
    142     if(U_SUCCESS(status)) {
    143         localeCount = ures_getSize(&installed);
    144         _installedLocales = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
    145         if (_installedLocales != NULL) {
    146             ures_resetIterator(&installed);
    147             while(ures_hasNext(&installed)) {
    148                 ures_getNextString(&installed, NULL, (const char **)&_installedLocales[i++], &status);
    149             }
    150             _installedLocales[i] = NULL;
    151             _installedLocalesCount = localeCount;
    152             ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
    153         }
    154     }
    155     ures_close(&installed);
    156     ures_close(indexLocale);
    157 }
    158 
    159 static void _load_installedLocales()
    160 {
    161     umtx_initOnce(_installedLocalesInitOnce, &loadInstalledLocales);
    162 }
    163 
    164 U_CAPI const char* U_EXPORT2
    165 uloc_getAvailable(int32_t offset)
    166 {
    167 
    168     _load_installedLocales();
    169 
    170     if (offset > _installedLocalesCount)
    171         return NULL;
    172     return _installedLocales[offset];
    173 }
    174 
    175 U_CAPI int32_t  U_EXPORT2
    176 uloc_countAvailable()
    177 {
    178     _load_installedLocales();
    179     return _installedLocalesCount;
    180 }
    181 
    182