#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"
U_NAMESPACE_BEGIN
static icu::Locale* availableLocaleList = NULL;
static int32_t availableLocaleListCount;
static icu::UInitOnce gInitOnce = 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;
gInitOnce.reset();
return TRUE;
}
U_CDECL_END
U_NAMESPACE_BEGIN
void U_CALLCONV locale_available_init() {
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(gInitOnce, &locale_available_init);
count = availableLocaleListCount;
return availableLocaleList;
}
U_NAMESPACE_END
U_NAMESPACE_USE
static const char _kIndexLocaleName[] = "res_index";
static const char _kIndexTag[] = "InstalledLocales";
static char** _installedLocales = NULL;
static int32_t _installedLocalesCount = 0;
static icu::UInitOnce _installedLocalesInitOnce;
static UBool U_CALLCONV uloc_cleanup(void) {
char ** temp;
if (_installedLocales) {
temp = _installedLocales;
_installedLocales = NULL;
_installedLocalesCount = 0;
_installedLocalesInitOnce.reset();
uprv_free(temp);
}
return TRUE;
}
static void U_CALLCONV loadInstalledLocales() {
UResourceBundle *indexLocale = NULL;
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);
indexLocale = ures_openDirect(NULL, _kIndexLocaleName, &status);
ures_getByKey(indexLocale, _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);
}
}
ures_close(&installed);
ures_close(indexLocale);
}
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;
}