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