tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

servls.cpp (8640B)


      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 ((char16_t)0x005f)
     24 #define AT_SIGN_CHAR    ((char16_t)64)
     25 #define PERIOD_CHAR     ((char16_t)46)
     26 
     27 U_NAMESPACE_BEGIN
     28 
     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, nullptr, status);
     48 }
     49 
     50 UObject*
     51 ICULocaleService::get(const Locale& locale, int32_t kind, UErrorCode& status) const
     52 {
     53    return get(locale, kind, nullptr, 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 = nullptr;
     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 == nullptr) {
     77                result = getKey(*key, status);
     78            } else {
     79                UnicodeString temp;
     80                result = getKey(*key, &temp, status);
     81 
     82                if (result != nullptr) {
     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 != nullptr) {
    121        return registerFactory(factory, status);
    122    }
    123    delete objToAdopt;
    124    return nullptr;
    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 != nullptr) {
    147        return registerFactory(factory, status);
    148    }
    149    delete objToAdopt;
    150    return nullptr;
    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, nullptr, 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, nullptr, 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                LocalPointer<UnicodeString> clonedId(static_cast<UnicodeString*>(other._ids.elementAt(i))->clone(), status);
    183                _ids.adoptElement(clonedId.orphan(), status);
    184            }
    185 
    186            if(U_SUCCESS(status)) {
    187                _pos = other._pos;
    188            }
    189        }
    190    }
    191 
    192 public:
    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)) {
    197            return result;
    198        }
    199        delete result;
    200        return nullptr;
    201    }
    202 
    203    virtual ~ServiceEnumeration();
    204 
    205    virtual StringEnumeration *clone() const override {
    206        UErrorCode status = U_ZERO_ERROR;
    207        ServiceEnumeration *cl = new ServiceEnumeration(*this, status);
    208        if(U_FAILURE(status)) {
    209            delete cl;
    210            cl = nullptr;
    211        }
    212        return cl;
    213    }
    214 
    215    UBool upToDate(UErrorCode& status) const {
    216        if (U_SUCCESS(status)) {
    217            if (_timestamp == _service->getTimestamp()) {
    218                return true;
    219            }
    220            status = U_ENUM_OUT_OF_SYNC_ERROR;
    221        }
    222        return false;
    223    }
    224 
    225    virtual int32_t count(UErrorCode& status) const override {
    226        return upToDate(status) ? _ids.size() : 0;
    227    }
    228 
    229    virtual const UnicodeString* snext(UErrorCode& status) override {
    230        if (upToDate(status) && (_pos < _ids.size())) {
    231            return static_cast<const UnicodeString*>(_ids[_pos++]);
    232        }
    233        return nullptr;
    234    }
    235 
    236    virtual void reset(UErrorCode& status) override {
    237        if (status == U_ENUM_OUT_OF_SYNC_ERROR) {
    238            status = U_ZERO_ERROR;
    239        }
    240        if (U_SUCCESS(status)) {
    241            _timestamp = _service->getTimestamp();
    242            _pos = 0;
    243            _service->getVisibleIDs(_ids, status);
    244        }
    245    }
    246 
    247 public:
    248    static UClassID U_EXPORT2 getStaticClassID();
    249    virtual UClassID getDynamicClassID() const override;
    250 };
    251 
    252 ServiceEnumeration::~ServiceEnumeration() {}
    253 
    254 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ServiceEnumeration)
    255 
    256 StringEnumeration*
    257 ICULocaleService::getAvailableLocales() const
    258 {
    259    return ServiceEnumeration::create(this);
    260 }
    261 
    262 const UnicodeString&
    263 ICULocaleService::validateFallbackLocale() const
    264 {
    265    const Locale&     loc    = Locale::getDefault();
    266    ICULocaleService* ncThis = const_cast<ICULocaleService*>(this);
    267    static UMutex llock;
    268    {
    269        Mutex mutex(&llock);
    270        if (loc != fallbackLocale) {
    271            ncThis->fallbackLocale = loc;
    272            LocaleUtility::initNameFromLocale(loc, ncThis->fallbackLocaleName);
    273            ncThis->clearServiceCache();
    274        }
    275    }
    276    return fallbackLocaleName;
    277 }
    278 
    279 ICUServiceKey*
    280 ICULocaleService::createKey(const UnicodeString* id, UErrorCode& status) const
    281 {
    282    return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), status);
    283 }
    284 
    285 ICUServiceKey*
    286 ICULocaleService::createKey(const UnicodeString* id, int32_t kind, UErrorCode& status) const
    287 {
    288    return LocaleKey::createWithCanonicalFallback(id, &validateFallbackLocale(), kind, status);
    289 }
    290 
    291 U_NAMESPACE_END
    292 
    293 /* !UCONFIG_NO_SERVICE */
    294 #endif