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