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