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