1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 2001-2014, International Business Machines Corporation and *
6 * others. All Rights Reserved. *
7 *******************************************************************************
9 *******************************************************************************
11 #include "unicode/utypes.h"
13 #if !UCONFIG_NO_SERVICE
15 #include "unicode/resbund.h"
23 #define UNDERSCORE_CHAR ((UChar)0x005f)
24 #define AT_SIGN_CHAR ((UChar)64)
25 #define PERIOD_CHAR ((UChar)46)
29 static UMutex llock
= U_MUTEX_INITIALIZER
;
30 ICULocaleService::ICULocaleService()
31 : fallbackLocale(Locale::getDefault())
35 ICULocaleService::ICULocaleService(const UnicodeString
& dname
)
37 , fallbackLocale(Locale::getDefault())
41 ICULocaleService::~ICULocaleService()
46 ICULocaleService::get(const Locale
& locale
, UErrorCode
& status
) const
48 return get(locale
, LocaleKey::KIND_ANY
, NULL
, status
);
52 ICULocaleService::get(const Locale
& locale
, int32_t kind
, UErrorCode
& status
) const
54 return get(locale
, kind
, NULL
, status
);
58 ICULocaleService::get(const Locale
& locale
, Locale
* actualReturn
, UErrorCode
& status
) const
60 return get(locale
, LocaleKey::KIND_ANY
, actualReturn
, status
);
64 ICULocaleService::get(const Locale
& locale
, int32_t kind
, Locale
* actualReturn
, UErrorCode
& status
) const
66 UObject
* result
= NULL
;
67 if (U_FAILURE(status
)) {
71 UnicodeString
locName(locale
.getName(), -1, US_INV
);
72 if (locName
.isBogus()) {
73 status
= U_MEMORY_ALLOCATION_ERROR
;
75 ICUServiceKey
* key
= createKey(&locName
, kind
, status
);
77 if (actualReturn
== NULL
) {
78 result
= getKey(*key
, status
);
81 result
= getKey(*key
, &temp
, status
);
84 key
->parseSuffix(temp
);
85 LocaleUtility::initLocaleFromName(temp
, *actualReturn
);
96 ICULocaleService::registerInstance(UObject
* objToAdopt
, const UnicodeString
& locale
,
97 UBool visible
, UErrorCode
& status
)
100 LocaleUtility::initLocaleFromName(locale
, loc
);
101 return registerInstance(objToAdopt
, loc
, LocaleKey::KIND_ANY
,
102 visible
? LocaleKeyFactory::VISIBLE
: LocaleKeyFactory::INVISIBLE
, status
);
106 ICULocaleService::registerInstance(UObject
* objToAdopt
, const Locale
& locale
, UErrorCode
& status
)
108 return registerInstance(objToAdopt
, locale
, LocaleKey::KIND_ANY
, LocaleKeyFactory::VISIBLE
, status
);
112 ICULocaleService::registerInstance(UObject
* objToAdopt
, const Locale
& locale
, int32_t kind
, UErrorCode
& status
)
114 return registerInstance(objToAdopt
, locale
, kind
, LocaleKeyFactory::VISIBLE
, status
);
118 ICULocaleService::registerInstance(UObject
* objToAdopt
, const Locale
& locale
, int32_t kind
, int32_t coverage
, UErrorCode
& status
)
120 ICUServiceFactory
* factory
= new SimpleLocaleKeyFactory(objToAdopt
, locale
, kind
, coverage
);
121 if (factory
!= NULL
) {
122 return registerFactory(factory
, status
);
130 ICULocaleService::registerInstance(UObject
* objToAdopt
, const UnicodeString
& locale
, UErrorCode
& status
)
132 return registerInstance(objToAdopt
, locale
, LocaleKey::KIND_ANY
, LocaleKeyFactory::VISIBLE
, status
);
136 ICULocaleService::registerInstance(UObject
* objToAdopt
, const UnicodeString
& locale
, UBool visible
, UErrorCode
& status
)
138 return registerInstance(objToAdopt
, locale
, LocaleKey::KIND_ANY
,
139 visible
? LocaleKeyFactory::VISIBLE
: LocaleKeyFactory::INVISIBLE
,
144 ICULocaleService::registerInstance(UObject
* objToAdopt
, const UnicodeString
& locale
, int32_t kind
, int32_t coverage
, UErrorCode
& status
)
146 ICUServiceFactory
* factory
= new SimpleLocaleKeyFactory(objToAdopt
, locale
, kind
, coverage
);
147 if (factory
!= NULL
) {
148 return registerFactory(factory
, status
);
155 class ServiceEnumeration
: public StringEnumeration
{
157 const ICULocaleService
* _service
;
163 ServiceEnumeration(const ICULocaleService
* service
, UErrorCode
&status
)
165 , _timestamp(service
->getTimestamp())
166 , _ids(uprv_deleteUObject
, NULL
, status
)
169 _service
->getVisibleIDs(_ids
, status
);
172 ServiceEnumeration(const ServiceEnumeration
&other
, UErrorCode
&status
)
173 : _service(other
._service
)
174 , _timestamp(other
._timestamp
)
175 , _ids(uprv_deleteUObject
, NULL
, status
)
178 if(U_SUCCESS(status
)) {
181 length
= other
._ids
.size();
182 for(i
= 0; i
< length
; ++i
) {
183 _ids
.addElement(((UnicodeString
*)other
._ids
.elementAt(i
))->clone(), status
);
186 if(U_SUCCESS(status
)) {
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
)) {
203 virtual ~ServiceEnumeration();
205 virtual StringEnumeration
*clone() const {
206 UErrorCode status
= U_ZERO_ERROR
;
207 ServiceEnumeration
*cl
= new ServiceEnumeration(*this, status
);
208 if(U_FAILURE(status
)) {
215 UBool
upToDate(UErrorCode
& status
) const {
216 if (U_SUCCESS(status
)) {
217 if (_timestamp
== _service
->getTimestamp()) {
220 status
= U_ENUM_OUT_OF_SYNC_ERROR
;
225 virtual int32_t count(UErrorCode
& status
) const {
226 return upToDate(status
) ? _ids
.size() : 0;
229 virtual const UnicodeString
* snext(UErrorCode
& status
) {
230 if (upToDate(status
) && (_pos
< _ids
.size())) {
231 return (const UnicodeString
*)_ids
[_pos
++];
236 virtual void reset(UErrorCode
& status
) {
237 if (status
== U_ENUM_OUT_OF_SYNC_ERROR
) {
238 status
= U_ZERO_ERROR
;
240 if (U_SUCCESS(status
)) {
241 _timestamp
= _service
->getTimestamp();
243 _service
->getVisibleIDs(_ids
, status
);
248 static UClassID U_EXPORT2
getStaticClassID(void);
249 virtual UClassID
getDynamicClassID(void) const;
252 ServiceEnumeration::~ServiceEnumeration() {}
254 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration
)
257 ICULocaleService::getAvailableLocales(void) const
259 return ServiceEnumeration::create(this);
263 ICULocaleService::validateFallbackLocale() const
265 const Locale
& loc
= Locale::getDefault();
266 ICULocaleService
* ncThis
= (ICULocaleService
*)this;
269 if (loc
!= fallbackLocale
) {
270 ncThis
->fallbackLocale
= loc
;
271 LocaleUtility::initNameFromLocale(loc
, ncThis
->fallbackLocaleName
);
272 ncThis
->clearServiceCache();
275 return fallbackLocaleName
;
279 ICULocaleService::createKey(const UnicodeString
* id
, UErrorCode
& status
) const
281 return LocaleKey::createWithCanonicalFallback(id
, &validateFallbackLocale(), status
);
285 ICULocaleService::createKey(const UnicodeString
* id
, int32_t kind
, UErrorCode
& status
) const
287 return LocaleKey::createWithCanonicalFallback(id
, &validateFallbackLocale(), kind
, status
);
292 /* !UCONFIG_NO_SERVICE */