xref: /aosp_15_r20/external/cronet/third_party/icu/source/common/servls.cpp (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 
ICULocaleService()29 ICULocaleService::ICULocaleService()
30   : fallbackLocale(Locale::getDefault())
31 {
32 }
33 
ICULocaleService(const UnicodeString & dname)34 ICULocaleService::ICULocaleService(const UnicodeString& dname)
35   : ICUService(dname)
36   , fallbackLocale(Locale::getDefault())
37 {
38 }
39 
~ICULocaleService()40 ICULocaleService::~ICULocaleService()
41 {
42 }
43 
44 UObject*
get(const Locale & locale,UErrorCode & status) const45 ICULocaleService::get(const Locale& locale, UErrorCode& status) const
46 {
47     return get(locale, LocaleKey::KIND_ANY, nullptr, status);
48 }
49 
50 UObject*
get(const Locale & locale,int32_t kind,UErrorCode & status) const51 ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
52 {
53     return get(locale, kind, nullptr, status);
54 }
55 
56 UObject*
get(const Locale & locale,Locale * actualReturn,UErrorCode & status) const57 ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
58 {
59     return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
60 }
61 
62 UObject*
get(const Locale & locale,int32_t kind,Locale * actualReturn,UErrorCode & status) const63 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
registerInstance(UObject * objToAdopt,const UnicodeString & locale,UBool visible,UErrorCode & status)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
registerInstance(UObject * objToAdopt,const Locale & locale,UErrorCode & status)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
registerInstance(UObject * objToAdopt,const Locale & locale,int32_t kind,UErrorCode & status)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
registerInstance(UObject * objToAdopt,const Locale & locale,int32_t kind,int32_t coverage,UErrorCode & status)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:
ServiceEnumeration(const ICULocaleService * service,UErrorCode & status)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 
ServiceEnumeration(const ServiceEnumeration & other,UErrorCode & status)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(((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:
create(const ICULocaleService * service)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 
clone() const205     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 
upToDate(UErrorCode & status) const215     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 
count(UErrorCode & status) const225     virtual int32_t count(UErrorCode& status) const override {
226         return upToDate(status) ? _ids.size() : 0;
227     }
228 
snext(UErrorCode & status)229     virtual const UnicodeString* snext(UErrorCode& status) override {
230         if (upToDate(status) && (_pos < _ids.size())) {
231             return (const UnicodeString*)_ids[_pos++];
232         }
233         return nullptr;
234     }
235 
reset(UErrorCode & status)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 
~ServiceEnumeration()252 ServiceEnumeration::~ServiceEnumeration() {}
253 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)254 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
255 
256 StringEnumeration*
257 ICULocaleService::getAvailableLocales() const
258 {
259     return ServiceEnumeration::create(this);
260 }
261 
262 const UnicodeString&
validateFallbackLocale() const263 ICULocaleService::validateFallbackLocale() const
264 {
265     const Locale&     loc    = Locale::getDefault();
266     ICULocaleService* ncThis = (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*
createKey(const UnicodeString * id,UErrorCode & status) const280 ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
281 {
282     return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
283 }
284 
285 ICUServiceKey*
createKey(const UnicodeString * id,int32_t kind,UErrorCode & status) const286 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
295 
296 
297