Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / common / servls.cpp
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