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