Home | History | Annotate | Download | only in common
      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 
    295