servls.cpp (8640B)
1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /** 4 ******************************************************************************* 5 * Copyright (C) 2001-2014, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 * 9 ******************************************************************************* 10 */ 11 #include "unicode/utypes.h" 12 13 #if !UCONFIG_NO_SERVICE 14 15 #include "unicode/resbund.h" 16 #include "uresimp.h" 17 #include "cmemory.h" 18 #include "servloc.h" 19 #include "ustrfmt.h" 20 #include "charstr.h" 21 #include "uassert.h" 22 23 #define UNDERSCORE_CHAR ((char16_t)0x005f) 24 #define AT_SIGN_CHAR ((char16_t)64) 25 #define PERIOD_CHAR ((char16_t)46) 26 27 U_NAMESPACE_BEGIN 28 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, nullptr, status); 48 } 49 50 UObject* 51 ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const 52 { 53 return get(locale, kind, nullptr, 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 = nullptr; 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 == nullptr) { 77 result = getKey(*key, status); 78 } else { 79 UnicodeString temp; 80 result = getKey(*key, &temp, status); 81 82 if (result != nullptr) { 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 != nullptr) { 121 return registerFactory(factory, status); 122 } 123 delete objToAdopt; 124 return nullptr; 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 != nullptr) { 147 return registerFactory(factory, status); 148 } 149 delete objToAdopt; 150 return nullptr; 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, nullptr, 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, nullptr, 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 LocalPointer<UnicodeString> clonedId(static_cast<UnicodeString*>(other._ids.elementAt(i))->clone(), status); 183 _ids.adoptElement(clonedId.orphan(), 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 nullptr; 201 } 202 203 virtual ~ServiceEnumeration(); 204 205 virtual StringEnumeration *clone() const override { 206 UErrorCode status = U_ZERO_ERROR; 207 ServiceEnumeration *cl = new ServiceEnumeration(*this, status); 208 if(U_FAILURE(status)) { 209 delete cl; 210 cl = nullptr; 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 override { 226 return upToDate(status) ? _ids.size() : 0; 227 } 228 229 virtual const UnicodeString* snext(UErrorCode& status) override { 230 if (upToDate(status) && (_pos < _ids.size())) { 231 return static_cast<const UnicodeString*>(_ids[_pos++]); 232 } 233 return nullptr; 234 } 235 236 virtual void reset(UErrorCode& status) override { 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(); 249 virtual UClassID getDynamicClassID() const override; 250 }; 251 252 ServiceEnumeration::~ServiceEnumeration() {} 253 254 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration) 255 256 StringEnumeration* 257 ICULocaleService::getAvailableLocales() const 258 { 259 return ServiceEnumeration::create(this); 260 } 261 262 const UnicodeString& 263 ICULocaleService::validateFallbackLocale() const 264 { 265 const Locale& loc = Locale::getDefault(); 266 ICULocaleService* ncThis = const_cast<ICULocaleService*>(this); 267 static UMutex llock; 268 { 269 Mutex mutex(&llock); 270 if (loc != fallbackLocale) { 271 ncThis->fallbackLocale = loc; 272 LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName); 273 ncThis->clearServiceCache(); 274 } 275 } 276 return fallbackLocaleName; 277 } 278 279 ICUServiceKey* 280 ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const 281 { 282 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status); 283 } 284 285 ICUServiceKey* 286 ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const 287 { 288 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status); 289 } 290 291 U_NAMESPACE_END 292 293 /* !UCONFIG_NO_SERVICE */ 294 #endif