Home | History | Annotate | Download | only in common
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 1997-2010, 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 "umutex.h"
     27 #include "uresimp.h"
     28 
     29 // C++ API ----------------------------------------------------------------- ***
     30 
     31 static U_NAMESPACE_QUALIFIER Locale*  availableLocaleList = NULL;
     32 static int32_t  availableLocaleListCount;
     33 
     34 U_CDECL_BEGIN
     35 
     36 static UBool U_CALLCONV locale_available_cleanup(void)
     37 {
     38     U_NAMESPACE_USE
     39 
     40     if (availableLocaleList) {
     41         delete []availableLocaleList;
     42         availableLocaleList = NULL;
     43     }
     44     availableLocaleListCount = 0;
     45 
     46     return TRUE;
     47 }
     48 
     49 U_CDECL_END
     50 
     51 U_NAMESPACE_BEGIN
     52 
     53 const Locale* U_EXPORT2
     54 Locale::getAvailableLocales(int32_t& count)
     55 {
     56     // for now, there is a hardcoded list, so just walk through that list and set it up.
     57     UBool needInit;
     58     UMTX_CHECK(NULL, availableLocaleList == NULL, needInit);
     59 
     60     if (needInit) {
     61         int32_t locCount = uloc_countAvailable();
     62         Locale *newLocaleList = 0;
     63         if(locCount) {
     64            newLocaleList = new Locale[locCount];
     65         }
     66         if (newLocaleList == NULL) {
     67             count = 0;
     68             return NULL;
     69         }
     70 
     71         count = locCount;
     72 
     73         while(--locCount >= 0) {
     74             newLocaleList[locCount].setFromPOSIXID(uloc_getAvailable(locCount));
     75         }
     76 
     77         umtx_lock(NULL);
     78         if(availableLocaleList == 0) {
     79             availableLocaleListCount = count;
     80             availableLocaleList = newLocaleList;
     81             newLocaleList = NULL;
     82             ucln_common_registerCleanup(UCLN_COMMON_LOCALE_AVAILABLE, locale_available_cleanup);
     83         }
     84         umtx_unlock(NULL);
     85         delete []newLocaleList;
     86     }
     87     count = availableLocaleListCount;
     88     return availableLocaleList;
     89 }
     90 
     91 
     92 U_NAMESPACE_END
     93 
     94 // C API ------------------------------------------------------------------- ***
     95 
     96 U_NAMESPACE_USE
     97 
     98 /* ### Constants **************************************************/
     99 
    100 /* These strings describe the resources we attempt to load from
    101  the locale ResourceBundle data file.*/
    102 static const char _kIndexLocaleName[] = "res_index";
    103 static const char _kIndexTag[]        = "InstalledLocales";
    104 
    105 static char** _installedLocales = NULL;
    106 static int32_t _installedLocalesCount = 0;
    107 
    108 /* ### Get available **************************************************/
    109 
    110 static UBool U_CALLCONV uloc_cleanup(void) {
    111     char ** temp;
    112 
    113     if (_installedLocales) {
    114         temp = _installedLocales;
    115         _installedLocales = NULL;
    116 
    117         _installedLocalesCount = 0;
    118 
    119         uprv_free(temp);
    120     }
    121     return TRUE;
    122 }
    123 
    124 static void _load_installedLocales()
    125 {
    126     UBool   localesLoaded;
    127 
    128     UMTX_CHECK(NULL, _installedLocales != NULL, localesLoaded);
    129 
    130     if (localesLoaded == FALSE) {
    131         UResourceBundle *indexLocale = NULL;
    132         UResourceBundle installed;
    133         UErrorCode status = U_ZERO_ERROR;
    134         char ** temp;
    135         int32_t i = 0;
    136         int32_t localeCount;
    137 
    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             temp = (char **) uprv_malloc(sizeof(char*) * (localeCount+1));
    145             /* Check for null pointer */
    146             if (temp != NULL) {
    147                 ures_resetIterator(&installed);
    148                 while(ures_hasNext(&installed)) {
    149                     ures_getNextString(&installed, NULL, (const char **)&temp[i++], &status);
    150                 }
    151                 temp[i] = NULL;
    152 
    153                 umtx_lock(NULL);
    154                 if (_installedLocales == NULL)
    155                 {
    156                     _installedLocalesCount = localeCount;
    157                     _installedLocales = temp;
    158                     temp = NULL;
    159                     ucln_common_registerCleanup(UCLN_COMMON_ULOC, uloc_cleanup);
    160                 }
    161                 umtx_unlock(NULL);
    162 
    163                 uprv_free(temp);
    164             }
    165         }
    166         ures_close(&installed);
    167         ures_close(indexLocale);
    168     }
    169 }
    170 
    171 U_CAPI const char* U_EXPORT2
    172 uloc_getAvailable(int32_t offset)
    173 {
    174 
    175     _load_installedLocales();
    176 
    177     if (offset > _installedLocalesCount)
    178         return NULL;
    179     return _installedLocales[offset];
    180 }
    181 
    182 U_CAPI int32_t  U_EXPORT2
    183 uloc_countAvailable()
    184 {
    185     _load_installedLocales();
    186     return _installedLocalesCount;
    187 }
    188