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 25 U_NAMESPACE_BEGIN 26 27 static UMutex llock = U_MUTEX_INITIALIZER; 28 ICULocaleService::ICULocaleService() 29 : fallbackLocale(Locale::getDefault()) 30 { 31 } 32 33 ICULocaleService::ICULocaleService(const UnicodeString& dname) 34 : ICUService(dname) 35 , fallbackLocale(Locale::getDefault()) 36 { 37 } 38 39 ICULocaleService::~ICULocaleService() 40 { 41 } 42 43 UObject* 44 ICULocaleService::get(const Locale& locale, UErrorCode& status) const 45 { 46 return get(locale, LocaleKey::KIND_ANY, NULL, status); 47 } 48 49 UObject* 50 ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const 51 { 52 return get(locale, kind, NULL, status); 53 } 54 55 UObject* 56 ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const 57 { 58 return get(locale, LocaleKey::KIND_ANY, actualReturn, status); 59 } 60 61 UObject* 62 ICULocaleService::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 93 URegistryKey 94 ICULocaleService::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 103 URegistryKey 104 ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status) 105 { 106 return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status); 107 } 108 109 URegistryKey 110 ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status) 111 { 112 return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status); 113 } 114 115 URegistryKey 116 ICULocaleService::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 127 URegistryKey 128 ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, UErrorCode& status) 129 { 130 return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status); 131 } 132 133 URegistryKey 134 ICULocaleService::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 141 URegistryKey 142 ICULocaleService::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 153 class ServiceEnumeration : public StringEnumeration { 154 private: 155 const ICULocaleService* _service; 156 int32_t _timestamp; 157 UVector _ids; 158 int32_t _pos; 159 160 private: 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 190 public: 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 245 public: 246 static UClassID U_EXPORT2 getStaticClassID(void); 247 virtual UClassID getDynamicClassID(void) const; 248 }; 249 250 ServiceEnumeration::~ServiceEnumeration() {} 251 252 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration) 253 254 StringEnumeration* 255 ICULocaleService::getAvailableLocales(void) const 256 { 257 return ServiceEnumeration::create(this); 258 } 259 260 const UnicodeString& 261 ICULocaleService::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 276 ICUServiceKey* 277 ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const 278 { 279 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status); 280 } 281 282 ICUServiceKey* 283 ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const 284 { 285 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status); 286 } 287 288 U_NAMESPACE_END 289 290 /* !UCONFIG_NO_SERVICE */ 291 #endif 292 293 294