91d38d14e8
Doing this consistently first will make it easier to then clean up resource management and error handling later.
184 lines
5.1 KiB
C++
184 lines
5.1 KiB
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: UTF-8
|
|
* 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 gInitOnceLocale = 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;
|
|
gInitOnceLocale.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(gInitOnceLocale, &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 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);
|
|
|
|
icu::LocalUResourceBundlePointer indexLocale(ures_openDirect(NULL, _kIndexLocaleName, &status));
|
|
|
|
// Automatically call ures_close() on this when it goes out of scope.
|
|
icu::LocalUResourceBundlePointer installedCloser(&installed);
|
|
|
|
ures_getByKey(indexLocale.getAlias(), _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);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|