1/** 2 ******************************************************************************* 3 * Copyright (C) 2001-2014, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 * 7 ******************************************************************************* 8 */ 9#include "unicode/utypes.h" 10 11#if !UCONFIG_NO_SERVICE 12 13#include "unicode/resbund.h" 14#include "uresimp.h" 15#include "cmemory.h" 16#include "servloc.h" 17#include "ustrfmt.h" 18#include "charstr.h" 19#include "uassert.h" 20 21#define UNDERSCORE_CHAR ((UChar)0x005f) 22#define AT_SIGN_CHAR ((UChar)64) 23#define PERIOD_CHAR ((UChar)46) 24 25U_NAMESPACE_BEGIN 26 27static UMutex llock = U_MUTEX_INITIALIZER; 28ICULocaleService::ICULocaleService() 29 : fallbackLocale(Locale::getDefault()) 30{ 31} 32 33ICULocaleService::ICULocaleService(const UnicodeString& dname) 34 : ICUService(dname) 35 , fallbackLocale(Locale::getDefault()) 36{ 37} 38 39ICULocaleService::~ICULocaleService() 40{ 41} 42 43UObject* 44ICULocaleService::get(const Locale& locale, UErrorCode& status) const 45{ 46 return get(locale, LocaleKey::KIND_ANY, NULL, status); 47} 48 49UObject* 50ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const 51{ 52 return get(locale, kind, NULL, status); 53} 54 55UObject* 56ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const 57{ 58 return get(locale, LocaleKey::KIND_ANY, actualReturn, status); 59} 60 61UObject* 62ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const 63{ 64 UObject* result = NULL; 65 if (U_FAILURE(status)) { 66 return result; 67 } 68 69 UnicodeString locName(locale.getName(), -1, US_INV); 70 if (locName.isBogus()) { 71 status = U_MEMORY_ALLOCATION_ERROR; 72 } else { 73 ICUServiceKey* key = createKey(&locName, kind, status); 74 if (key) { 75 if (actualReturn == NULL) { 76 result = getKey(*key, status); 77 } else { 78 UnicodeString temp; 79 result = getKey(*key, &temp, status); 80 81 if (result != NULL) { 82 key->parseSuffix(temp); 83 LocaleUtility::initLocaleFromName(temp, *actualReturn); 84 } 85 } 86 delete key; 87 } 88 } 89 return result; 90} 91 92 93URegistryKey 94ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, 95 UBool visible, UErrorCode& status) 96{ 97 Locale loc; 98 LocaleUtility::initLocaleFromName(locale, loc); 99 return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY, 100 visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status); 101} 102 103URegistryKey 104ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status) 105{ 106 return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status); 107} 108 109URegistryKey 110ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status) 111{ 112 return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status); 113} 114 115URegistryKey 116ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status) 117{ 118 ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage); 119 if (factory != NULL) { 120 return registerFactory(factory, status); 121 } 122 delete objToAdopt; 123 return NULL; 124} 125 126#if 0 127URegistryKey 128ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UErrorCode& status) 129{ 130 return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status); 131} 132 133URegistryKey 134ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UBool visible, UErrorCode& status) 135{ 136 return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, 137 visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, 138 status); 139} 140 141URegistryKey 142ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, int32_t kind, int32_t coverage, UErrorCode& status) 143{ 144 ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage); 145 if (factory != NULL) { 146 return registerFactory(factory, status); 147 } 148 delete objToAdopt; 149 return NULL; 150} 151#endif 152 153class ServiceEnumeration : public StringEnumeration { 154private: 155 const ICULocaleService* _service; 156 int32_t _timestamp; 157 UVector _ids; 158 int32_t _pos; 159 160private: 161 ServiceEnumeration(const ICULocaleService* service, UErrorCode &status) 162 : _service(service) 163 , _timestamp(service->getTimestamp()) 164 , _ids(uprv_deleteUObject, NULL, status) 165 , _pos(0) 166 { 167 _service->getVisibleIDs(_ids, status); 168 } 169 170 ServiceEnumeration(const ServiceEnumeration &other, UErrorCode &status) 171 : _service(other._service) 172 , _timestamp(other._timestamp) 173 , _ids(uprv_deleteUObject, NULL, status) 174 , _pos(0) 175 { 176 if(U_SUCCESS(status)) { 177 int32_t i, length; 178 179 length = other._ids.size(); 180 for(i = 0; i < length; ++i) { 181 _ids.addElement(((UnicodeString *)other._ids.elementAt(i))->clone(), status); 182 } 183 184 if(U_SUCCESS(status)) { 185 _pos = other._pos; 186 } 187 } 188 } 189 190public: 191 static ServiceEnumeration* create(const ICULocaleService* service) { 192 UErrorCode status = U_ZERO_ERROR; 193 ServiceEnumeration* result = new ServiceEnumeration(service, status); 194 if (U_SUCCESS(status)) { 195 return result; 196 } 197 delete result; 198 return NULL; 199 } 200 201 virtual ~ServiceEnumeration(); 202 203 virtual StringEnumeration *clone() const { 204 UErrorCode status = U_ZERO_ERROR; 205 ServiceEnumeration *cl = new ServiceEnumeration(*this, status); 206 if(U_FAILURE(status)) { 207 delete cl; 208 cl = NULL; 209 } 210 return cl; 211 } 212 213 UBool upToDate(UErrorCode& status) const { 214 if (U_SUCCESS(status)) { 215 if (_timestamp == _service->getTimestamp()) { 216 return TRUE; 217 } 218 status = U_ENUM_OUT_OF_SYNC_ERROR; 219 } 220 return FALSE; 221 } 222 223 virtual int32_t count(UErrorCode& status) const { 224 return upToDate(status) ? _ids.size() : 0; 225 } 226 227 virtual const UnicodeString* snext(UErrorCode& status) { 228 if (upToDate(status) && (_pos < _ids.size())) { 229 return (const UnicodeString*)_ids[_pos++]; 230 } 231 return NULL; 232 } 233 234 virtual void reset(UErrorCode& status) { 235 if (status == U_ENUM_OUT_OF_SYNC_ERROR) { 236 status = U_ZERO_ERROR; 237 } 238 if (U_SUCCESS(status)) { 239 _timestamp = _service->getTimestamp(); 240 _pos = 0; 241 _service->getVisibleIDs(_ids, status); 242 } 243 } 244 245public: 246 static UClassID U_EXPORT2 getStaticClassID(void); 247 virtual UClassID getDynamicClassID(void) const; 248}; 249 250ServiceEnumeration::~ServiceEnumeration() {} 251 252UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration) 253 254StringEnumeration* 255ICULocaleService::getAvailableLocales(void) const 256{ 257 return ServiceEnumeration::create(this); 258} 259 260const UnicodeString& 261ICULocaleService::validateFallbackLocale() const 262{ 263 const Locale& loc = Locale::getDefault(); 264 ICULocaleService* ncThis = (ICULocaleService*)this; 265 { 266 Mutex mutex(&llock); 267 if (loc != fallbackLocale) { 268 ncThis->fallbackLocale = loc; 269 LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName); 270 ncThis->clearServiceCache(); 271 } 272 } 273 return fallbackLocaleName; 274} 275 276ICUServiceKey* 277ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const 278{ 279 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status); 280} 281 282ICUServiceKey* 283ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const 284{ 285 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status); 286} 287 288U_NAMESPACE_END 289 290/* !UCONFIG_NO_SERVICE */ 291#endif 292 293 294