1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/* 2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho******************************************************************************* 31b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 2011-2015, International Business Machines Corporation and 4103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius* others. All Rights Reserved. 5b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho******************************************************************************* 6b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*/ 7b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 8b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/utypes.h" 9b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 10b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if !UCONFIG_NO_FORMATTING 11b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 12b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "tzgnames.h" 13b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 14b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/basictz.h" 15b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/locdspnm.h" 16b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/msgfmt.h" 17b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/rbtz.h" 18b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/simpletz.h" 19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/vtzone.h" 20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "cmemory.h" 22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "cstring.h" 2359d709d503bab6e2b61931737e662dd293b40578ccornelius#include "mutex.h" 24b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uhash.h" 25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uassert.h" 26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "umutex.h" 27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uresimp.h" 28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ureslocs.h" 29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "zonemeta.h" 30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "tznames_impl.h" 31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "olsontz.h" 32103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "ucln_in.h" 33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_BEGIN 35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define ZID_KEY_MAX 128 37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gZoneStrings[] = "zoneStrings"; 39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gRegionFormatTag[] = "regionFormat"; 41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gFallbackFormatTag[] = "fallbackFormat"; 42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gEmpty[] = {0x00}; 44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gDefRegionPattern[] = {0x7B, 0x30, 0x7D, 0x00}; // "{0}" 46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gDefFallbackPattern[] = {0x7B, 0x31, 0x7D, 0x20, 0x28, 0x7B, 0x30, 0x7D, 0x29, 0x00}; // "{1} ({0})" 47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 48b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const double kDstCheckRange = (double)184*U_MILLIS_PER_DAY; 49b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN 53b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct PartialLocationKey { 55b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* tzID; 56b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* mzID; 57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool isLong; 58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} PartialLocationKey; 59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/** 61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Hash function for partial location name hash key 62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t U_CALLCONV 64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehohashPartialLocationKey(const UHashTok key) { 65b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // <tzID>&<mzID>#[L|S] 66b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho PartialLocationKey *p = (PartialLocationKey *)key.pointer; 67b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString str(p->tzID); 68b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho str.append((UChar)0x26) 69103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius .append(p->mzID, -1) 70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho .append((UChar)0x23) 71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho .append((UChar)(p->isLong ? 0x4C : 0x53)); 72103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return str.hashCode(); 73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/** 76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Comparer for partial location name hash key 77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool U_CALLCONV 79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehocomparePartialLocationKey(const UHashTok key1, const UHashTok key2) { 80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho PartialLocationKey *p1 = (PartialLocationKey *)key1.pointer; 81b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho PartialLocationKey *p2 = (PartialLocationKey *)key2.pointer; 82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 83b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (p1 == p2) { 84b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return TRUE; 85b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (p1 == NULL || p2 == NULL) { 87b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return FALSE; 88b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 89b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // We just check identity of tzID/mzID 90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return (p1->tzID == p2->tzID && p1->mzID == p2->mzID && p1->isLong == p2->isLong); 91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/** 94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for GNameInfo 95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV 97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteGNameInfo(void *obj) { 98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(obj); 99b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/** 102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * GNameInfo stores zone name information in the local trie 103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct GNameInfo { 105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UTimeZoneGenericNameType type; 106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* tzID; 107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZNameInfo; 108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/** 110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * GMatchInfo stores zone name match information used by find method 111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct GMatchInfo { 113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const GNameInfo* gnameInfo; 114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t matchLength; 115103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UTimeZoneFormatTimeType timeType; 116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZMatchInfo; 117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END 119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// --------------------------------------------------- 121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// The class stores time zone generic name match information 122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// --------------------------------------------------- 123103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusclass TimeZoneGenericNameMatchInfo : public UMemory { 124103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliuspublic: 125103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TimeZoneGenericNameMatchInfo(UVector* matches); 126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius ~TimeZoneGenericNameMatchInfo(); 127103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 128103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t size() const; 129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UTimeZoneGenericNameType getGenericNameType(int32_t index) const; 130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t getMatchLength(int32_t index) const; 131103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& getTimeZoneID(int32_t index, UnicodeString& tzID) const; 132103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusprivate: 134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UVector* fMatches; // vector of MatchEntry 135103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}; 136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::TimeZoneGenericNameMatchInfo(UVector* matches) 138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fMatches(matches) { 139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::~TimeZoneGenericNameMatchInfo() { 142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fMatches != NULL) { 143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete fMatches; 144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t 148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::size() const { 149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fMatches == NULL) { 150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return fMatches->size(); 153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUTimeZoneGenericNameType 156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::getGenericNameType(int32_t index) const { 157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GMatchInfo *minfo = (GMatchInfo *)fMatches->elementAt(index); 158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (minfo != NULL) { 159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return static_cast<UTimeZoneGenericNameType>(minfo->gnameInfo->type); 160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return UTZGNM_UNKNOWN; 162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t 165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::getMatchLength(int32_t index) const { 166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ZMatchInfo *minfo = (ZMatchInfo *)fMatches->elementAt(index); 167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (minfo != NULL) { 168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return minfo->matchLength; 169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return -1; 171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& 174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::getTimeZoneID(int32_t index, UnicodeString& tzID) const { 175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GMatchInfo *minfo = (GMatchInfo *)fMatches->elementAt(index); 176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (minfo != NULL && minfo->gnameInfo->tzID != NULL) { 177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzID.setTo(TRUE, minfo->gnameInfo->tzID, -1); 178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzID.setToBogus(); 180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return tzID; 182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// --------------------------------------------------- 185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// GNameSearchHandler 186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// --------------------------------------------------- 187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass GNameSearchHandler : public TextTrieMapSearchResultHandler { 188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic: 189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GNameSearchHandler(uint32_t types); 190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho virtual ~GNameSearchHandler(); 191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status); 193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UVector* getMatches(int32_t& maxMatchLen); 194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate: 196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uint32_t fTypes; 197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UVector* fResults; 198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t fMaxMatchLen; 199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}; 200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::GNameSearchHandler(uint32_t types) 202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fTypes(types), fResults(NULL), fMaxMatchLen(0) { 203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::~GNameSearchHandler() { 206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fResults != NULL) { 207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete fResults; 208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool 212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) { 213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return FALSE; 215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (node->hasValues()) { 217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t valuesCount = node->countValues(); 218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (int32_t i = 0; i < valuesCount; i++) { 219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GNameInfo *nameinfo = (ZNameInfo *)node->getValue(i); 220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (nameinfo == NULL) { 221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if ((nameinfo->type & fTypes) != 0) { 224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // matches a requested type 225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fResults == NULL) { 226103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fResults = new UVector(uprv_free, NULL, status); 227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fResults == NULL) { 228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 232103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(fResults != NULL); 233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GMatchInfo *gmatch = (GMatchInfo *)uprv_malloc(sizeof(GMatchInfo)); 234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gmatch == NULL) { 235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // add the match to the vector 238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gmatch->gnameInfo = nameinfo; 239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gmatch->matchLength = matchLength; 240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gmatch->timeType = UTZFMT_TIME_TYPE_UNKNOWN; 241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fResults->addElement(gmatch, status); 242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(gmatch); 244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (matchLength > fMaxMatchLen) { 246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fMaxMatchLen = matchLength; 247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return TRUE; 255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUVector* 258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::getMatches(int32_t& maxMatchLen) { 259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // give the ownership to the caller 260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UVector *results = fResults; 261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho maxMatchLen = fMaxMatchLen; 262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // reset 264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fResults = NULL; 265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fMaxMatchLen = 0; 266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return results; 267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 26954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gLock = U_MUTEX_INITIALIZER; 27054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusclass TZGNCore : public UMemory { 272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliuspublic: 273103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCore(const Locale& locale, UErrorCode& status); 274103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius virtual ~TZGNCore(); 275103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 276103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type, 277103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate date, UnicodeString& name) const; 278103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 279103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const; 280103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 281103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t findBestMatch(const UnicodeString& text, int32_t start, uint32_t types, 282103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const; 283103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 284103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusprivate: 285103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius Locale fLocale; 286103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const TimeZoneNames* fTimeZoneNames; 287103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UHashtable* fLocationNamesMap; 288103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UHashtable* fPartialLocationNamesMap; 289103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 290103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius MessageFormat* fRegionFormat; 291103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius MessageFormat* fFallbackFormat; 292103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 293103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius LocaleDisplayNames* fLocaleDisplayNames; 294103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius ZNStringPool fStringPool; 295103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 296103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TextTrieMap fGNamesTrie; 297103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool fGNamesTrieFullyLoaded; 298103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 299103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius char fTargetRegion[ULOC_COUNTRY_CAPACITY]; 300103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 301103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius void initialize(const Locale& locale, UErrorCode& status); 302103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius void cleanup(); 303103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 304103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius void loadStrings(const UnicodeString& tzCanonicalID); 305103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 306103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const UChar* getGenericLocationName(const UnicodeString& tzCanonicalID); 307103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 308103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type, 309103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate date, UnicodeString& name) const; 310103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 311103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& getPartialLocationName(const UnicodeString& tzCanonicalID, 312103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName, 313103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& name) const; 314103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 315103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const UChar* getPartialLocationName(const UnicodeString& tzCanonicalID, 316103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName); 317103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 318103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TimeZoneGenericNameMatchInfo* findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const; 319103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 320103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TimeZoneNames::MatchInfoCollection* findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const; 321103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}; 322103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 323103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// --------------------------------------------------- 325103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// TZGNCore - core implmentation of TimeZoneGenericNames 326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// 327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneGenericNames is parallel to TimeZoneNames, 328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// but handles run-time generated time zone names. 329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// This is the main part of this module. 330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// --------------------------------------------------- 331103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::TZGNCore(const Locale& locale, UErrorCode& status) 332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLocale(locale), 333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames(NULL), 334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fLocationNamesMap(NULL), 335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fPartialLocationNamesMap(NULL), 336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fRegionFormat(NULL), 337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fFallbackFormat(NULL), 338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fLocaleDisplayNames(NULL), 339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fStringPool(status), 340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fGNamesTrie(TRUE, deleteGNameInfo), 341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fGNamesTrieFullyLoaded(FALSE) { 342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho initialize(locale, status); 343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 345103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::~TZGNCore() { 346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cleanup(); 347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid 350103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::initialize(const Locale& locale, UErrorCode& status) { 351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // TimeZoneNames 356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames = TimeZoneNames::createInstance(locale, status); 357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Initialize format patterns 362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString rpat(TRUE, gDefRegionPattern, -1); 363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString fpat(TRUE, gDefFallbackPattern, -1); 364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode tmpsts = U_ZERO_ERROR; // OK with fallback warning.. 366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle *zoneStrings = ures_open(U_ICUDATA_ZONE, locale.getName(), &tmpsts); 367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho zoneStrings = ures_getByKeyWithFallback(zoneStrings, gZoneStrings, zoneStrings, &tmpsts); 368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpsts)) { 370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *regionPattern = ures_getStringByKeyWithFallback(zoneStrings, gRegionFormatTag, NULL, &tmpsts); 371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpsts) && u_strlen(regionPattern) > 0) { 372103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius rpat.setTo(regionPattern, -1); 373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpsts = U_ZERO_ERROR; 375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *fallbackPattern = ures_getStringByKeyWithFallback(zoneStrings, gFallbackFormatTag, NULL, &tmpsts); 376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpsts) && u_strlen(fallbackPattern) > 0) { 377103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fpat.setTo(fallbackPattern, -1); 378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(zoneStrings); 381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fRegionFormat = new MessageFormat(rpat, status); 383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fRegionFormat == NULL) { 384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fFallbackFormat = new MessageFormat(fpat, status); 387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fFallbackFormat == NULL) { 388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cleanup(); 392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // locale display names 396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fLocaleDisplayNames = LocaleDisplayNames::createInstance(locale); 397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // hash table for names - no key/value deleters 399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fLocationNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cleanup(); 402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fPartialLocationNamesMap = uhash_open(hashPartialLocationKey, comparePartialLocationKey, NULL, &status); 406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cleanup(); 408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 410103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uhash_setKeyDeleter(fPartialLocationNamesMap, uprv_free); 411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // no value deleter 412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // target region 414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const char* region = fLocale.getCountry(); 415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t regionLen = uprv_strlen(region); 416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (regionLen == 0) { 417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char loc[ULOC_FULLNAME_CAPACITY]; 418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status); 419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho regionLen = uloc_getCountry(loc, fTargetRegion, sizeof(fTargetRegion), &status); 421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTargetRegion[regionLen] = 0; 423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cleanup(); 425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return; 426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else if (regionLen < (int32_t)sizeof(fTargetRegion)) { 428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_strcpy(fTargetRegion, region); 429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTargetRegion[0] = 0; 431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // preload generic names for the default zone 434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZone *tz = TimeZone::createDefault(); 435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz); 436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzID != NULL) { 4371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert loadStrings(UnicodeString(TRUE, tzID, -1)); 438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete tz; 440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid 443103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::cleanup() { 444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fRegionFormat != NULL) { 445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete fRegionFormat; 446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fFallbackFormat != NULL) { 448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete fFallbackFormat; 449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fLocaleDisplayNames != NULL) { 451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete fLocaleDisplayNames; 452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (fTimeZoneNames != NULL) { 454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete fTimeZoneNames; 455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(fLocationNamesMap); 458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(fPartialLocationNamesMap); 459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 461103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& 463103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const { 464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho switch (type) { 466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case UTZGNM_LOCATION: 467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* tzCanonicalID = ZoneMeta::getCanonicalCLDRID(tz); 469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID != NULL) { 4701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert getGenericLocationName(UnicodeString(TRUE, tzCanonicalID, -1), name); 471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case UTZGNM_LONG: 475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case UTZGNM_SHORT: 476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho formatGenericNonLocationName(tz, type, date, name); 477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (name.isEmpty()) { 478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* tzCanonicalID = ZoneMeta::getCanonicalCLDRID(tz); 479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID != NULL) { 4801b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert getGenericLocationName(UnicodeString(TRUE, tzCanonicalID, -1), name); 481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho default: 485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& 491103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const { 492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID.isEmpty()) { 493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *locname = NULL; 498103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCore *nonConstThis = const_cast<TZGNCore *>(this); 49954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_lock(&gLock); 500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho locname = nonConstThis->getGenericLocationName(tzCanonicalID); 502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 50354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_unlock(&gLock); 504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (locname == NULL) { 506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 508103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius name.setTo(locname, u_strlen(locname)); 509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/* 515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock 516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 518103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::getGenericLocationName(const UnicodeString& tzCanonicalID) { 519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(!tzCanonicalID.isEmpty()); 520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID.length() > ZID_KEY_MAX) { 521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar tzIDKey[ZID_KEY_MAX + 1]; 526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t tzIDKeyLen = tzCanonicalID.extract(tzIDKey, ZID_KEY_MAX + 1, status); 527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(status == U_ZERO_ERROR); // already checked length above 528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzIDKey[tzIDKeyLen] = 0; 529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *locname = (const UChar *)uhash_get(fLocationNamesMap, tzIDKey); 531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (locname != NULL) { 533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // gEmpty indicate the name is not available 534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (locname == gEmpty) { 535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return locname; 538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Construct location name 541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString name; 542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString usCountryCode; 5438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool isPrimary = FALSE; 5448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 5458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ZoneMeta::getCanonicalCountry(tzCanonicalID, usCountryCode, &isPrimary); 546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!usCountryCode.isEmpty()) { 5488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius FieldPosition fpos; 549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 5508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (isPrimary) { 5518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // If this is the primary zone in the country, use the country name. 5528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char countryCode[ULOC_COUNTRY_CAPACITY]; 5538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius U_ASSERT(usCountryCode.length() < ULOC_COUNTRY_CAPACITY); 5548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t ccLen = usCountryCode.extract(0, usCountryCode.length(), countryCode, sizeof(countryCode), US_INV); 5558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius countryCode[ccLen] = 0; 5568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 5578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UnicodeString country; 5588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius fLocaleDisplayNames->regionDisplayName(countryCode, country); 559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho Formattable param[] = { 561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho Formattable(country) 562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho }; 5638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fRegionFormat->format(param, 1, name, fpos, status); 565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 5668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // If this is not the primary zone in the country, 5678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // use the exemplar city name. 56854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // getExemplarLocationName should retur non-empty string 570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // if the time zone is associated with a region 57154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius 572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString city; 573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getExemplarLocationName(tzCanonicalID, city); 574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 57554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius Formattable param[] = { 576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho Formattable(city), 577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho }; 5788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 57954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius fRegionFormat->format(param, 1, name, fpos, status); 580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho locname = name.isEmpty() ? NULL : fStringPool.get(name, status); 587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Cache the result 589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* cacheID = ZoneMeta::findTimeZoneID(tzCanonicalID); 590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(cacheID != NULL); 591b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (locname == NULL) { 592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // gEmpty to indicate - no location name available 593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_put(fLocationNamesMap, (void *)cacheID, (void *)gEmpty, &status); 594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_put(fLocationNamesMap, (void *)cacheID, (void *)locname, &status); 596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho locname = NULL; 598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // put the name info into the trie 600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(GNameInfo)); 601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (nameinfo != NULL) { 602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nameinfo->type = UTZGNM_LOCATION; 603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nameinfo->tzID = cacheID; 604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fGNamesTrie.put(locname, nameinfo, status); 605b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return locname; 611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& 614103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const { 615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(type == UTZGNM_LONG || type == UTZGNM_SHORT); 616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* uID = ZoneMeta::getCanonicalCLDRID(tz); 619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uID == NULL) { 620b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 621b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 6231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnicodeString tzID(TRUE, uID, -1); 624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Try to get a name from time zone first 626b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UTimeZoneNameType nameType = (type == UTZGNM_LONG) ? UTZNM_LONG_GENERIC : UTZNM_SHORT_GENERIC; 627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getTimeZoneDisplayName(tzID, nameType, name); 628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!name.isEmpty()) { 630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Try meta zone 6341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UChar mzIDBuf[32]; 6351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnicodeString mzID(mzIDBuf, 0, UPRV_LENGTHOF(mzIDBuf)); 636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getMetaZoneID(tzID, date, mzID); 637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!mzID.isEmpty()) { 638b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 639b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool useStandard = FALSE; 640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t raw, sav; 6411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UChar tmpNameBuf[64]; 642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tz.getOffset(date, FALSE, raw, sav, status); 644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (sav == 0) { 649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho useStandard = TRUE; 650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZone *tmptz = tz.clone(); 652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check if the zone actually uses daylight saving time around the time 653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho BasicTimeZone *btz = NULL; 654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (dynamic_cast<OlsonTimeZone *>(tmptz) != NULL 655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho || dynamic_cast<SimpleTimeZone *>(tmptz) != NULL 656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho || dynamic_cast<RuleBasedTimeZone *>(tmptz) != NULL 657b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho || dynamic_cast<VTimeZone *>(tmptz) != NULL) { 658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho btz = (BasicTimeZone*)tmptz; 659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (btz != NULL) { 662b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZoneTransition before; 663b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool beforTrs = btz->getPreviousTransition(date, TRUE, before); 664b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (beforTrs 665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && (date - before.getTime() < kDstCheckRange) 666b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && before.getFrom()->getDSTSavings() != 0) { 667b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho useStandard = FALSE; 668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 669b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZoneTransition after; 670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool afterTrs = btz->getNextTransition(date, FALSE, after); 671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (afterTrs 672b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && (after.getTime() - date < kDstCheckRange) 673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho && after.getTo()->getDSTSavings() != 0) { 674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho useStandard = FALSE; 675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 676b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 677b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 678b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If not BasicTimeZone... only if the instance is not an ICU's implementation. 679b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // We may get a wrong answer in edge case, but it should practically work OK. 680b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmptz->getOffset(date - kDstCheckRange, FALSE, raw, sav, status); 681b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (sav != 0) { 682b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho useStandard = FALSE; 683b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 684b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmptz->getOffset(date + kDstCheckRange, FALSE, raw, sav, status); 685b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (sav != 0){ 686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho useStandard = FALSE; 687b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 688b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete tmptz; 691b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 692b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 693b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 694b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete tmptz; 695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 696b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (useStandard) { 697b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UTimeZoneNameType stdNameType = (nameType == UTZNM_LONG_GENERIC) 698103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius ? UTZNM_LONG_STANDARD : UTZNM_SHORT_STANDARD; 6991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnicodeString stdName(tmpNameBuf, 0, UPRV_LENGTHOF(tmpNameBuf)); 700b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getDisplayName(tzID, stdNameType, date, stdName); 701b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!stdName.isEmpty()) { 702b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setTo(stdName); 703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 704b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // TODO: revisit this issue later 705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // In CLDR, a same display name is used for both generic and standard 706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // for some meta zones in some locales. This looks like a data bugs. 707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // For now, we check if the standard name is different from its generic 708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // name below. 7091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UChar genNameBuf[64]; 7101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnicodeString mzGenericName(genNameBuf, 0, UPRV_LENGTHOF(genNameBuf)); 711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getMetaZoneDisplayName(mzID, nameType, mzGenericName); 712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (stdName.caseCompare(mzGenericName, 0) == 0) { 713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (name.isEmpty()) { 718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Get a name from meta zone 7191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnicodeString mzName(tmpNameBuf, 0, UPRV_LENGTHOF(tmpNameBuf)); 720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getMetaZoneDisplayName(mzID, nameType, mzName); 721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!mzName.isEmpty()) { 722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check if we need to use a partial location format. 723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // This check is done by comparing offset with the meta zone's 724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // golden zone at the given date. 7251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UChar idBuf[32]; 7261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UnicodeString goldenID(idBuf, 0, UPRV_LENGTHOF(idBuf)); 727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, goldenID); 728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!goldenID.isEmpty() && goldenID != tzID) { 729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZone *goldenZone = TimeZone::createTimeZone(goldenID); 730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t raw1, sav1; 731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check offset in the golden zone with wall time. 733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // With getOffset(date, false, offsets1), 734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // you may get incorrect results because of time overlap at DST->STD 735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // transition. 736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho goldenZone->getOffset(date + raw + sav, TRUE, raw1, sav1, status); 737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete goldenZone; 738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (raw != raw1 || sav != sav1) { 740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Now we need to use a partial location format 741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho getPartialLocationName(tzID, mzID, (nameType == UTZNM_LONG_GENERIC), mzName, name); 742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setTo(mzName); 744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setTo(mzName); 748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& 756103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID, 757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName, 758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString& name) const { 759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID.isEmpty() || mzID.isEmpty() || mzDisplayName.isEmpty()) { 761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *uplname = NULL; 765103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCore *nonConstThis = const_cast<TZGNCore *>(this); 76654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_lock(&gLock); 767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uplname = nonConstThis->getPartialLocationName(tzCanonicalID, mzID, isLong, mzDisplayName); 769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 77054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_unlock(&gLock); 771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uplname == NULL) { 773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setToBogus(); 774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho name.setTo(TRUE, uplname, -1); 776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return name; 778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/* 781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock 782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 784103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID, 785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName) { 786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(!tzCanonicalID.isEmpty()); 787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(!mzID.isEmpty()); 788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(!mzDisplayName.isEmpty()); 789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho PartialLocationKey key; 791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho key.tzID = ZoneMeta::findTimeZoneID(tzCanonicalID); 792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho key.mzID = ZoneMeta::findMetaZoneID(mzID); 793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho key.isLong = isLong; 794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(key.tzID != NULL && key.mzID != NULL); 795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* uplname = (const UChar*)uhash_get(fPartialLocationNamesMap, (void *)&key); 797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uplname != NULL) { 798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return uplname; 799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString location; 802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString usCountryCode; 803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ZoneMeta::getCanonicalCountry(tzCanonicalID, usCountryCode); 804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!usCountryCode.isEmpty()) { 805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char countryCode[ULOC_COUNTRY_CAPACITY]; 806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(usCountryCode.length() < ULOC_COUNTRY_CAPACITY); 807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t ccLen = usCountryCode.extract(0, usCountryCode.length(), countryCode, sizeof(countryCode), US_INV); 808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho countryCode[ccLen] = 0; 809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString regionalGolden; 811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getReferenceZoneID(mzID, countryCode, regionalGolden); 812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID == regionalGolden) { 813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Use country name 814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fLocaleDisplayNames->regionDisplayName(countryCode, location); 815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Otherwise, use exemplar city name 817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getExemplarLocationName(tzCanonicalID, location); 818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getExemplarLocationName(tzCanonicalID, location); 821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (location.isEmpty()) { 822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // This could happen when the time zone is not associated with a country, 823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // and its ID is not hierarchical, for example, CST6CDT. 824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // We use the canonical ID itself as the location for this case. 825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho location.setTo(tzCanonicalID); 826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString name; 831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho FieldPosition fpos; 833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho Formattable param[] = { 834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho Formattable(location), 835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho Formattable(mzDisplayName) 836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho }; 837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fFallbackFormat->format(param, 2, name, fpos, status); 838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uplname = fStringPool.get(name, status); 843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Add the name to cache 845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho PartialLocationKey* cacheKey = (PartialLocationKey *)uprv_malloc(sizeof(PartialLocationKey)); 846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (cacheKey != NULL) { 847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cacheKey->tzID = key.tzID; 848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cacheKey->mzID = key.mzID; 849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho cacheKey->isLong = key.isLong; 850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_put(fPartialLocationNamesMap, (void *)cacheKey, (void *)uplname, &status); 851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(cacheKey); 853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // put the name to the local trie as well 855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(GNameInfo)); 856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (nameinfo != NULL) { 857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nameinfo->type = isLong ? UTZGNM_LONG : UTZGNM_SHORT; 858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nameinfo->tzID = key.tzID; 859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fGNamesTrie.put(uplname, nameinfo, status); 860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return uplname; 865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/* 868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock, 869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * except initializer. 870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */ 871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid 872103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::loadStrings(const UnicodeString& tzCanonicalID) { 873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // load the generic location name 874b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho getGenericLocationName(tzCanonicalID); 875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // partial location names 877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UnicodeString *mzID; 880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString goldenID; 881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString mzGenName; 882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UTimeZoneNameType genNonLocTypes[] = { 883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UTZNM_LONG_GENERIC, UTZNM_SHORT_GENERIC, 884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UTZNM_UNKNOWN /*terminator*/ 885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho }; 886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho StringEnumeration *mzIDs = fTimeZoneNames->getAvailableMetaZoneIDs(tzCanonicalID, status); 888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while ((mzID = mzIDs->snext(status))) { 889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // if this time zone is not the golden zone of the meta zone, 893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // partial location name (such as "PT (Los Angeles)") might be 894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // available. 895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getReferenceZoneID(*mzID, fTargetRegion, goldenID); 896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzCanonicalID != goldenID) { 897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (int32_t i = 0; genNonLocTypes[i] != UTZNM_UNKNOWN; i++) { 898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fTimeZoneNames->getMetaZoneDisplayName(*mzID, genNonLocTypes[i], mzGenName); 899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!mzGenName.isEmpty()) { 900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // getPartialLocationName formats a name and put it into the trie 901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho getPartialLocationName(tzCanonicalID, *mzID, 902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho (genNonLocTypes[i] == UTZNM_LONG_GENERIC), mzGenName); 903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (mzIDs != NULL) { 908b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete mzIDs; 909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 910b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t 913103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types, 914103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const { 915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho timeType = UTZFMT_TIME_TYPE_UNKNOWN; 916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzID.setToBogus(); 917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 919b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 920b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Find matches in the TimeZoneNames first 923103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TimeZoneNames::MatchInfoCollection *tznamesMatches = findTimeZoneNames(text, start, types, status); 924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t bestMatchLen = 0; 929103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UTimeZoneFormatTimeType bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN; 930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString bestMatchTzID; 931103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // UBool isLongStandard = FALSE; // workaround - see the comments below 932103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool isStandard = FALSE; // TODO: Temporary hack (on hack) for short standard name/location name conflict (found in zh_Hant), should be removed after CLDR 21m1 integration 933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tznamesMatches != NULL) { 935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString mzID; 936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (int32_t i = 0; i < tznamesMatches->size(); i++) { 937103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t len = tznamesMatches->getMatchLengthAt(i); 938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len > bestMatchLen) { 939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bestMatchLen = len; 940103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (!tznamesMatches->getTimeZoneIDAt(i, bestMatchTzID)) { 941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // name for a meta zone 942103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (tznamesMatches->getMetaZoneIDAt(i, mzID)) { 943103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, bestMatchTzID); 944103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 945103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 946103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UTimeZoneNameType nameType = tznamesMatches->getNameTypeAt(i); 947103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_FAILURE(status)) { 948103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius break; 949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho switch (nameType) { 951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case UTZNM_LONG_STANDARD: 952103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // isLongStandard = TRUE; 953103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius case UTZNM_SHORT_STANDARD: // this one is never used for generic, but just in case 954103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius isStandard = TRUE; // TODO: Remove this later, see the comments above. 955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bestMatchTimeType = UTZFMT_TIME_TYPE_STANDARD; 956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case UTZNM_LONG_DAYLIGHT: 958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho case UTZNM_SHORT_DAYLIGHT: // this one is never used for generic, but just in case 959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bestMatchTimeType = UTZFMT_TIME_TYPE_DAYLIGHT; 960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho default: 962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN; 963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete tznamesMatches; 967103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_FAILURE(status)) { 968103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return 0; 969103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (bestMatchLen == (text.length() - start)) { 972b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Full match 973b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho //tzID.setTo(bestMatchTzID); 975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho //timeType = bestMatchTimeType; 976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho //return bestMatchLen; 977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 978b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // TODO Some time zone uses a same name for the long standard name 979b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // and the location name. When the match is a long standard name, 980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // then we need to check if the name is same with the location name. 981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // This is probably a data error or a design bug. 982103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/* 983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!isLongStandard) { 984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzID.setTo(bestMatchTzID); 985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho timeType = bestMatchTimeType; 986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return bestMatchLen; 987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 988103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius*/ 989103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // TODO The deprecation of commonlyUsed flag introduced the name 990103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // conflict not only for long standard names, but short standard names too. 991103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // These short names (found in zh_Hant) should be gone once we clean 992103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // up CLDR time zone display name data. Once the short name conflict 993103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // problem (with location name) is resolved, we should change the condition 994103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // below back to the original one above. -Yoshito (2011-09-14) 995103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (!isStandard) { 996103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tzID.setTo(bestMatchTzID); 997103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius timeType = bestMatchTimeType; 998103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return bestMatchLen; 999103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Find matches in the local trie 1004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZoneGenericNameMatchInfo *localMatches = findLocal(text, start, types, status); 1005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 1006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return 0; 1007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (localMatches != NULL) { 1009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho for (int32_t i = 0; i < localMatches->size(); i++) { 1010b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t len = localMatches->getMatchLength(i); 1011b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // TODO See the above TODO. We use len >= bestMatchLen 1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // because of the long standard/location name collision 1014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // problem. If it is also a location name, carrying 1015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // timeType = UTZFMT_TIME_TYPE_STANDARD will cause a 1016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // problem in SimpleDateFormat 1017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len >= bestMatchLen) { 1018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bestMatchLen = localMatches->getMatchLength(i); 1019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN; // because generic 1020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho localMatches->getTimeZoneID(i, bestMatchTzID); 1021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete localMatches; 1024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (bestMatchLen > 0) { 1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho timeType = bestMatchTimeType; 1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzID.setTo(bestMatchTzID); 1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return bestMatchLen; 1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo* 1034103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const { 1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho GNameSearchHandler handler(types); 1036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1037103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCore *nonConstThis = const_cast<TZGNCore *>(this); 1038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 103954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_lock(&gLock); 1040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 1041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); 1042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 104354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_unlock(&gLock); 1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 1046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 1047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho TimeZoneGenericNameMatchInfo *gmatchInfo = NULL; 1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t maxLen = 0; 1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UVector *results = handler.getMatches(maxLen); 1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (results != NULL && ((maxLen == (text.length() - start)) || fGNamesTrieFullyLoaded)) { 1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // perfect match 1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gmatchInfo = new TimeZoneGenericNameMatchInfo(results); 1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gmatchInfo == NULL) { 1057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete results; 1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return gmatchInfo; 1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (results != NULL) { 1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete results; 1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // All names are not yet loaded into the local trie. 1069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Load all available names into the trie. This could be very heavy. 107054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_lock(&gLock); 1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 1072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!fGNamesTrieFullyLoaded) { 1073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status); 1074b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 1075b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UnicodeString *tzID; 1076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while ((tzID = tzIDs->snext(status))) { 1077b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 1078b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 1079b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1080b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nonConstThis->loadStrings(*tzID); 1081b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1082b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (tzIDs != NULL) { 1084b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete tzIDs; 1085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1087b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 1088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nonConstThis->fGNamesTrieFullyLoaded = TRUE; 1089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 109254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_unlock(&gLock); 1093b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1094b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 1095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 1096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 109854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_lock(&gLock); 1099b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 1100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // now try it again 1101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); 1102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 110354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius umtx_unlock(&gLock); 1104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho results = handler.getMatches(maxLen); 1106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (results != NULL && maxLen > 0) { 1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gmatchInfo = new TimeZoneGenericNameMatchInfo(results); 1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gmatchInfo == NULL) { 1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete results; 1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 1112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return gmatchInfo; 1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1118103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames::MatchInfoCollection* 1119103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZGNCore::findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const { 1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check if the target name typs is really in the TimeZoneNames 1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uint32_t nameTypes = 0; 1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (types & UTZGNM_LONG) { 1123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho nameTypes |= (UTZNM_LONG_GENERIC | UTZNM_LONG_STANDARD); 1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (types & UTZGNM_SHORT) { 1126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius nameTypes |= (UTZNM_SHORT_GENERIC | UTZNM_SHORT_STANDARD); 1127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 1128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (types) { 1130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Find matches in the TimeZoneNames 1131103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fTimeZoneNames->find(text, start, nameTypes, status); 1132103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 1135103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1137103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliustypedef struct TZGNCoreRef { 1138103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCore* obj; 1139103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t refCount; 1140103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius double lastAccess; 1141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} TZGNCoreRef; 1142103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1143103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// TZGNCore object cache handling 114454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gTZGNLock = U_MUTEX_INITIALIZER; 1145103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic UHashtable *gTZGNCoreCache = NULL; 1146103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic UBool gTZGNCoreCacheInitialized = FALSE; 1147103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1148103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Access count - incremented every time up to SWEEP_INTERVAL, 1149103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// then reset to 0 1150103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t gAccessCount = 0; 1151103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1152103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Interval for calling the cache sweep function - every 100 times 1153103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#define SWEEP_INTERVAL 100 1154103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1155103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Cache expiration in millisecond. When a cached entry is no 1156103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// longer referenced and exceeding this threshold since last 1157103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// access time, then the cache entry will be deleted by the sweep 1158103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// function. For now, 3 minutes. 1159103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#define CACHE_EXPIRATION 180000.0 1160103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1161103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CDECL_BEGIN 1162103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/** 1163103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Cleanup callback func 1164103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */ 1165103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic UBool U_CALLCONV tzgnCore_cleanup(void) 1166103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{ 1167103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (gTZGNCoreCache != NULL) { 1168103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uhash_close(gTZGNCoreCache); 1169103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius gTZGNCoreCache = NULL; 1170103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1171103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius gTZGNCoreCacheInitialized = FALSE; 1172103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return TRUE; 1173103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1174103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1175103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/** 1176103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Deleter for TZGNCoreRef 1177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */ 1178103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic void U_CALLCONV 1179103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusdeleteTZGNCoreRef(void *obj) { 1180103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius icu::TZGNCoreRef *entry = (icu::TZGNCoreRef*)obj; 1181103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius delete (icu::TZGNCore*) entry->obj; 1182103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_free(entry); 1183103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1184103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CDECL_END 1185103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1186103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/** 1187103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Function used for removing unreferrenced cache entries exceeding 1188103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * the expiration time. This function must be called with in the mutex 1189103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * block. 1190103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */ 1191103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic void sweepCache() { 11921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t pos = UHASH_FIRST; 1193103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const UHashElement* elem; 1194103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius double now = (double)uprv_getUTCtime(); 1195103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1196103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius while ((elem = uhash_nextElement(gTZGNCoreCache, &pos))) { 1197103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCoreRef *entry = (TZGNCoreRef *)elem->value.pointer; 1198103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (entry->refCount <= 0 && (now - entry->lastAccess) > CACHE_EXPIRATION) { 1199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // delete this entry 1200103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uhash_removeElement(gTZGNCoreCache, elem); 1201103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1202103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1204103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1205103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::TimeZoneGenericNames() 1206103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius: fRef(0) { 1207103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1208103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1209103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::~TimeZoneGenericNames() { 1210103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius umtx_lock(&gTZGNLock); 1211103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius { 1212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius U_ASSERT(fRef->refCount > 0); 1213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Just decrement the reference count 1214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fRef->refCount--; 1215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius umtx_unlock(&gTZGNLock); 1217103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1218103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1219103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames* 1220103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) { 1221103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_FAILURE(status)) { 1222103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 1223103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1224103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TimeZoneGenericNames* instance = new TimeZoneGenericNames(); 1225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (instance == NULL) { 1226103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius status = U_MEMORY_ALLOCATION_ERROR; 1227103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 1228103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1229103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 123059d709d503bab6e2b61931737e662dd293b40578ccornelius TZGNCoreRef *cacheEntry = NULL; 123159d709d503bab6e2b61931737e662dd293b40578ccornelius { 123259d709d503bab6e2b61931737e662dd293b40578ccornelius Mutex lock(&gTZGNLock); 123359d709d503bab6e2b61931737e662dd293b40578ccornelius 123459d709d503bab6e2b61931737e662dd293b40578ccornelius if (!gTZGNCoreCacheInitialized) { 123559d709d503bab6e2b61931737e662dd293b40578ccornelius // Create empty hashtable 123659d709d503bab6e2b61931737e662dd293b40578ccornelius gTZGNCoreCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); 123759d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_SUCCESS(status)) { 123859d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setKeyDeleter(gTZGNCoreCache, uprv_free); 123959d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setValueDeleter(gTZGNCoreCache, deleteTZGNCoreRef); 124059d709d503bab6e2b61931737e662dd293b40578ccornelius gTZGNCoreCacheInitialized = TRUE; 124159d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEGENERICNAMES, tzgnCore_cleanup); 1242103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1243103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1244103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_FAILURE(status)) { 1245103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 1246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1247103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 124859d709d503bab6e2b61931737e662dd293b40578ccornelius // Check the cache, if not available, create new one and cache 1249103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius const char *key = locale.getName(); 1250103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry = (TZGNCoreRef *)uhash_get(gTZGNCoreCache, key); 1251103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (cacheEntry == NULL) { 1252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TZGNCore *tzgnCore = NULL; 1253103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius char *newKey = NULL; 1254103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1255103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tzgnCore = new TZGNCore(locale, status); 1256103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (tzgnCore == NULL) { 1257103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius status = U_MEMORY_ALLOCATION_ERROR; 1258103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1259103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_SUCCESS(status)) { 1260103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius newKey = (char *)uprv_malloc(uprv_strlen(key) + 1); 1261103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (newKey == NULL) { 1262103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius status = U_MEMORY_ALLOCATION_ERROR; 1263103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 1264103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_strcpy(newKey, key); 1265103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1266103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1267103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_SUCCESS(status)) { 1268103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry = (TZGNCoreRef *)uprv_malloc(sizeof(TZGNCoreRef)); 1269103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (cacheEntry == NULL) { 1270103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius status = U_MEMORY_ALLOCATION_ERROR; 1271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 1272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry->obj = tzgnCore; 1273103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry->refCount = 1; 1274103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry->lastAccess = (double)uprv_getUTCtime(); 1275103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1276103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uhash_put(gTZGNCoreCache, newKey, cacheEntry, &status); 1277103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1278103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1279103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (U_FAILURE(status)) { 1280103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (tzgnCore != NULL) { 1281103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius delete tzgnCore; 1282103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1283103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (newKey != NULL) { 1284103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_free(newKey); 1285103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1286103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (cacheEntry != NULL) { 1287103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius uprv_free(cacheEntry); 1288103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1289103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry = NULL; 1290103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1291103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 1292103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Update the reference count 1293103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry->refCount++; 1294103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius cacheEntry->lastAccess = (double)uprv_getUTCtime(); 1295103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1296103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius gAccessCount++; 1297103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (gAccessCount >= SWEEP_INTERVAL) { 1298103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // sweep 1299103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius sweepCache(); 1300103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius gAccessCount = 0; 1301103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 130259d709d503bab6e2b61931737e662dd293b40578ccornelius } // End of mutex locked block 1303103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1304103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (cacheEntry == NULL) { 1305103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius delete instance; 1306103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return NULL; 1307103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1308103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1309103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius instance->fRef = cacheEntry; 1310103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return instance; 1311103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1313103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUBool 1314103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::operator==(const TimeZoneGenericNames& other) const { 1315103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Just compare if the other object also use the same 1316103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // ref entry 1317103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fRef == other.fRef; 1318103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1319103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1320103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames* 1321103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::clone() const { 1322103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius TimeZoneGenericNames* other = new TimeZoneGenericNames(); 1323103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (other) { 1324103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius umtx_lock(&gTZGNLock); 1325103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius { 1326103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Just increments the reference count 1327103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius fRef->refCount++; 1328103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius other->fRef = fRef; 1329103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1330103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius umtx_unlock(&gTZGNLock); 1331103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 1332103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return other; 1333103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1334103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1335103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString& 1336103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type, 1337103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UDate date, UnicodeString& name) const { 1338103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fRef->obj->getDisplayName(tz, type, date, name); 1339103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1340103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1341103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString& 1342103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const { 1343103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fRef->obj->getGenericLocationName(tzCanonicalID, name); 1344103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 1345103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 1346103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusint32_t 1347103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types, 1348103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString& tzID, UTimeZoneFormatTimeType& timeType, UErrorCode& status) const { 1349103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return fRef->obj->findBestMatch(text, start, types, tzID, timeType, status); 1350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 1351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 1352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_END 1353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif 1354