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