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