1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* Copyright (C) 2011, International Business Machines Corporation and         *
4b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* 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"
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_BEGIN
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define ZID_KEY_MAX  128
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gZoneStrings[]                = "zoneStrings";
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gRegionFormatTag[]            = "regionFormat";
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gFallbackRegionFormatTag[]    = "fallbackRegionFormat";
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gFallbackFormatTag[]          = "fallbackFormat";
41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gEmpty[]                     = {0x00};
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gDefRegionPattern[]          = {0x7B, 0x30, 0x7D, 0x00}; // "{0}"
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gDefFallbackRegionPattern[]  = {0x7B, 0x31, 0x7D, 0x20, 0x28, 0x7B, 0x30, 0x7D, 0x29, 0x00}; // "{1} ({0})"
46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar gDefFallbackPattern[]        = {0x7B, 0x31, 0x7D, 0x20, 0x28, 0x7B, 0x30, 0x7D, 0x29, 0x00}; // "{1} ({0})"
47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
48b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const double kDstCheckRange      = (double)184*U_MILLIS_PER_DAY;
49b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
53b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct PartialLocationKey {
55b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* tzID;
56b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* mzID;
57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool isLong;
58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} PartialLocationKey;
59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Hash function for partial location name hash key
62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t U_CALLCONV
64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehohashPartialLocationKey(const UHashTok key) {
65b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // <tzID>&<mzID>#[L|S]
66b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    PartialLocationKey *p = (PartialLocationKey *)key.pointer;
67b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString str(p->tzID);
68b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    str.append((UChar)0x26)
69b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        .append(p->mzID)
70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        .append((UChar)0x23)
71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        .append((UChar)(p->isLong ? 0x4C : 0x53));
72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return uhash_hashUCharsN(str.getBuffer(), str.length());
73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Comparer for partial location name hash key
77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool U_CALLCONV
79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehocomparePartialLocationKey(const UHashTok key1, const UHashTok key2) {
80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    PartialLocationKey *p1 = (PartialLocationKey *)key1.pointer;
81b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    PartialLocationKey *p2 = (PartialLocationKey *)key2.pointer;
82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
83b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (p1 == p2) {
84b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return TRUE;
85b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (p1 == NULL || p2 == NULL) {
87b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
88b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
89b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We just check identity of tzID/mzID
90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (p1->tzID == p2->tzID && p1->mzID == p2->mzID && p1->isLong == p2->isLong);
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for GNameInfo
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteGNameInfo(void *obj) {
98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(obj);
99b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * GNameInfo stores zone name information in the local trie
103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct GNameInfo {
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneGenericNameType    type;
106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar*                tzID;
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZNameInfo;
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * GMatchInfo stores zone name match information used by find method
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct GMatchInfo {
113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const GNameInfo*    gnameInfo;
114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t             matchLength;
115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneTimeType   timeType;
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZMatchInfo;
117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// The class stores time zone generic name match information
122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::TimeZoneGenericNameMatchInfo(UVector* matches)
124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fMatches(matches) {
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::~TimeZoneGenericNameMatchInfo() {
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fMatches != NULL) {
129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fMatches;
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::size() const {
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fMatches == NULL) {
136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fMatches->size();
139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUTimeZoneGenericNameType
142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::getGenericNameType(int32_t index) const {
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    GMatchInfo *minfo = (GMatchInfo *)fMatches->elementAt(index);
144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (minfo != NULL) {
145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return static_cast<UTimeZoneGenericNameType>(minfo->gnameInfo->type);
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return UTZGNM_UNKNOWN;
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::getMatchLength(int32_t index) const {
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZMatchInfo *minfo = (ZMatchInfo *)fMatches->elementAt(index);
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (minfo != NULL) {
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return minfo->matchLength;
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return -1;
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo::getTimeZoneID(int32_t index, UnicodeString& tzID) const {
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    GMatchInfo *minfo = (GMatchInfo *)fMatches->elementAt(index);
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (minfo != NULL && minfo->gnameInfo->tzID != NULL) {
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tzID.setTo(TRUE, minfo->gnameInfo->tzID, -1);
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tzID.setToBogus();
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tzID;
168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// GNameSearchHandler
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass GNameSearchHandler : public TextTrieMapSearchResultHandler {
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    GNameSearchHandler(uint32_t types);
176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~GNameSearchHandler();
177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector* getMatches(int32_t& maxMatchLen);
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint32_t fTypes;
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector* fResults;
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fMaxMatchLen;
185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::GNameSearchHandler(uint32_t types)
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fTypes(types), fResults(NULL), fMaxMatchLen(0) {
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::~GNameSearchHandler() {
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fResults != NULL) {
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fResults;
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node->hasValues()) {
203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t valuesCount = node->countValues();
204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < valuesCount; i++) {
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            GNameInfo *nameinfo = (ZNameInfo *)node->getValue(i);
206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (nameinfo == NULL) {
207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if ((nameinfo->type & fTypes) != 0) {
210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // matches a requested type
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (fResults == NULL) {
212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    fResults = new UVector(uhash_freeBlock, NULL, status);
213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (fResults == NULL) {
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        status = U_MEMORY_ALLOCATION_ERROR;
215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (U_SUCCESS(status)) {
218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    GMatchInfo *gmatch = (GMatchInfo *)uprv_malloc(sizeof(GMatchInfo));
219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (gmatch == NULL) {
220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        status = U_MEMORY_ALLOCATION_ERROR;
221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else {
222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        // add the match to the vector
223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        gmatch->gnameInfo = nameinfo;
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        gmatch->matchLength = matchLength;
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        gmatch->timeType = UTZFMT_TIME_TYPE_UNKNOWN;
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        fResults->addElement(gmatch, status);
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (U_FAILURE(status)) {
228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            uprv_free(gmatch);
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        } else {
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            if (matchLength > fMaxMatchLen) {
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                fMaxMatchLen = matchLength;
232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            }
233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUVector*
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoGNameSearchHandler::getMatches(int32_t& maxMatchLen) {
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // give the ownership to the caller
245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector *results = fResults;
246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    maxMatchLen = fMaxMatchLen;
247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // reset
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fResults = NULL;
250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fMaxMatchLen = 0;
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return results;
252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneGenericNames
256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneGenericNames is parallel to TimeZoneNames,
258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// but handles run-time generated time zone names.
259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// This is the main part of this module.
260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::TimeZoneGenericNames(const Locale& locale, UErrorCode& status)
262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLocale(locale),
263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fLock(NULL),
264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fTimeZoneNames(NULL),
265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fLocationNamesMap(NULL),
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fPartialLocationNamesMap(NULL),
267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fRegionFormat(NULL),
268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fFallbackRegionFormat(NULL),
269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fFallbackFormat(NULL),
270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fLocaleDisplayNames(NULL),
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fStringPool(status),
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fGNamesTrie(TRUE, deleteGNameInfo),
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fGNamesTrieFullyLoaded(FALSE) {
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    initialize(locale, status);
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::~TimeZoneGenericNames() {
278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cleanup();
279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_destroy(&fLock);
280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::initialize(const Locale& locale, UErrorCode& status) {
284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // TimeZoneNames
289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneNames = TimeZoneNames::createInstance(locale, status);
290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Initialize format patterns
295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString rpat(TRUE, gDefRegionPattern, -1);
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString frpat(TRUE, gDefFallbackRegionPattern, -1);
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString fpat(TRUE, gDefFallbackPattern, -1);
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode tmpsts = U_ZERO_ERROR;   // OK with fallback warning..
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *zoneStrings = ures_open(U_ICUDATA_ZONE, locale.getName(), &tmpsts);
301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    zoneStrings = ures_getByKeyWithFallback(zoneStrings, gZoneStrings, zoneStrings, &tmpsts);
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(tmpsts)) {
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar *regionPattern = ures_getStringByKeyWithFallback(zoneStrings, gRegionFormatTag, NULL, &tmpsts);
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(tmpsts) && u_strlen(regionPattern) > 0) {
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            rpat.setTo(regionPattern);
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tmpsts = U_ZERO_ERROR;
309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar *fallbackRegionPattern = ures_getStringByKeyWithFallback(zoneStrings, gFallbackRegionFormatTag, NULL, &tmpsts);
310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(tmpsts) && u_strlen(fallbackRegionPattern) > 0) {
311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            frpat.setTo(fallbackRegionPattern);
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tmpsts = U_ZERO_ERROR;
314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar *fallbackPattern = ures_getStringByKeyWithFallback(zoneStrings, gFallbackFormatTag, NULL, &tmpsts);
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(tmpsts) && u_strlen(fallbackPattern) > 0) {
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fpat.setTo(fallbackPattern);
317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(zoneStrings);
320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fRegionFormat = new MessageFormat(rpat, status);
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fRegionFormat == NULL) {
323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fFallbackRegionFormat = new MessageFormat(frpat, status);
326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFallbackRegionFormat == NULL) {
327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fFallbackFormat = new MessageFormat(fpat, status);
330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFallbackFormat == NULL) {
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // locale display names
339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLocaleDisplayNames = LocaleDisplayNames::createInstance(locale);
340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // hash table for names - no key/value deleters
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLocationNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fPartialLocationNamesMap = uhash_open(hashPartialLocationKey, comparePartialLocationKey, NULL, &status);
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_setKeyDeleter(fPartialLocationNamesMap, uhash_freeBlock);
354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // no value deleter
355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // target region
357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const char* region = fLocale.getCountry();
358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t regionLen = uprv_strlen(region);
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (regionLen == 0) {
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char loc[ULOC_FULLNAME_CAPACITY];
361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status);
362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        regionLen = uloc_getCountry(loc, fTargetRegion, sizeof(fTargetRegion), &status);
364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status)) {
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fTargetRegion[regionLen] = 0;
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cleanup();
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (regionLen < (int32_t)sizeof(fTargetRegion)) {
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uprv_strcpy(fTargetRegion, region);
372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fTargetRegion[0] = 0;
374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // preload generic names for the default zone
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZone *tz = TimeZone::createDefault();
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz);
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID != NULL) {
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        loadStrings(UnicodeString(tzID));
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete tz;
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::cleanup() {
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fRegionFormat != NULL) {
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fRegionFormat;
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFallbackRegionFormat != NULL) {
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fFallbackRegionFormat;
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fFallbackFormat != NULL) {
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fFallbackFormat;
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLocaleDisplayNames != NULL) {
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLocaleDisplayNames;
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fTimeZoneNames != NULL) {
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fTimeZoneNames;
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(fLocationNamesMap);
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(fPartialLocationNamesMap);
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::getDisplayName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const {
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    switch (type) {
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZGNM_LOCATION:
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        {
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UChar* tzCanonicalID = ZoneMeta::getCanonicalCLDRID(tz);
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tzCanonicalID != NULL) {
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                getGenericLocationName(UnicodeString(tzCanonicalID), name);
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZGNM_LONG:
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZGNM_SHORT:
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formatGenericNonLocationName(tz, type, date, name);
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (name.isEmpty()) {
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UChar* tzCanonicalID = ZoneMeta::getCanonicalCLDRID(tz);
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tzCanonicalID != NULL) {
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                getGenericLocationName(UnicodeString(tzCanonicalID), name);
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    default:
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeString& name) const {
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzCanonicalID.isEmpty()) {
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setToBogus();
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *locname = NULL;
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneGenericNames *nonConstThis = const_cast<TimeZoneGenericNames *>(this);
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_lock(&nonConstThis->fLock);
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        locname = nonConstThis->getGenericLocationName(tzCanonicalID);
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_unlock(&nonConstThis->fLock);
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (locname == NULL) {
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setToBogus();
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setTo(TRUE, locname, -1);
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::getGenericLocationName(const UnicodeString& tzCanonicalID) {
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(!tzCanonicalID.isEmpty());
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzCanonicalID.length() > ZID_KEY_MAX) {
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar tzIDKey[ZID_KEY_MAX + 1];
471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t tzIDKeyLen = tzCanonicalID.extract(tzIDKey, ZID_KEY_MAX + 1, status);
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    tzIDKey[tzIDKeyLen] = 0;
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *locname = (const UChar *)uhash_get(fLocationNamesMap, tzIDKey);
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (locname != NULL) {
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // gEmpty indicate the name is not available
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (locname == gEmpty) {
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return locname;
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Construct location name
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString name;
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool isSingleCountry = FALSE;
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString usCountryCode;
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZoneMeta::getSingleCountry(tzCanonicalID, usCountryCode);
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!usCountryCode.isEmpty()) {
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        isSingleCountry = TRUE;
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZoneMeta::getCanonicalCountry(tzCanonicalID, usCountryCode);
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!usCountryCode.isEmpty()) {
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char countryCode[ULOC_COUNTRY_CAPACITY];
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(usCountryCode.length() < ULOC_COUNTRY_CAPACITY);
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t ccLen = usCountryCode.extract(0, usCountryCode.length(), countryCode, sizeof(countryCode), US_INV);
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        countryCode[ccLen] = 0;
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString country;
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLocaleDisplayNames->regionDisplayName(countryCode, country);
504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Format
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        FieldPosition fpos;
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (isSingleCountry) {
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // If the zone is only one zone in the country, do not add city
509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            Formattable param[] = {
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                Formattable(country)
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            };
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fRegionFormat->format(param, 1, name, fpos, status);
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // getExemplarLocationName should retur non-empty string
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // if the time zone is associated with a region
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString city;
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fTimeZoneNames->getExemplarLocationName(tzCanonicalID, city);
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            Formattable params[] = {
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                Formattable(city),
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                Formattable(country)
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            };
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fFallbackRegionFormat->format(params, 2, name, fpos, status);
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    locname = name.isEmpty() ? NULL : fStringPool.get(name, status);
531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Cache the result
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* cacheID = ZoneMeta::findTimeZoneID(tzCanonicalID);
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(cacheID != NULL);
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (locname == NULL) {
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // gEmpty to indicate - no location name available
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fLocationNamesMap, (void *)cacheID, (void *)gEmpty, &status);
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fLocationNamesMap, (void *)cacheID, (void *)locname, &status);
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                locname = NULL;
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // put the name info into the trie
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                GNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(GNameInfo));
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (nameinfo != NULL) {
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nameinfo->type = UTZGNM_LOCATION;
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nameinfo->tzID = cacheID;
548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    fGNamesTrie.put(locname, nameinfo, status);
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return locname;
555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::formatGenericNonLocationName(const TimeZone& tz, UTimeZoneGenericNameType type, UDate date, UnicodeString& name) const {
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(type == UTZGNM_LONG || type == UTZGNM_SHORT);
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* uID = ZoneMeta::getCanonicalCLDRID(tz);
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uID == NULL) {
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString tzID(uID);
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Try to get a name from time zone first
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneNameType nameType = (type == UTZGNM_LONG) ? UTZNM_LONG_GENERIC : UTZNM_SHORT_GENERIC;
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneNames->getTimeZoneDisplayName(tzID, nameType, name);
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!name.isEmpty()) {
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Try meta zone
578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString mzID;
579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTimeZoneNames->getMetaZoneID(tzID, date, mzID);
580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!mzID.isEmpty()) {
581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UErrorCode status = U_ZERO_ERROR;
582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UBool useStandard = FALSE;
583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t raw, sav;
584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tz.getOffset(date, FALSE, raw, sav, status);
586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return name;
588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (sav == 0) {
591b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            useStandard = TRUE;
592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            TimeZone *tmptz = tz.clone();
594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Check if the zone actually uses daylight saving time around the time
595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            BasicTimeZone *btz = NULL;
596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (dynamic_cast<OlsonTimeZone *>(tmptz) != NULL
597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                || dynamic_cast<SimpleTimeZone *>(tmptz) != NULL
598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                || dynamic_cast<RuleBasedTimeZone *>(tmptz) != NULL
599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                || dynamic_cast<VTimeZone *>(tmptz) != NULL) {
600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                btz = (BasicTimeZone*)tmptz;
601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (btz != NULL) {
604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                TimeZoneTransition before;
605b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UBool beforTrs = btz->getPreviousTransition(date, TRUE, before);
606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (beforTrs
607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        && (date - before.getTime() < kDstCheckRange)
608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        && before.getFrom()->getDSTSavings() != 0) {
609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    useStandard = FALSE;
610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    TimeZoneTransition after;
612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    UBool afterTrs = btz->getNextTransition(date, FALSE, after);
613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (afterTrs
614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            && (after.getTime() - date < kDstCheckRange)
615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            && after.getTo()->getDSTSavings() != 0) {
616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        useStandard = FALSE;
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
620b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // If not BasicTimeZone... only if the instance is not an ICU's implementation.
621b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // We may get a wrong answer in edge case, but it should practically work OK.
622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                tmptz->getOffset(date - kDstCheckRange, FALSE, raw, sav, status);
623b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (sav != 0) {
624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    useStandard = FALSE;
625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
626b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    tmptz->getOffset(date + kDstCheckRange, FALSE, raw, sav, status);
627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (sav != 0){
628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        useStandard = FALSE;
629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (U_FAILURE(status)) {
632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete tmptz;
633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return name;
634b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
635b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            delete tmptz;
637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
638b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (useStandard) {
639b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UTimeZoneNameType stdNameType = (nameType == UTZNM_LONG_GENERIC)
640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ? UTZNM_LONG_STANDARD : UTZNM_SHORT_STANDARD_COMMONLY_USED;
641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString stdName;
642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fTimeZoneNames->getDisplayName(tzID, stdNameType, date, stdName);
643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!stdName.isEmpty()) {
644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                name.setTo(stdName);
645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // TODO: revisit this issue later
647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // In CLDR, a same display name is used for both generic and standard
648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // for some meta zones in some locales.  This looks like a data bugs.
649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // For now, we check if the standard name is different from its generic
650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // name below.
651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UnicodeString mzGenericName;
652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                fTimeZoneNames->getMetaZoneDisplayName(mzID, nameType, mzGenericName);
653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (stdName.caseCompare(mzGenericName, 0) == 0) {
654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    name.setToBogus();
655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
657b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (name.isEmpty()) {
659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Get a name from meta zone
660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString mzName;
661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fTimeZoneNames->getMetaZoneDisplayName(mzID, nameType, mzName);
662b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!mzName.isEmpty()) {
663b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // Check if we need to use a partial location format.
664b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // This check is done by comparing offset with the meta zone's
665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // golden zone at the given date.
666b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UnicodeString goldenID;
667b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, goldenID);
668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (!goldenID.isEmpty() && goldenID != tzID) {
669b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    TimeZone *goldenZone = TimeZone::createTimeZone(goldenID);
670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t raw1, sav1;
671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
672b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Check offset in the golden zone with wall time.
673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // With getOffset(date, false, offsets1),
674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // you may get incorrect results because of time overlap at DST->STD
675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // transition.
676b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    goldenZone->getOffset(date + raw + sav, TRUE, raw1, sav1, status);
677b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete goldenZone;
678b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_SUCCESS(status)) {
679b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (raw != raw1 || sav != sav1) {
680b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            // Now we need to use a partial location format
681b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            getPartialLocationName(tzID, mzID, (nameType == UTZNM_LONG_GENERIC), mzName, name);
682b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        } else {
683b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            name.setTo(mzName);
684b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
685b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
687b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    name.setTo(mzName);
688b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
691b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
692b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
693b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
694b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
696b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
697b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName,
698b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        UnicodeString& name) const {
699b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();
700b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzCanonicalID.isEmpty() || mzID.isEmpty() || mzDisplayName.isEmpty()) {
701b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
702b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
704b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *uplname = NULL;
705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneGenericNames *nonConstThis = const_cast<TimeZoneGenericNames *>(this);
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_lock(&nonConstThis->fLock);
707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uplname = nonConstThis->getPartialLocationName(tzCanonicalID, mzID, isLong, mzDisplayName);
709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_unlock(&nonConstThis->fLock);
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uplname == NULL) {
713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setToBogus();
714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setTo(TRUE, uplname, -1);
716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock
722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::getPartialLocationName(const UnicodeString& tzCanonicalID,
725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        const UnicodeString& mzID, UBool isLong, const UnicodeString& mzDisplayName) {
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(!tzCanonicalID.isEmpty());
727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(!mzID.isEmpty());
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(!mzDisplayName.isEmpty());
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    PartialLocationKey key;
731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    key.tzID = ZoneMeta::findTimeZoneID(tzCanonicalID);
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    key.mzID = ZoneMeta::findMetaZoneID(mzID);
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    key.isLong = isLong;
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(key.tzID != NULL && key.mzID != NULL);
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* uplname = (const UChar*)uhash_get(fPartialLocationNamesMap, (void *)&key);
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uplname != NULL) {
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return uplname;
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString location;
742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString usCountryCode;
743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZoneMeta::getCanonicalCountry(tzCanonicalID, usCountryCode);
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!usCountryCode.isEmpty()) {
745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char countryCode[ULOC_COUNTRY_CAPACITY];
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(usCountryCode.length() < ULOC_COUNTRY_CAPACITY);
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t ccLen = usCountryCode.extract(0, usCountryCode.length(), countryCode, sizeof(countryCode), US_INV);
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        countryCode[ccLen] = 0;
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString regionalGolden;
751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fTimeZoneNames->getReferenceZoneID(mzID, countryCode, regionalGolden);
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (tzCanonicalID == regionalGolden) {
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Use country name
754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fLocaleDisplayNames->regionDisplayName(countryCode, location);
755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Otherwise, use exemplar city name
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fTimeZoneNames->getExemplarLocationName(tzCanonicalID, location);
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fTimeZoneNames->getExemplarLocationName(tzCanonicalID, location);
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (location.isEmpty()) {
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This could happen when the time zone is not associated with a country,
763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // and its ID is not hierarchical, for example, CST6CDT.
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // We use the canonical ID itself as the location for this case.
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            location.setTo(tzCanonicalID);
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString name;
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    FieldPosition fpos;
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    Formattable param[] = {
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Formattable(location),
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Formattable(mzDisplayName)
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fFallbackFormat->format(param, 2, name, fpos, status);
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uplname = fStringPool.get(name, status);
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Add the name to cache
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        PartialLocationKey* cacheKey = (PartialLocationKey *)uprv_malloc(sizeof(PartialLocationKey));
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (cacheKey != NULL) {
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheKey->tzID = key.tzID;
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheKey->mzID = key.mzID;
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheKey->isLong = key.isLong;
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fPartialLocationNamesMap, (void *)cacheKey, (void *)uplname, &status);
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_free(cacheKey);
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // put the name to the local trie as well
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                GNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(GNameInfo));
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (nameinfo != NULL) {
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nameinfo->type = isLong ? UTZGNM_LONG : UTZGNM_SHORT;
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nameinfo->tzID = key.tzID;
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    fGNamesTrie.put(uplname, nameinfo, status);
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return uplname;
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock,
809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * except initializer.
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::loadStrings(const UnicodeString& tzCanonicalID) {
813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // load the generic location name
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    getGenericLocationName(tzCanonicalID);
815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // partial location names
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString *mzID;
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString goldenID;
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString mzGenName;
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneNameType genNonLocTypes[] = {
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UTZNM_LONG_GENERIC, UTZNM_SHORT_GENERIC,
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UTZNM_UNKNOWN /*terminator*/
825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringEnumeration *mzIDs = fTimeZoneNames->getAvailableMetaZoneIDs(tzCanonicalID, status);
828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while ((mzID = mzIDs->snext(status))) {
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // if this time zone is not the golden zone of the meta zone,
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // partial location name (such as "PT (Los Angeles)") might be
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // available.
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fTimeZoneNames->getReferenceZoneID(*mzID, fTargetRegion, goldenID);
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (tzCanonicalID != goldenID) {
837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int32_t i = 0; genNonLocTypes[i] != UTZNM_UNKNOWN; i++) {
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                fTimeZoneNames->getMetaZoneDisplayName(*mzID, genNonLocTypes[i], mzGenName);
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (!mzGenName.isEmpty()) {
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // getPartialLocationName formats a name and put it into the trie
841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    getPartialLocationName(tzCanonicalID, *mzID,
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        (genNonLocTypes[i] == UTZNM_LONG_GENERIC), mzGenName);
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzIDs != NULL) {
848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete mzIDs;
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::findBestMatch(const UnicodeString& text, int32_t start, uint32_t types,
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString& tzID, UTimeZoneTimeType& timeType, UErrorCode& status) const {
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    timeType = UTZFMT_TIME_TYPE_UNKNOWN;
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    tzID.setToBogus();
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Find matches in the TimeZoneNames first
863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNameMatchInfo *tznamesMatches = findTimeZoneNames(text, start, types, status);
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t bestMatchLen = 0;
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneTimeType bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString bestMatchTzID;
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool isLongStandard = FALSE;  // workaround - see the comments below
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tznamesMatches != NULL) {
874b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString mzID;
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < tznamesMatches->size(); i++) {
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t len = tznamesMatches->getMatchLength(i);
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (len > bestMatchLen) {
878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                bestMatchLen = len;
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                tznamesMatches->getTimeZoneID(i, bestMatchTzID);
880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (bestMatchTzID.isEmpty()) {
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // name for a meta zone
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    tznamesMatches->getMetaZoneID(i, mzID);
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    U_ASSERT(mzID.length() > 0);
884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    fTimeZoneNames->getReferenceZoneID(mzID, fTargetRegion, bestMatchTzID);
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UTimeZoneNameType nameType = tznamesMatches->getNameType(i);
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                switch (nameType) {
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UTZNM_LONG_STANDARD:
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    isLongStandard = TRUE;
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UTZNM_SHORT_STANDARD_COMMONLY_USED:
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UTZNM_SHORT_STANDARD: // this one is never used for generic, but just in case
892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    bestMatchTimeType = UTZFMT_TIME_TYPE_STANDARD;
893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UTZNM_LONG_DAYLIGHT:
895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UTZNM_SHORT_DAYLIGHT_COMMONLY_USED:
896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                case UTZNM_SHORT_DAYLIGHT: // this one is never used for generic, but just in case
897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    bestMatchTimeType = UTZFMT_TIME_TYPE_DAYLIGHT;
898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                default:
900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN;
901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete tznamesMatches;
905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (bestMatchLen == (text.length() - start)) {
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Full match
908b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            //tzID.setTo(bestMatchTzID);
910b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            //timeType = bestMatchTimeType;
911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            //return bestMatchLen;
912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
913b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // TODO Some time zone uses a same name for the long standard name
914b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // and the location name. When the match is a long standard name,
915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // then we need to check if the name is same with the location name.
916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This is probably a data error or a design bug.
917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!isLongStandard) {
918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                tzID.setTo(bestMatchTzID);
919b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                timeType = bestMatchTimeType;
920b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return bestMatchLen;
921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Find matches in the local trie
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneGenericNameMatchInfo *localMatches = findLocal(text, start, types, status);
927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (localMatches != NULL) {
931b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < localMatches->size(); i++) {
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t len = localMatches->getMatchLength(i);
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // TODO See the above TODO. We use len >= bestMatchLen
935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // because of the long standard/location name collision
936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // problem. If it is also a location name, carrying
937b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // timeType = UTZFMT_TIME_TYPE_STANDARD will cause a
938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // problem in SimpleDateFormat
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (len >= bestMatchLen) {
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                bestMatchLen = localMatches->getMatchLength(i);
941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                bestMatchTimeType = UTZFMT_TIME_TYPE_UNKNOWN;   // because generic
942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                localMatches->getTimeZoneID(i, bestMatchTzID);
943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete localMatches;
946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (bestMatchLen > 0) {
949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        timeType = bestMatchTimeType;
950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tzID.setTo(bestMatchTzID);
951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return bestMatchLen;
953b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNameMatchInfo*
956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    GNameSearchHandler handler(types);
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneGenericNames *nonConstThis = const_cast<TimeZoneGenericNames *>(this);
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_lock(&nonConstThis->fLock);
962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_unlock(&nonConstThis->fLock);
966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
967b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
968b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
969b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneGenericNameMatchInfo *gmatchInfo = NULL;
972b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
973b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t maxLen = 0;
974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector *results = handler.getMatches(maxLen);
975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (results != NULL && ((maxLen == (text.length() - start)) || fGNamesTrieFullyLoaded)) {
976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // perfect match
977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        gmatchInfo = new TimeZoneGenericNameMatchInfo(results);
978b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gmatchInfo == NULL) {
979b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            delete results;
981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
982b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return gmatchInfo;
984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (results != NULL) {
987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete results;
988b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
990b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // All names are not yet loaded into the local trie.
991b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Load all available names into the trie. This could be very heavy.
992b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_lock(&nonConstThis->fLock);
993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
994b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!fGNamesTrieFullyLoaded) {
995b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
997b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const UnicodeString *tzID;
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                while ((tzID = tzIDs->snext(status))) {
999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(status)) {
1000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nonConstThis->loadStrings(*tzID);
1003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tzIDs != NULL) {
1006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete tzIDs;
1007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1010b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                nonConstThis->fGNamesTrieFullyLoaded = TRUE;
1011b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_unlock(&nonConstThis->fLock);
1015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_lock(&nonConstThis->fLock);
1021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // now try it again
1023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
1024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_unlock(&nonConstThis->fLock);
1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    results = handler.getMatches(maxLen);
1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (results != NULL && maxLen > 0) {
1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        gmatchInfo = new TimeZoneGenericNameMatchInfo(results);
1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (gmatchInfo == NULL) {
1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            delete results;
1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
1034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return gmatchInfo;
1038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1039b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNameMatchInfo*
1041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneGenericNames::findTimeZoneNames(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
1042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNameMatchInfo *matchInfo = NULL;
1043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Check if the target name typs is really in the TimeZoneNames
1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint32_t nameTypes = 0;
1046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (types & UTZGNM_LONG) {
1047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nameTypes |= (UTZNM_LONG_GENERIC | UTZNM_LONG_STANDARD);
1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (types & UTZGNM_SHORT) {
1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nameTypes |= (UTZNM_SHORT_GENERIC | UTZNM_SHORT_STANDARD_COMMONLY_USED);
1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (types) {
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Find matches in the TimeZoneNames
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        matchInfo = fTimeZoneNames->find(text, start, nameTypes, status);
1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return matchInfo;
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_END
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif
1063