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