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