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