X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/4388f060552cc537e71e957d32f35e9d75a61233..51004dcb01e06fef634b61be77ed73dd61cb6db9:/icuSources/i18n/tznames_impl.cpp?ds=sidebyside diff --git a/icuSources/i18n/tznames_impl.cpp b/icuSources/i18n/tznames_impl.cpp index a699ec8c..e3b0c3c0 100644 --- a/icuSources/i18n/tznames_impl.cpp +++ b/icuSources/i18n/tznames_impl.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 2011-2012, International Business Machines Corporation and +* Copyright (C) 2011-2013, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* * @@ -46,6 +46,7 @@ static const char EMPTY[] = ""; // place holder for empty static const UTimeZoneNameType ALL_NAME_TYPES[] = { UTZNM_LONG_GENERIC, UTZNM_LONG_STANDARD, UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_GENERIC, UTZNM_SHORT_STANDARD, UTZNM_SHORT_DAYLIGHT, + UTZNM_EXEMPLAR_LOCATION, UTZNM_UNKNOWN // unknown as the last one }; @@ -282,7 +283,7 @@ TextTrieMap::getChildNode(CharacterNode *parent, UChar c) const { } // Mutex for protecting the lazy creation of the Trie node structure on the first call to search(). -static UMTX TextTrieMutex; +static UMutex TextTrieMutex = U_MUTEX_INITIALIZER; // buildTrie() - The Trie node structure is needed. Create it from the data that was // saved at the time the ZoneStringFormatter was created. The Trie is only @@ -489,7 +490,7 @@ public: virtual ~ZNames(); static ZNames* createInstance(UResourceBundle* rb, const char* key); - const UChar* getName(UTimeZoneNameType type); + virtual const UChar* getName(UTimeZoneNameType type); protected: ZNames(const UChar** names); @@ -544,6 +545,7 @@ ZNames::getName(UTimeZoneNameType type) { case UTZNM_SHORT_DAYLIGHT: name = fNames[5]; break; + case UTZNM_EXEMPLAR_LOCATION: // implemeted by subclass default: name = NULL; } @@ -594,48 +596,80 @@ class TZNames : public ZNames { public: virtual ~TZNames(); - static TZNames* createInstance(UResourceBundle* rb, const char* key); - const UChar* getLocationName(void); + static TZNames* createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID); + virtual const UChar* getName(UTimeZoneNameType type); private: - TZNames(const UChar** names, const UChar* locationName); + TZNames(const UChar** names); const UChar* fLocationName; + UChar* fLocationNameOwned; }; -TZNames::TZNames(const UChar** names, const UChar* locationName) -: ZNames(names), fLocationName(locationName) { +TZNames::TZNames(const UChar** names) +: ZNames(names), fLocationName(NULL), fLocationNameOwned(NULL) { } TZNames::~TZNames() { + if (fLocationNameOwned) { + uprv_free(fLocationNameOwned); + } } const UChar* -TZNames::getLocationName() { - return fLocationName; +TZNames::getName(UTimeZoneNameType type) { + if (type == UTZNM_EXEMPLAR_LOCATION) { + return fLocationName; + } + return ZNames::getName(type); } TZNames* -TZNames::createInstance(UResourceBundle* rb, const char* key) { +TZNames::createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID) { if (rb == NULL || key == NULL || *key == 0) { return NULL; } - TZNames* tznames = NULL; + + const UChar** names = loadData(rb, key); + const UChar* locationName = NULL; + UChar* locationNameOwned = NULL; + UErrorCode status = U_ZERO_ERROR; - UResourceBundle* rbTable = ures_getByKeyWithFallback(rb, key, NULL, &status); - if (U_SUCCESS(status)) { - int32_t len = 0; - const UChar* locationName = ures_getStringByKeyWithFallback(rbTable, gEcTag, &len, &status); - if (U_FAILURE(status) || len == 0) { - locationName = NULL; + int32_t len = 0; + + UResourceBundle* table = ures_getByKeyWithFallback(rb, key, NULL, &status); + locationName = ures_getStringByKeyWithFallback(table, gEcTag, &len, &status); + // ignore missing resource here + status = U_ZERO_ERROR; + + ures_close(table); + + if (locationName == NULL) { + UnicodeString tmpName; + int32_t tmpNameLen = 0; + TimeZoneNamesImpl::getDefaultExemplarLocationName(tzID, tmpName); + tmpNameLen = tmpName.length(); + + if (tmpNameLen > 0) { + locationNameOwned = (UChar*) uprv_malloc(sizeof(UChar) * (tmpNameLen + 1)); + if (locationNameOwned) { + tmpName.extract(locationNameOwned, tmpNameLen + 1, status); + locationName = locationNameOwned; + } } + } - const UChar** names = loadData(rb, key); - - if (locationName != NULL || names != NULL) { - tznames = new TZNames(names, locationName); + TZNames* tznames = NULL; + if (locationName != NULL || names != NULL) { + tznames = new TZNames(names); + if (tznames == NULL) { + if (locationNameOwned) { + uprv_free(locationNameOwned); + } } + tznames->fLocationName = locationName; + tznames->fLocationNameOwned = locationNameOwned; } - ures_close(rbTable); + return tznames; } @@ -837,9 +871,10 @@ deleteZNameInfo(void *obj) { U_CDECL_END +static UMutex gLock = U_MUTEX_INITIALIZER; + TimeZoneNamesImpl::TimeZoneNamesImpl(const Locale& locale, UErrorCode& status) : fLocale(locale), - fLock(NULL), fZoneStrings(NULL), fTZNamesMap(NULL), fMZNamesMap(NULL), @@ -911,7 +946,6 @@ TimeZoneNamesImpl::loadStrings(const UnicodeString& tzCanonicalID) { TimeZoneNamesImpl::~TimeZoneNamesImpl() { cleanup(); - umtx_destroy(&fLock); } void @@ -1015,11 +1049,11 @@ TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID, ZNames *znames = NULL; TimeZoneNamesImpl *nonConstThis = const_cast(this); - umtx_lock(&nonConstThis->fLock); + umtx_lock(&gLock); { znames = nonConstThis->loadMetaZoneNames(mzID); } - umtx_unlock(&nonConstThis->fLock); + umtx_unlock(&gLock); if (znames != NULL) { const UChar* s = znames->getName(type); @@ -1040,11 +1074,11 @@ TimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNa TZNames *tznames = NULL; TimeZoneNamesImpl *nonConstThis = const_cast(this); - umtx_lock(&nonConstThis->fLock); + umtx_lock(&gLock); { tznames = nonConstThis->loadTimeZoneNames(tzID); } - umtx_unlock(&nonConstThis->fLock); + umtx_unlock(&gLock); if (tznames != NULL) { const UChar *s = tznames->getName(type); @@ -1057,25 +1091,25 @@ TimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNa UnicodeString& TimeZoneNamesImpl::getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const { + name.setToBogus(); // cleanup result. const UChar* locName = NULL; TZNames *tznames = NULL; TimeZoneNamesImpl *nonConstThis = const_cast(this); - umtx_lock(&nonConstThis->fLock); + umtx_lock(&gLock); { tznames = nonConstThis->loadTimeZoneNames(tzID); } - umtx_unlock(&nonConstThis->fLock); + umtx_unlock(&gLock); if (tznames != NULL) { - locName = tznames->getLocationName(); + locName = tznames->getName(UTZNM_EXEMPLAR_LOCATION); } if (locName != NULL) { name.setTo(TRUE, locName, -1); - return name; } - return TimeZoneNames::getExemplarLocationName(tzID, name); + return name; } @@ -1193,7 +1227,7 @@ TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) { } } uKey.extract(0, uKey.length(), key, sizeof(key), US_INV); - tznames = TZNames::createInstance(fZoneStrings, key); + tznames = TZNames::createInstance(fZoneStrings, key, tzID); if (tznames == NULL) { cacheVal = (void *)EMPTY; @@ -1246,11 +1280,11 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types TimeZoneNamesImpl *nonConstThis = const_cast(this); - umtx_lock(&nonConstThis->fLock); + umtx_lock(&gLock); { fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); } - umtx_unlock(&nonConstThis->fLock); + umtx_unlock(&gLock); if (U_FAILURE(status)) { return NULL; @@ -1266,7 +1300,7 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types delete matches; // All names are not yet loaded into the trie - umtx_lock(&nonConstThis->fLock); + umtx_lock(&gLock); { if (!fNamesTrieFullyLoaded) { const UnicodeString *id; @@ -1290,22 +1324,48 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types } } } - umtx_unlock(&nonConstThis->fLock); + umtx_unlock(&gLock); if (U_FAILURE(status)) { return NULL; } - umtx_lock(&nonConstThis->fLock); + umtx_lock(&gLock); { // now try it again fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); } - umtx_unlock(&nonConstThis->fLock); + umtx_unlock(&gLock); return handler.getMatches(maxLen); } +static const UChar gEtcPrefix[] = { 0x45, 0x74, 0x63, 0x2F }; // "Etc/" +static const int32_t gEtcPrefixLen = 4; +static const UChar gSystemVPrefix[] = { 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x56, 0x2F }; // "SystemV/ +static const int32_t gSystemVPrefixLen = 8; +static const UChar gRiyadh8[] = { 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, 0x38 }; // "Riyadh8" +static const int32_t gRiyadh8Len = 7; + +UnicodeString& U_EXPORT2 +TimeZoneNamesImpl::getDefaultExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) { + if (tzID.isEmpty() || tzID.startsWith(gEtcPrefix, gEtcPrefixLen) + || tzID.startsWith(gSystemVPrefix, gSystemVPrefixLen) || tzID.indexOf(gRiyadh8, gRiyadh8Len, 0) > 0) { + name.setToBogus(); + return name; + } + + int32_t sep = tzID.lastIndexOf((UChar)0x2F /* '/' */); + if (sep > 0 && sep + 1 < tzID.length()) { + name.setTo(tzID, sep + 1); + name.findAndReplace(UnicodeString((UChar)0x5f /* _ */), + UnicodeString((UChar)0x20 /* space */)); + } else { + name.setToBogus(); + } + return name; +} + U_NAMESPACE_END