ICU-5440 Return the correct list of supported locales for collation.

X-SVN-Rev: 20484
This commit is contained in:
George Rhoten 2006-10-04 06:05:30 +00:00
parent c5406f3b0c
commit ef584abc21
2 changed files with 143 additions and 13 deletions

View file

@ -44,30 +44,40 @@
#include "unicode/coll.h"
#include "unicode/tblcoll.h"
#include "ucol_imp.h"
#include "cstring.h"
#include "cmemory.h"
#include "umutex.h"
#include "servloc.h"
#include "ustrenum.h"
#include "ucln_in.h"
U_NAMESPACE_BEGIN
#if !UCONFIG_NO_SERVICE
U_NAMESPACE_END
static U_NAMESPACE_QUALIFIER Locale* availableLocaleList = NULL;
static int32_t availableLocaleListCount;
static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL;
/**
* Release all static memory held by collator.
*/
U_CDECL_BEGIN
static UBool U_CALLCONV collator_cleanup(void) {
#if !UCONFIG_NO_SERVICE
if (gService) {
delete gService;
gService = NULL;
}
#endif
if (availableLocaleList) {
delete []availableLocaleList;
availableLocaleList = NULL;
}
availableLocaleListCount = 0;
return TRUE;
}
U_CDECL_END
#if !UCONFIG_NO_SERVICE
U_NAMESPACE_BEGIN
// ------------------------------------------
@ -178,8 +188,6 @@ public:
// -------------------------------------
class ICUCollatorService;
static ICULocaleService*
getService(void)
{
@ -199,9 +207,7 @@ getService(void)
delete newservice;
}
else {
#if !UCONFIG_NO_SERVICE
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
#endif
}
}
return gService;
@ -242,6 +248,57 @@ Collator::createUCollator(const char *loc,
}
#endif /* UCONFIG_NO_SERVICE */
static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
// for now, there is a hardcoded list, so just walk through that list and set it up.
UBool needInit;
UMTX_CHECK(NULL, availableLocaleList == NULL, needInit);
if (needInit) {
UResourceBundle *index = NULL;
UResourceBundle installed;
Locale * temp;
int32_t i = 0;
int32_t localeCount;
ures_initStackObject(&installed);
index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
ures_getByKey(index, "InstalledLocales", &installed, &status);
if(U_SUCCESS(status)) {
localeCount = ures_getSize(&installed);
temp = new Locale[localeCount];
if (temp != NULL) {
ures_resetIterator(&installed);
while(ures_hasNext(&installed)) {
const char *tempKey = NULL;
ures_getNextString(&installed, NULL, &tempKey, &status);
temp[i++] = Locale(tempKey);
}
umtx_lock(NULL);
if (availableLocaleList == NULL)
{
availableLocaleList = temp;
availableLocaleListCount = localeCount;
temp = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
}
umtx_unlock(NULL);
needInit = FALSE;
if (temp) {
delete []temp;
}
}
ures_close(&installed);
}
ures_close(index);
}
return !needInit;
}
// Collator public methods -----------------------------------------------
Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success)
@ -396,7 +453,15 @@ UBool Collator::greater(const UnicodeString& source,
// array of indefinite lifetime
const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count)
{
return Locale::getAvailableLocales(count);
UErrorCode status = U_ZERO_ERROR;
Locale *result = NULL;
count = 0;
if (isAvailableLocaleListInitialized(status))
{
result = availableLocaleList;
count = availableLocaleListCount;
}
return result;
}
UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
@ -617,15 +682,82 @@ Collator::unregister(URegistryKey key, UErrorCode& status)
}
return FALSE;
}
#endif /* UCONFIG_NO_SERVICE */
class CollationLocaleListEnumeration : public StringEnumeration {
private:
int32_t index;
public:
static UClassID U_EXPORT2 getStaticClassID(void);
virtual UClassID getDynamicClassID(void) const;
public:
CollationLocaleListEnumeration()
: index(0)
{
// The global variables should already be initialized.
//isAvailableLocaleListInitialized(status);
}
virtual ~CollationLocaleListEnumeration() {
}
virtual StringEnumeration * clone() const
{
CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration();
result->index = index;
return result;
}
virtual int32_t count(UErrorCode &/*status*/) const {
return availableLocaleListCount;
}
virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) {
const char* result;
if(index < availableLocaleListCount) {
result = availableLocaleList[index++].getName();
if(resultLength != NULL) {
*resultLength = uprv_strlen(result);
}
} else {
if(resultLength != NULL) {
*resultLength = 0;
}
result = NULL;
}
return result;
}
virtual const UnicodeString* snext(UErrorCode& status) {
int32_t resultLength = 0;
const char *s = next(&resultLength, status);
return setChars(s, resultLength, status);
}
virtual void reset(UErrorCode& /*status*/) {
index = 0;
}
};
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration)
// -------------------------------------
StringEnumeration* U_EXPORT2
Collator::getAvailableLocales(void)
{
return getService()->getAvailableLocales();
}
#if !UCONFIG_NO_SERVICE
if (hasService()) {
return getService()->getAvailableLocales();
}
#endif /* UCONFIG_NO_SERVICE */
UErrorCode status = U_ZERO_ERROR;
if (isAvailableLocaleListInitialized(status)) {
return new CollationLocaleListEnumeration();
}
return NULL;
}
StringEnumeration* U_EXPORT2
Collator::getKeywords(UErrorCode& status) {

View file

@ -600,7 +600,6 @@ public:
*/
static const Locale* U_EXPORT2 getAvailableLocales(int32_t& count);
#if !UCONFIG_NO_SERVICE
/**
* Return a StringEnumeration over the locales available at the time of the call,
* including registered locales. If a severe error occurs (such as out of memory
@ -610,7 +609,6 @@ public:
* @stable ICU 2.6
*/
static StringEnumeration* U_EXPORT2 getAvailableLocales(void);
#endif
/**
* Create a string enumerator of all possible keywords that are relevant to