296 lines
8.2 KiB
C++
296 lines
8.2 KiB
C++
|
// © 2016 and later: Unicode, Inc. and others.
|
||
|
// License & terms of use: http://www.unicode.org/copyright.html
|
||
|
/**
|
||
|
*******************************************************************************
|
||
|
* Copyright (C) 2001-2014, International Business Machines Corporation and *
|
||
|
* others. All Rights Reserved. *
|
||
|
*******************************************************************************
|
||
|
*
|
||
|
*******************************************************************************
|
||
|
*/
|
||
|
#include "unicode/utypes.h"
|
||
|
|
||
|
#if !UCONFIG_NO_SERVICE
|
||
|
|
||
|
#include "unicode/resbund.h"
|
||
|
#include "uresimp.h"
|
||
|
#include "cmemory.h"
|
||
|
#include "servloc.h"
|
||
|
#include "ustrfmt.h"
|
||
|
#include "charstr.h"
|
||
|
#include "uassert.h"
|
||
|
|
||
|
#define UNDERSCORE_CHAR ((UChar)0x005f)
|
||
|
#define AT_SIGN_CHAR ((UChar)64)
|
||
|
#define PERIOD_CHAR ((UChar)46)
|
||
|
|
||
|
U_NAMESPACE_BEGIN
|
||
|
|
||
|
ICULocaleService::ICULocaleService()
|
||
|
: fallbackLocale(Locale::getDefault())
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ICULocaleService::ICULocaleService(const UnicodeString& dname)
|
||
|
: ICUService(dname)
|
||
|
, fallbackLocale(Locale::getDefault())
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ICULocaleService::~ICULocaleService()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
UObject*
|
||
|
ICULocaleService::get(const Locale& locale, UErrorCode& status) const
|
||
|
{
|
||
|
return get(locale, LocaleKey::KIND_ANY, NULL, status);
|
||
|
}
|
||
|
|
||
|
UObject*
|
||
|
ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
|
||
|
{
|
||
|
return get(locale, kind, NULL, status);
|
||
|
}
|
||
|
|
||
|
UObject*
|
||
|
ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
|
||
|
{
|
||
|
return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
|
||
|
}
|
||
|
|
||
|
UObject*
|
||
|
ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const
|
||
|
{
|
||
|
UObject* result = NULL;
|
||
|
if (U_FAILURE(status)) {
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
UnicodeString locName(locale.getName(), -1, US_INV);
|
||
|
if (locName.isBogus()) {
|
||
|
status = U_MEMORY_ALLOCATION_ERROR;
|
||
|
} else {
|
||
|
ICUServiceKey* key = createKey(&locName, kind, status);
|
||
|
if (key) {
|
||
|
if (actualReturn == NULL) {
|
||
|
result = getKey(*key, status);
|
||
|
} else {
|
||
|
UnicodeString temp;
|
||
|
result = getKey(*key, &temp, status);
|
||
|
|
||
|
if (result != NULL) {
|
||
|
key->parseSuffix(temp);
|
||
|
LocaleUtility::initLocaleFromName(temp, *actualReturn);
|
||
|
}
|
||
|
}
|
||
|
delete key;
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale,
|
||
|
UBool visible, UErrorCode& status)
|
||
|
{
|
||
|
Locale loc;
|
||
|
LocaleUtility::initLocaleFromName(locale, loc);
|
||
|
return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY,
|
||
|
visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status);
|
||
|
}
|
||
|
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status)
|
||
|
{
|
||
|
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
|
||
|
}
|
||
|
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status)
|
||
|
{
|
||
|
return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status);
|
||
|
}
|
||
|
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status)
|
||
|
{
|
||
|
ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
|
||
|
if (factory != NULL) {
|
||
|
return registerFactory(factory, status);
|
||
|
}
|
||
|
delete objToAdopt;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UErrorCode& status)
|
||
|
{
|
||
|
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
|
||
|
}
|
||
|
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UBool visible, UErrorCode& status)
|
||
|
{
|
||
|
return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY,
|
||
|
visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE,
|
||
|
status);
|
||
|
}
|
||
|
|
||
|
URegistryKey
|
||
|
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, int32_t kind, int32_t coverage, UErrorCode& status)
|
||
|
{
|
||
|
ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
|
||
|
if (factory != NULL) {
|
||
|
return registerFactory(factory, status);
|
||
|
}
|
||
|
delete objToAdopt;
|
||
|
return NULL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
class ServiceEnumeration : public StringEnumeration {
|
||
|
private:
|
||
|
const ICULocaleService* _service;
|
||
|
int32_t _timestamp;
|
||
|
UVector _ids;
|
||
|
int32_t _pos;
|
||
|
|
||
|
private:
|
||
|
ServiceEnumeration(const ICULocaleService* service, UErrorCode &status)
|
||
|
: _service(service)
|
||
|
, _timestamp(service->getTimestamp())
|
||
|
, _ids(uprv_deleteUObject, NULL, status)
|
||
|
, _pos(0)
|
||
|
{
|
||
|
_service->getVisibleIDs(_ids, status);
|
||
|
}
|
||
|
|
||
|
ServiceEnumeration(const ServiceEnumeration &other, UErrorCode &status)
|
||
|
: _service(other._service)
|
||
|
, _timestamp(other._timestamp)
|
||
|
, _ids(uprv_deleteUObject, NULL, status)
|
||
|
, _pos(0)
|
||
|
{
|
||
|
if(U_SUCCESS(status)) {
|
||
|
int32_t i, length;
|
||
|
|
||
|
length = other._ids.size();
|
||
|
for(i = 0; i < length; ++i) {
|
||
|
_ids.addElement(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
|
||
|
}
|
||
|
|
||
|
if(U_SUCCESS(status)) {
|
||
|
_pos = other._pos;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
static ServiceEnumeration* create(const ICULocaleService* service) {
|
||
|
UErrorCode status = U_ZERO_ERROR;
|
||
|
ServiceEnumeration* result = new ServiceEnumeration(service, status);
|
||
|
if (U_SUCCESS(status)) {
|
||
|
return result;
|
||
|
}
|
||
|
delete result;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
virtual ~ServiceEnumeration();
|
||
|
|
||
|
virtual StringEnumeration *clone() const {
|
||
|
UErrorCode status = U_ZERO_ERROR;
|
||
|
ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
|
||
|
if(U_FAILURE(status)) {
|
||
|
delete cl;
|
||
|
cl = NULL;
|
||
|
}
|
||
|
return cl;
|
||
|
}
|
||
|
|
||
|
UBool upToDate(UErrorCode& status) const {
|
||
|
if (U_SUCCESS(status)) {
|
||
|
if (_timestamp == _service->getTimestamp()) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
status = U_ENUM_OUT_OF_SYNC_ERROR;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
virtual int32_t count(UErrorCode& status) const {
|
||
|
return upToDate(status) ? _ids.size() : 0;
|
||
|
}
|
||
|
|
||
|
virtual const UnicodeString* snext(UErrorCode& status) {
|
||
|
if (upToDate(status) && (_pos < _ids.size())) {
|
||
|
return (const UnicodeString*)_ids[_pos++];
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
virtual void reset(UErrorCode& status) {
|
||
|
if (status == U_ENUM_OUT_OF_SYNC_ERROR) {
|
||
|
status = U_ZERO_ERROR;
|
||
|
}
|
||
|
if (U_SUCCESS(status)) {
|
||
|
_timestamp = _service->getTimestamp();
|
||
|
_pos = 0;
|
||
|
_service->getVisibleIDs(_ids, status);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
static UClassID U_EXPORT2 getStaticClassID(void);
|
||
|
virtual UClassID getDynamicClassID(void) const;
|
||
|
};
|
||
|
|
||
|
ServiceEnumeration::~ServiceEnumeration() {}
|
||
|
|
||
|
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
|
||
|
|
||
|
StringEnumeration*
|
||
|
ICULocaleService::getAvailableLocales(void) const
|
||
|
{
|
||
|
return ServiceEnumeration::create(this);
|
||
|
}
|
||
|
|
||
|
const UnicodeString&
|
||
|
ICULocaleService::validateFallbackLocale() const
|
||
|
{
|
||
|
const Locale& loc = Locale::getDefault();
|
||
|
ICULocaleService* ncThis = (ICULocaleService*)this;
|
||
|
static UMutex llock;
|
||
|
{
|
||
|
Mutex mutex(&llock);
|
||
|
if (loc != fallbackLocale) {
|
||
|
ncThis->fallbackLocale = loc;
|
||
|
LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
|
||
|
ncThis->clearServiceCache();
|
||
|
}
|
||
|
}
|
||
|
return fallbackLocaleName;
|
||
|
}
|
||
|
|
||
|
ICUServiceKey*
|
||
|
ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
|
||
|
{
|
||
|
return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
|
||
|
}
|
||
|
|
||
|
ICUServiceKey*
|
||
|
ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
|
||
|
{
|
||
|
return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
|
||
|
}
|
||
|
|
||
|
U_NAMESPACE_END
|
||
|
|
||
|
/* !UCONFIG_NO_SERVICE */
|
||
|
#endif
|
||
|
|
||
|
|