• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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