Coverage Report

Created: 2024-04-24 06:23

/src/icu/source/common/servls.cpp
Line
Count
Source (jump to first uncovered line)
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
ICULocaleService::ICULocaleService()
30
  : fallbackLocale(Locale::getDefault())
31
0
{
32
0
}
33
34
ICULocaleService::ICULocaleService(const UnicodeString& dname)
35
  : ICUService(dname)
36
  , fallbackLocale(Locale::getDefault())
37
0
{
38
0
}
39
40
ICULocaleService::~ICULocaleService()
41
0
{
42
0
}
43
44
UObject*
45
ICULocaleService::get(const Locale& locale, UErrorCode& status) const
46
0
{
47
0
    return get(locale, LocaleKey::KIND_ANY, NULL, status);
48
0
}
49
50
UObject*
51
ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
52
0
{
53
0
    return get(locale, kind, NULL, status);
54
0
}
55
56
UObject*
57
ICULocaleService::get(const Locale& locale, Locale* actualReturn, UErrorCode& status) const
58
0
{
59
0
    return get(locale, LocaleKey::KIND_ANY, actualReturn, status);
60
0
}
61
62
UObject*
63
ICULocaleService::get(const Locale& locale, int32_t kind, Locale* actualReturn, UErrorCode& status) const
64
0
{
65
0
    UObject* result = NULL;
66
0
    if (U_FAILURE(status)) {
67
0
        return result;
68
0
    }
69
70
0
    UnicodeString locName(locale.getName(), -1, US_INV);
71
0
    if (locName.isBogus()) {
72
0
        status = U_MEMORY_ALLOCATION_ERROR;
73
0
    } else {
74
0
        ICUServiceKey* key = createKey(&locName, kind, status);
75
0
        if (key) {
76
0
            if (actualReturn == NULL) {
77
0
                result = getKey(*key, status);
78
0
            } else {
79
0
                UnicodeString temp;
80
0
                result = getKey(*key, &temp, status);
81
82
0
                if (result != NULL) {
83
0
                    key->parseSuffix(temp);
84
0
                    LocaleUtility::initLocaleFromName(temp, *actualReturn);
85
0
                }
86
0
            }
87
0
            delete key;
88
0
        }
89
0
    }
90
0
    return result;
91
0
}
92
93
94
URegistryKey
95
ICULocaleService::registerInstance(UObject* objToAdopt, const UnicodeString& locale, 
96
    UBool visible, UErrorCode& status)
