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