• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
ICULocaleService()30 ICULocaleService::ICULocaleService()
31   : fallbackLocale(Locale::getDefault())
32 {
33 }
34 
ICULocaleService(const UnicodeString & dname)35 ICULocaleService::ICULocaleService(const UnicodeString& dname)
36   : ICUService(dname)
37   , fallbackLocale(Locale::getDefault())
38 {
39 }
40 
~ICULocaleService()41 ICULocaleService::~ICULocaleService()
42 {
43 }
44 
45 UObject*
get(const Locale & locale,UErrorCode & status) const46 ICULocaleService::get(const Locale& locale, UErrorCode& status) const
47 {
48     return get(locale, LocaleKey::KIND_ANY, NULL, status);
49 }
50 
51 UObject*
get(const Locale & locale,int32_t kind,UErrorCode & status) const52 ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
53 {
54     return get(locale, kind, NULL, status);
55 }
56 
57 UObject*
get(const Locale & locale,Locale * actualReturn,UErrorCode & status) const58 ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
59 {
60     return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
61 }
62 
63 UObject*
get(const Locale & locale,int32_t kind,Locale * actualReturn,UErrorCode & status) const64 ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const
65 {
66     UObject* result = NULL;
67     if (U_FAILURE(status)) {
68         return result;
69     }
70 
71     UnicodeString locName(locale.getName(), -1, US_INV);
72     if (locName.isBogus()) {
73         status = U_MEMORY_ALLOCATION_ERROR;
74     } else {
75         ICUServiceKey* key = createKey(&locName, kind, status);
76         if (key) {
77             if (actualReturn == NULL) {
78                 result = getKey(*key, status);
79             } else {
80                 UnicodeString temp;
81                 result = getKey(*key, &temp, status);
82 
83                 if (result != NULL) {
84                     key->parseSuffix(temp);
85                     LocaleUtility::initLocaleFromName(temp, *actualReturn);
86                 }
87             }
88             delete key;
89         }
90     }
91     return result;
92 }
93 
94 
95 URegistryKey
registerInstance(UObject * objToAdopt,const UnicodeString & locale,UBool visible,UErrorCode & status)96 ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale,
97     UBool visible, UErrorCode& status)
98 {
99     Locale loc;
100     LocaleUtility::initLocaleFromName(locale, loc);
101     return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY,
102         visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status);
103 }
104 
105 URegistryKey
registerInstance(UObject * objToAdopt,const Locale & locale,UErrorCode & status)106 ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status)
107 {
108     return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
109 }
110 
111 URegistryKey
registerInstance(UObject * objToAdopt,const Locale & locale,int32_t kind,UErrorCode & status)112 ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status)
113 {
114     return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status);
115 }
116 
117 URegistryKey
registerInstance(UObject * objToAdopt,const Locale & locale,int32_t kind,int32_t coverage,UErrorCode & status)118 ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status)
119 {
120     ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
121     if (factory != NULL) {
122         return registerFactory(factory, status);
123     }
124     delete objToAdopt;
125     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:
ServiceEnumeration(const ICULocaleService * service,UErrorCode & status)163     ServiceEnumeration(const ICULocaleService* service, UErrorCode &status)
164         : _service(service)
165         , _timestamp(service->getTimestamp())
166         , _ids(uprv_deleteUObject, NULL, status)
167         , _pos(0)
168     {
169         _service->getVisibleIDs(_ids, status);
170     }
171 
ServiceEnumeration(const ServiceEnumeration & other,UErrorCode & status)172     ServiceEnumeration(const ServiceEnumeration &other, UErrorCode &status)
173         : _service(other._service)
174         , _timestamp(other._timestamp)
175         , _ids(uprv_deleteUObject, NULL, status)
176         , _pos(0)
177     {
178         if(U_SUCCESS(status)) {
179             int32_t i, length;
180 
181             length = other._ids.size();
182             for(i = 0; i < length; ++i) {
183                 _ids.addElement(((UnicodeString *)other._ids.elementAt(i))->clone(), 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 NULL;
201     }
202 
203     virtual ~ServiceEnumeration();
204 
clone() const205     virtual StringEnumeration *clone() const {
206         UErrorCode status = U_ZERO_ERROR;
207         ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
208         if(U_FAILURE(status)) {
209             delete cl;
210             cl = NULL;
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 {
226         return upToDate(status) ? _ids.size() : 0;
227     }
228 
snext(UErrorCode & status)229     virtual const UnicodeString* snext(UErrorCode& status) {
230         if (upToDate(status) && (_pos < _ids.size())) {
231             return (const UnicodeString*)_ids[_pos++];
232         }
233         return NULL;
234     }
235 
reset(UErrorCode & status)236     virtual void reset(UErrorCode& status) {
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(void);
249     virtual UClassID getDynamicClassID(void) const;
250 };
251 
~ServiceEnumeration()252 ServiceEnumeration::~ServiceEnumeration() {}
253 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)254 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
255 
256 StringEnumeration*
257 ICULocaleService::getAvailableLocales(void) 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     {
268         Mutex mutex(&llock);
269         if (loc != fallbackLocale) {
270             ncThis->fallbackLocale = loc;
271             LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
272             ncThis->clearServiceCache();
273         }
274     }
275     return fallbackLocaleName;
276 }
277 
278 ICUServiceKey*
createKey(const UnicodeString * id,UErrorCode & status) const279 ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
280 {
281     return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
282 }
283 
284 ICUServiceKey*
createKey(const UnicodeString * id,int32_t kind,UErrorCode & status) const285 ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
286 {
287     return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
288 }
289 
290 U_NAMESPACE_END
291 
292 /* !UCONFIG_NO_SERVICE */
293 #endif
294 
295 
296