97
0
{
98
0
    Locale loc;
99
0
    LocaleUtility::initLocaleFromName(locale, loc);
100
0
    return registerInstance(objToAdopt, loc, LocaleKey::KIND_ANY, 
101
0
        visible ? LocaleKeyFactory::VISIBLE : LocaleKeyFactory::INVISIBLE, status);
102
0
}
103
104
URegistryKey
105
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, UErrorCode& status)
106
0
{
107
0
    return registerInstance(objToAdopt, locale, LocaleKey::KIND_ANY, LocaleKeyFactory::VISIBLE, status);
108
0
}
109
110
URegistryKey
111
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, UErrorCode& status)
112
0
{
113
0
    return registerInstance(objToAdopt, locale, kind, LocaleKeyFactory::VISIBLE, status);
114
0
}
115
116
URegistryKey
117
ICULocaleService::registerInstance(UObject* objToAdopt, const Locale& locale, int32_t kind, int32_t coverage, UErrorCode& status)
118
0
{
119
0
    ICUServiceFactory * factory = new SimpleLocaleKeyFactory(objToAdopt, locale, kind, coverage);
120
0
    if (factory != NULL) {
121
0
        return registerFactory(factory, status);
122
0
    }
123
0
    delete objToAdopt;
124
0
    return NULL;
125
0
}
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
0
    {
168
0
        _service->getVisibleIDs(_ids, status);
169
0
    }
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
0
    {
177
0
        if(U_SUCCESS(status)) {
178
0
            int32_t i, length;
179
180
0
            length = other._ids.size();
181
0
            for(i = 0; i < length; ++i) {
182
0
                LocalPointer<UnicodeString> clonedId(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
183
0
                _ids.adoptElement(clonedId.orphan(), status);
184
0
            }
185
186
0
            if(U_SUCCESS(status)) {
187
0
                _pos = other._pos;
188
0
            }
189
0
        }
190
0
    }
191
192
public:
193
0
    static ServiceEnumeration* create(const ICULocaleService* service) {
194
0
        UErrorCode status = U_ZERO_ERROR;
195
0
        ServiceEnumeration* result = new ServiceEnumeration(service, status);
196
0
        if (U_SUCCESS(status)) {
197
0
            return result;
198
0
        }
199
0
        delete result;
200
0
        return NULL;
201
0
    }
202
203
    virtual ~ServiceEnumeration();
204
205
0
    virtual StringEnumeration *clone() const override {
206
0
        UErrorCode status = U_ZERO_ERROR;
207
0
        ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
208
0
        if(U_FAILURE(status)) {
209
0
            delete cl;
210
0
            cl = NULL;
211
0
        }
212
0
        return cl;
213
0
    }
214
215
0
    UBool upToDate(UErrorCode& status) const {
216
0
        if (U_SUCCESS(status)) {
217
0
            if (_timestamp == _service->getTimestamp()) {
218
0
                return TRUE;
219
0
            }
220
0
            status = U_ENUM_OUT_OF_SYNC_ERROR;
221
0
        }
222
0
        return FALSE;
223
0
    }
224
225
0
    virtual int32_t count(UErrorCode& status) const override {
226
0
        return upToDate(status) ? _ids.size() : 0;
227
0
    }
228
229
0
    virtual const UnicodeString* snext(UErrorCode& status) override {
230
0
        if (upToDate(status) && (_pos < _ids.size())) {
231
0
            return (const UnicodeString*)_ids[_pos++];
232
0
        }
233
0
        return NULL;
234
0
    }
235
236
0
    virtual void reset(UErrorCode& status) override {
237
0
        if (status == U_ENUM_OUT_OF_SYNC_ERROR) {
238
0
            status = U_ZERO_ERROR;
239
0
        }
240
0
        if (U_SUCCESS(status)) {
241
0
            _timestamp = _service->getTimestamp();
242
0
            _pos = 0;
243
0
            _service->getVisibleIDs(_ids, status);
244
0
        }
245
0
    }
246
247
public:
248
    static UClassID U_EXPORT2 getStaticClassID(void);
249
    virtual UClassID getDynamicClassID(void) const override;
250
};
251
252
0
ServiceEnumeration::~ServiceEnumeration() {}
253
254
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
255
256
StringEnumeration*
257
ICULocaleService::getAvailableLocales(void) const
258
0
{
259
0
    return ServiceEnumeration::create(this);
260
0
}
261
262
const UnicodeString&
263
ICULocaleService::validateFallbackLocale() const
264
0
{
265
0
    const Locale&     loc    = Locale::getDefault();
266
0
    ICULocaleService* ncThis = (ICULocaleService*)this;
267
0
    static UMutex llock;
268
0
    {
269
0
        Mutex mutex(&llock);
270
0
        if (loc != fallbackLocale) {
271
0
            ncThis->fallbackLocale = loc;
272
0
            LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
273
0
            ncThis->clearServiceCache();
274
0
        }
275
0
    }
276
0
    return fallbackLocaleName;
277
0
}
278
279
ICUServiceKey*
280
ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
281
0
{
282
0
    return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
283
0
}
284
285
ICUServiceKey*
286
ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
287
0
{
288
0
    return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
289
0
}
290
291
U_NAMESPACE_END
292
293
/* !UCONFIG_NO_SERVICE */
294
#endif
295
296