|
1 /** |
|
2 ******************************************************************************* |
|
3 * Copyright (C) 2001-2012, 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 "charstr.h" |
|
19 #include "ucln_cmn.h" |
|
20 #include "uassert.h" |
|
21 |
|
22 #define UNDERSCORE_CHAR ((UChar)0x005f) |
|
23 #define AT_SIGN_CHAR ((UChar)64) |
|
24 #define PERIOD_CHAR ((UChar)46) |
|
25 |
|
26 U_NAMESPACE_BEGIN |
|
27 |
|
28 static UMutex llock = U_MUTEX_INITIALIZER; |
|
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, NULL, status); |
|
48 } |
|
49 |
|
50 UObject* |
|
51 ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const |
|
52 { |
|
53 return get(locale, kind, NULL, 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 = NULL; |
|
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 == NULL) { |
|
77 result = getKey(*key, status); |
|
78 } else { |
|
79 UnicodeString temp; |
|
80 result = getKey(*key, &temp, status); |
|
81 |
|
82 if (result != NULL) { |
|
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 != NULL) { |
|
121 return registerFactory(factory, status); |
|
122 } |
|
123 delete objToAdopt; |
|
124 return NULL; |
|
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 != NULL) { |
|
147 return registerFactory(factory, status); |
|
148 } |
|
149 delete objToAdopt; |
|
150 return NULL; |
|
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, NULL, 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, NULL, 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 _ids.addElement(((UnicodeString *)other._ids.elementAt(i))->clone(), status); |
|
183 } |
|
184 |
|
185 if(U_SUCCESS(status)) { |
|
186 _pos = other._pos; |
|
187 } |
|
188 } |
|
189 } |
|
190 |
|
191 public: |
|
192 static ServiceEnumeration* create(const ICULocaleService* service) { |
|
193 UErrorCode status = U_ZERO_ERROR; |
|
194 ServiceEnumeration* result = new ServiceEnumeration(service, status); |
|
195 if (U_SUCCESS(status)) { |
|
196 return result; |
|
197 } |
|
198 delete result; |
|
199 return NULL; |
|
200 } |
|
201 |
|
202 virtual ~ServiceEnumeration(); |
|
203 |
|
204 virtual StringEnumeration *clone() const { |
|
205 UErrorCode status = U_ZERO_ERROR; |
|
206 ServiceEnumeration *cl = new ServiceEnumeration(*this, status); |
|
207 if(U_FAILURE(status)) { |
|
208 delete cl; |
|
209 cl = NULL; |
|
210 } |
|
211 return cl; |
|
212 } |
|
213 |
|
214 UBool upToDate(UErrorCode& status) const { |
|
215 if (U_SUCCESS(status)) { |
|
216 if (_timestamp == _service->getTimestamp()) { |
|
217 return TRUE; |
|
218 } |
|
219 status = U_ENUM_OUT_OF_SYNC_ERROR; |
|
220 } |
|
221 return FALSE; |
|
222 } |
|
223 |
|
224 virtual int32_t count(UErrorCode& status) const { |
|
225 return upToDate(status) ? _ids.size() : 0; |
|
226 } |
|
227 |
|
228 virtual const UnicodeString* snext(UErrorCode& status) { |
|
229 if (upToDate(status) && (_pos < _ids.size())) { |
|
230 return (const UnicodeString*)_ids[_pos++]; |
|
231 } |
|
232 return NULL; |
|
233 } |
|
234 |
|
235 virtual void reset(UErrorCode& status) { |
|
236 if (status == U_ENUM_OUT_OF_SYNC_ERROR) { |
|
237 status = U_ZERO_ERROR; |
|
238 } |
|
239 if (U_SUCCESS(status)) { |
|
240 _timestamp = _service->getTimestamp(); |
|
241 _pos = 0; |
|
242 _service->getVisibleIDs(_ids, status); |
|
243 } |
|
244 } |
|
245 |
|
246 public: |
|
247 static UClassID U_EXPORT2 getStaticClassID(void); |
|
248 virtual UClassID getDynamicClassID(void) const; |
|
249 }; |
|
250 |
|
251 ServiceEnumeration::~ServiceEnumeration() {} |
|
252 |
|
253 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration) |
|
254 |
|
255 StringEnumeration* |
|
256 ICULocaleService::getAvailableLocales(void) const |
|
257 { |
|
258 return ServiceEnumeration::create(this); |
|
259 } |
|
260 |
|
261 const UnicodeString& |
|
262 ICULocaleService::validateFallbackLocale() const |
|
263 { |
|
264 const Locale& loc = Locale::getDefault(); |
|
265 ICULocaleService* ncThis = (ICULocaleService*)this; |
|
266 { |
|
267 Mutex mutex(&llock); |
|
268 if (loc != fallbackLocale) { |
|
269 ncThis->fallbackLocale = loc; |
|
270 LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName); |
|
271 ncThis->clearServiceCache(); |
|
272 } |
|
273 } |
|
274 return fallbackLocaleName; |
|
275 } |
|
276 |
|
277 ICUServiceKey* |
|
278 ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const |
|
279 { |
|
280 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status); |
|
281 } |
|
282 |
|
283 ICUServiceKey* |
|
284 ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const |
|
285 { |
|
286 return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status); |
|
287 } |
|
288 |
|
289 U_NAMESPACE_END |
|
290 |
|
291 /* !UCONFIG_NO_SERVICE */ |
|
292 #endif |
|
293 |
|
294 |