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