| /** |
| ******************************************************************************* |
| * Copyright (C) 2001-2012, 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 "ucln_cmn.h" |
| #include "uassert.h" |
| |
| #define UNDERSCORE_CHAR ((UChar)0x005f) |
| #define AT_SIGN_CHAR ((UChar)64) |
| #define PERIOD_CHAR ((UChar)46) |
| |
| U_NAMESPACE_BEGIN |
| |
| static UMutex llock = U_MUTEX_INITIALIZER; |
| 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; |
| { |
| 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 |
| |
| |