1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
3f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius* Copyright (C) 2011-2014, International Business Machines Corporation and
4b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* others. All Rights Reserved.
5b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
6b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*
7b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* File TZNAMES_IMPL.CPP
8b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*
9b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
10b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*/
11b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
12b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/utypes.h"
13b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
14b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#if !UCONFIG_NO_FORMATTING
15b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
16b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/ustring.h"
17b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/timezone.h"
18b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "tznames_impl.h"
20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "cmemory.h"
21b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "cstring.h"
22b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uassert.h"
2359d709d503bab6e2b61931737e662dd293b40578ccornelius#include "mutex.h"
24b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uresimp.h"
25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ureslocs.h"
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "zonemeta.h"
27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ucln_in.h"
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uvector.h"
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "olsontz.h"
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_BEGIN
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define ZID_KEY_MAX  128
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define MZ_PREFIX_LEN 5
36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gZoneStrings[]        = "zoneStrings";
38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gMZPrefix[]           = "meta:";
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char* KEYS[]               = {"lg", "ls", "ld", "sg", "ss", "sd"};
41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t KEYS_SIZE = (sizeof KEYS / sizeof KEYS[0]);
42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gEcTag[]              = "ec";
44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char EMPTY[]               = "<empty>";   // place holder for empty ZNames/TZNames
46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UTimeZoneNameType ALL_NAME_TYPES[] = {
48b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTZNM_LONG_GENERIC, UTZNM_LONG_STANDARD, UTZNM_LONG_DAYLIGHT,
49b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTZNM_SHORT_GENERIC, UTZNM_SHORT_STANDARD, UTZNM_SHORT_DAYLIGHT,
508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UTZNM_EXEMPLAR_LOCATION,
51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTZNM_UNKNOWN // unknown as the last one
52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
53b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
54f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// stuff for TZDBTimeZoneNames
55f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic const char* TZDBNAMES_KEYS[]               = {"ss", "sd"};
56f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic const int32_t TZDBNAMES_KEYS_SIZE = (sizeof TZDBNAMES_KEYS / sizeof TZDBNAMES_KEYS[0]);
57f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
58f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER;
59f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
60f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UHashtable* gTZDBNamesMap = NULL;
61f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic icu::UInitOnce gTZDBNamesMapInitOnce = U_INITONCE_INITIALIZER;
62f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
63f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic TextTrieMap* gTZDBNamesTrie = NULL;
64f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic icu::UInitOnce gTZDBNamesTrieInitOnce = U_INITONCE_INITIALIZER;
65f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
66f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CDECL_BEGIN
67f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic UBool U_CALLCONV tzdbTimeZoneNames_cleanup(void) {
68f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gTZDBNamesMap != NULL) {
69f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uhash_close(gTZDBNamesMap);
70f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        gTZDBNamesMap = NULL;
71f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
72f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTZDBNamesMapInitOnce.reset();
73f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
74f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gTZDBNamesTrie != NULL) {
75f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        delete gTZDBNamesTrie;
76f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        gTZDBNamesTrie = NULL;
77f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
78f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTZDBNamesTrieInitOnce.reset();
79f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
80f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TRUE;
81f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
82f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CDECL_END
83f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
84b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define DEFAULT_CHARACTERNODE_CAPACITY 1
85b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
87103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// CharacterNode class implementation
88b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
89b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid CharacterNode::clear() {
90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memset(this, 0, sizeof(*this));
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid CharacterNode::deleteValues(UObjectDeleter *valueDeleter) {
94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fValues == NULL) {
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Do nothing.
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (!fHasValuesVector) {
97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (valueDeleter) {
98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            valueDeleter(fValues);
99b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete (UVector *)fValues;
102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCharacterNode::addValue(void *value, UObjectDeleter *valueDeleter, UErrorCode &status) {
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (valueDeleter) {
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            valueDeleter(value);
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fValues == NULL) {
114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fValues = value;
115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // At least one value already.
117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!fHasValuesVector) {
118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // There is only one value so far, and not in a vector yet.
119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Create a vector and add the old value.
120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UVector *values = new UVector(valueDeleter, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status);
121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (valueDeleter) {
123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    valueDeleter(value);
124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            values->addElement(fValues, status);
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fValues = values;
129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fHasValuesVector = TRUE;
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Add the new value.
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((UVector *)fValues)->addElement(value, status);
133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TextTrieMapSearchResultHandler class implementation
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMapSearchResultHandler::~TextTrieMapSearchResultHandler(){
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TextTrieMap class implementation
144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::TextTrieMap(UBool ignoreCase, UObjectDeleter *valueDeleter)
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fIgnoreCase(ignoreCase), fNodes(NULL), fNodesCapacity(0), fNodesCount(0),
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fLazyContents(NULL), fIsEmpty(TRUE), fValueDeleter(valueDeleter) {
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::~TextTrieMap() {
151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t index;
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (index = 0; index < fNodesCount; ++index) {
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes[index].deleteValues(fValueDeleter);
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(fNodes);
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLazyContents != NULL) {
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i=0; i<fLazyContents->size(); i+=2) {
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (fValueDeleter) {
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                fValueDeleter(fLazyContents->elementAt(i+1));
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLazyContents;
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t TextTrieMap::isEmpty() const {
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Use a separate field for fIsEmpty because it will remain unchanged once the
168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   Trie is built, while fNodes and fLazyContents change with the lazy init
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   of the nodes structure.  Trying to test the changing fields has
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   thread safety complications.
171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fIsEmpty;
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//  We defer actually building the TextTrieMap node structure until the first time a
176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//     search is performed.  put() simply saves the parameters in case we do
177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//     eventually need to build it.
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::put(const UnicodeString &key, void *value, ZNStringPool &sp, UErrorCode &status) {
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *s = sp.get(key, status);
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    put(s, value, status);
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// This method is for designed for a persistent key, such as string key stored in
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// resource bundle.
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::put(const UChar *key, void *value, UErrorCode &status) {
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fIsEmpty = FALSE;
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLazyContents == NULL) {
191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLazyContents = new UVector(status);
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (fLazyContents == NULL) {
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U_ASSERT(fLazyContents != NULL);
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar *s = const_cast<UChar *>(key);
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLazyContents->addElement(s, status);
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLazyContents->addElement(value, status);
203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::putImpl(const UnicodeString &key, void *value, UErrorCode &status) {
207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodes == NULL) {
208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodesCapacity = 512;
209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes = (CharacterNode *)uprv_malloc(fNodesCapacity * sizeof(CharacterNode));
210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes[0].clear();  // Init root node.
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodesCount = 1;
212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString foldedKey;
215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *keyBuffer;
216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t keyLength;
217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fIgnoreCase) {
218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Ok to use fastCopyFrom() because we discard the copy when we return.
219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        foldedKey.fastCopyFrom(key).foldCase();
220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyBuffer = foldedKey.getBuffer();
221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyLength = foldedKey.length();
222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyBuffer = key.getBuffer();
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyLength = key.length();
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CharacterNode *node = fNodes;
228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t index;
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (index = 0; index < keyLength; ++index) {
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        node = addChildNode(node, keyBuffer[index], status);
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->addValue(value, fValueDeleter, status);
233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::growNodes() {
237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodesCapacity == 0xffff) {
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;  // We use 16-bit node indexes.
239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t newCapacity = fNodesCapacity + 1000;
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (newCapacity > 0xffff) {
242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        newCapacity = 0xffff;
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CharacterNode *newNodes = (CharacterNode *)uprv_malloc(newCapacity * sizeof(CharacterNode));
245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (newNodes == NULL) {
246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memcpy(newNodes, fNodes, fNodesCount * sizeof(CharacterNode));
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(fNodes);
250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fNodes = newNodes;
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fNodesCapacity = newCapacity;
252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCharacterNode*
256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::addChildNode(CharacterNode *parent, UChar c, UErrorCode &status) {
257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Linear search of the sorted list of children.
261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint16_t prevIndex = 0;
262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint16_t nodeIndex = parent->fFirstChild;
263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (nodeIndex > 0) {
264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        CharacterNode *current = fNodes + nodeIndex;
265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar childCharacter = current->fCharacter;
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (childCharacter == c) {
267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return current;
268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (childCharacter > c) {
269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        prevIndex = nodeIndex;
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nodeIndex = current->fNextSibling;
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Ensure capacity. Grow fNodes[] if needed.
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodesCount == fNodesCapacity) {
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t parentIndex = (int32_t)(parent - fNodes);
278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!growNodes()) {
279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parent = fNodes + parentIndex;
283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Insert a new child node with c in sorted order.
286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CharacterNode *node = fNodes + fNodesCount;
287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->clear();
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->fCharacter = c;
289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->fNextSibling = nodeIndex;
290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (prevIndex == 0) {
291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parent->fFirstChild = (uint16_t)fNodesCount;
292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes[prevIndex].fNextSibling = (uint16_t)fNodesCount;
294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ++fNodesCount;
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return node;
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCharacterNode*
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::getChildNode(CharacterNode *parent, UChar c) const {
301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Linear search of the sorted list of children.
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint16_t nodeIndex = parent->fFirstChild;
303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (nodeIndex > 0) {
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        CharacterNode *current = fNodes + nodeIndex;
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar childCharacter = current->fCharacter;
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (childCharacter == c) {
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return current;
308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (childCharacter > c) {
309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nodeIndex = current->fNextSibling;
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Mutex for protecting the lazy creation of the Trie node structure on the first call to search().
31754dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex TextTrieMutex = U_MUTEX_INITIALIZER;
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// buildTrie() - The Trie node structure is needed.  Create it from the data that was
320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//               saved at the time the ZoneStringFormatter was created.  The Trie is only
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//               needed for parsing operations, which are less common than formatting,
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//               and the Trie is big, which is why its creation is deferred until first use.
323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid TextTrieMap::buildTrie(UErrorCode &status) {
324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLazyContents != NULL) {
325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i=0; i<fLazyContents->size(); i+=2) {
326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UChar *key = (UChar *)fLazyContents->elementAt(i);
327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            void  *val = fLazyContents->elementAt(i+1);
328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString keyString(TRUE, key, -1);  // Aliasing UnicodeString constructor.
329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            putImpl(keyString, val, status);
330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLazyContents;
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLazyContents = NULL;
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::search(const UnicodeString &text, int32_t start,
338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
33959d709d503bab6e2b61931737e662dd293b40578ccornelius    {
34059d709d503bab6e2b61931737e662dd293b40578ccornelius        // TODO: if locking the mutex for each check proves to be a performance problem,
34159d709d503bab6e2b61931737e662dd293b40578ccornelius        //       add a flag of type atomic_int32_t to class TextTrieMap, and use only
34259d709d503bab6e2b61931737e662dd293b40578ccornelius        //       the ICU atomic safe functions for assigning and testing.
34359d709d503bab6e2b61931737e662dd293b40578ccornelius        //       Don't test the pointer fLazyContents.
34459d709d503bab6e2b61931737e662dd293b40578ccornelius        //       Don't do unless it's really required.
34559d709d503bab6e2b61931737e662dd293b40578ccornelius        Mutex lock(&TextTrieMutex);
34659d709d503bab6e2b61931737e662dd293b40578ccornelius        if (fLazyContents != NULL) {
34759d709d503bab6e2b61931737e662dd293b40578ccornelius            TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
34859d709d503bab6e2b61931737e662dd293b40578ccornelius            nonConstThis->buildTrie(status);
34959d709d503bab6e2b61931737e662dd293b40578ccornelius        }
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodes == NULL) {
352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    search(fNodes, text, start, start, handler, status);
355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::search(CharacterNode *node, const UnicodeString &text, int32_t start,
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node->hasValues()) {
364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!handler->handleMatch(index - start, node, status)) {
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar32 c = text.char32At(index);
372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fIgnoreCase) {
373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // size of character may grow after fold operation
374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString tmp(c);
375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tmp.foldCase();
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t tmpidx = 0;
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while (tmpidx < tmp.length()) {
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            c = tmp.char32At(tmpidx);
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            node = getChildNode(node, c);
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (node == NULL) {
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            tmpidx = tmp.moveIndex32(tmpidx, 1);
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        node = getChildNode(node, c);
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node != NULL) {
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        search(node, text, start, index+1, handler, status);
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ZNStringPool class implementation
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t POOL_CHUNK_SIZE = 2000;
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct ZNStringPoolChunk: public UMemory {
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNStringPoolChunk    *fNext;                       // Ptr to next pool chunk
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t               fLimit;                       // Index to start of unused area at end of fStrings
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar                 fStrings[POOL_CHUNK_SIZE];    //  Strings array
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNStringPoolChunk();
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNStringPoolChunk::ZNStringPoolChunk() {
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fNext = NULL;
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLimit = 0;
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNStringPool::ZNStringPool(UErrorCode &status) {
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fChunks = NULL;
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fHash   = NULL;
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fChunks = new ZNStringPoolChunk;
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fChunks == NULL) {
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fHash   = uhash_open(uhash_hashUChars      /* keyHash */,
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         uhash_compareUChars   /* keyComp */,
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         uhash_compareUChars   /* valueComp */,
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         &status);
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNStringPool::~ZNStringPool() {
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fHash != NULL) {
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_close(fHash);
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fHash = NULL;
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (fChunks != NULL) {
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZNStringPoolChunk *nextChunk = fChunks->fNext;
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fChunks;
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fChunks = nextChunk;
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar EmptyString = 0;
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar *ZNStringPool::get(const UChar *s, UErrorCode &status) {
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *pooledString;
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return &EmptyString;
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    pooledString = static_cast<UChar *>(uhash_get(fHash, s));
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (pooledString != NULL) {
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return pooledString;
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t length = u_strlen(s);
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t remainingLength = POOL_CHUNK_SIZE - fChunks->fLimit;
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (remainingLength <= length) {
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(length < POOL_CHUNK_SIZE);
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (length >= POOL_CHUNK_SIZE) {
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_INTERNAL_PROGRAM_ERROR;
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return &EmptyString;
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZNStringPoolChunk *oldChunk = fChunks;
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fChunks = new ZNStringPoolChunk;
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (fChunks == NULL) {
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return &EmptyString;
469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fChunks->fNext = oldChunk;
471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar *destString = &fChunks->fStrings[fChunks->fLimit];
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_strcpy(destString, s);
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fChunks->fLimit += (length + 1);
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_put(fHash, destString, destString, &status);
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return destString;
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//  ZNStringPool::adopt()    Put a string into the hash, but do not copy the string data
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//                           into the pool's storage.  Used for strings from resource bundles,
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//                           which will perisist for the life of the zone string formatter, and
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//                           therefore can be used directly without copying.
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar *ZNStringPool::adopt(const UChar * s, UErrorCode &status) {
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *pooledString;
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return &EmptyString;
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (s != NULL) {
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pooledString = static_cast<UChar *>(uhash_get(fHash, s));
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (pooledString == NULL) {
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UChar *ncs = const_cast<UChar *>(s);
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fHash, ncs, ncs, &status);
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return s;
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar *ZNStringPool::get(const UnicodeString &s, UErrorCode &status) {
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString &nonConstStr = const_cast<UnicodeString &>(s);
504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return this->get(nonConstStr.getTerminatedBuffer(), status);
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * freeze().   Close the hash table that maps to the pooled strings.
509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *             After freezing, the pool can not be searched or added to,
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *             but all existing references to pooled strings remain valid.
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *             The main purpose is to recover the storage used for the hash.
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid ZNStringPool::freeze() {
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(fHash);
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fHash = NULL;
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ZNames - names common for time zone and meta zone
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass ZNames : public UMemory {
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~ZNames();
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static ZNames* createInstance(UResourceBundle* rb, const char* key);
5288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    virtual const UChar* getName(UTimeZoneNameType type);
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprotected:
531103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    ZNames(const UChar** names);
532103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    static const UChar** loadData(UResourceBundle* rb, const char* key);
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar** fNames;
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
538103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZNames::ZNames(const UChar** names)
539103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius: fNames(names) {
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames::~ZNames() {
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNames != NULL) {
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uprv_free(fNames);
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames*
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames::createInstance(UResourceBundle* rb, const char* key) {
550103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar** names = loadData(rb, key);
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (names == NULL) {
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // No names data available
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
555103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return new ZNames(names);
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames::getName(UTimeZoneNameType type) {
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNames == NULL) {
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *name = NULL;
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    switch(type) {
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_LONG_GENERIC:
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[0];
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_LONG_STANDARD:
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[1];
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_LONG_DAYLIGHT:
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[2];
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_SHORT_GENERIC:
575103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        name = fNames[3];
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_SHORT_STANDARD:
578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[4];
579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_SHORT_DAYLIGHT:
581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[5];
582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
5838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    case UTZNM_EXEMPLAR_LOCATION:   // implemeted by subclass
584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    default:
585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = NULL;
586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar**
591103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZNames::loadData(UResourceBundle* rb, const char* key) {
592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (rb == NULL || key == NULL || *key == 0) {
593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar **names = NULL;
598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle* rbTable = NULL;
600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    rbTable = ures_getByKeyWithFallback(rb, key, rbTable, &status);
601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        names = (const UChar **)uprv_malloc(sizeof(const UChar*) * KEYS_SIZE);
603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (names != NULL) {
604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UBool isEmpty = TRUE;
605b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int32_t i = 0; i < KEYS_SIZE; i++) {
606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                status = U_ZERO_ERROR;
607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t len = 0;
608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const UChar *value = ures_getStringByKeyWithFallback(rbTable, KEYS[i], &len, &status);
609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (U_FAILURE(status) || len == 0) {
610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    names[i] = NULL;
611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    names[i] = value;
613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    isEmpty = FALSE;
614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (isEmpty) {
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // No need to keep the names array
618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_free(names);
619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                names = NULL;
620b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
621b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
623b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(rbTable);
624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return names;
625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
626b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TZNames - names for a time zone
629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass TZNames : public ZNames {
631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~TZNames();
633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
6348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    static TZNames* createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID);
6358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    virtual const UChar* getName(UTimeZoneNameType type);
636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
6388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    TZNames(const UChar** names);
639b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* fLocationName;
6408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UChar* fLocationNameOwned;
641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
6438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTZNames::TZNames(const UChar** names)
6448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius: ZNames(names), fLocationName(NULL), fLocationNameOwned(NULL) {
645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTZNames::~TZNames() {
6488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (fLocationNameOwned) {
6498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        uprv_free(fLocationNameOwned);
6508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
6548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTZNames::getName(UTimeZoneNameType type) {
6558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (type == UTZNM_EXEMPLAR_LOCATION) {
6568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return fLocationName;
6578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
6588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return ZNames::getName(type);
659b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
661b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTZNames*
6628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTZNames::createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID) {
663b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (rb == NULL || key == NULL || *key == 0) {
664b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
6668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const UChar** names = loadData(rb, key);
6688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const UChar* locationName = NULL;
6698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UChar* locationNameOwned = NULL;
6708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
6728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int32_t len = 0;
6738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UResourceBundle* table = ures_getByKeyWithFallback(rb, key, NULL, &status);
6758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    locationName = ures_getStringByKeyWithFallback(table, gEcTag, &len, &status);
6768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // ignore missing resource here
6778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    status = U_ZERO_ERROR;
6788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ures_close(table);
6808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (locationName == NULL) {
6828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        UnicodeString tmpName;
6838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        int32_t tmpNameLen = 0;
6848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        TimeZoneNamesImpl::getDefaultExemplarLocationName(tzID, tmpName);
6858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tmpNameLen = tmpName.length();
6868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (tmpNameLen > 0) {
6888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            locationNameOwned = (UChar*) uprv_malloc(sizeof(UChar) * (tmpNameLen + 1));
6898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (locationNameOwned) {
6908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tmpName.extract(locationNameOwned, tmpNameLen + 1, status);
6918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                locationName = locationNameOwned;
6928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
693b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
6948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
6968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    TZNames* tznames = NULL;
6978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (locationName != NULL || names != NULL) {
6988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames = new TZNames(names);
6998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (tznames == NULL) {
7008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (locationNameOwned) {
7018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                uprv_free(locationNameOwned);
7028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
7048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames->fLocationName = locationName;
7058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames->fLocationNameOwned = locationNameOwned;
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
7078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tznames;
709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// The meta zone ID enumeration class
713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass MetaZoneIDsEnumeration : public StringEnumeration {
715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration();
717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration(const UVector& mzIDs);
718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration(UVector* mzIDs);
719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~MetaZoneIDsEnumeration();
720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static UClassID U_EXPORT2 getStaticClassID(void);
721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual UClassID getDynamicClassID(void) const;
722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual const UnicodeString* snext(UErrorCode& status);
723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual void reset(UErrorCode& status);
724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual int32_t count(UErrorCode& status) const;
725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fLen;
727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fPos;
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UVector* fMetaZoneIDs;
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector *fLocalVector;
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUOBJECT_DEFINE_RTTI_IMPLEMENTATION(MetaZoneIDsEnumeration)
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::MetaZoneIDsEnumeration()
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLen(0), fPos(0), fMetaZoneIDs(NULL), fLocalVector(NULL) {
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::MetaZoneIDsEnumeration(const UVector& mzIDs)
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fPos(0), fMetaZoneIDs(&mzIDs), fLocalVector(NULL) {
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLen = fMetaZoneIDs->size();
741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::MetaZoneIDsEnumeration(UVector *mzIDs)
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLen(0), fPos(0), fMetaZoneIDs(mzIDs), fLocalVector(mzIDs) {
745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fMetaZoneIDs) {
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLen = fMetaZoneIDs->size();
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UnicodeString*
751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::snext(UErrorCode& status) {
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status) && fMetaZoneIDs != NULL && fPos < fLen) {
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        unistr.setTo((const UChar*)fMetaZoneIDs->elementAt(fPos++), -1);
754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return &unistr;
755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::reset(UErrorCode& /*status*/) {
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fPos = 0;
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::count(UErrorCode& /*status*/) const {
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fLen;
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::~MetaZoneIDsEnumeration() {
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLocalVector) {
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLocalVector;
772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * ZNameInfo stores zone name information in the trie
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct ZNameInfo {
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneNameType   type;
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar*        tzID;
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar*        mzID;
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZNameInfo;
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * ZMatchInfo stores zone name match information used by find method
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct ZMatchInfo {
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const ZNameInfo*    znameInfo;
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t             matchLength;
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZMatchInfo;
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ZNameSearchHandler
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass ZNameSearchHandler : public TextTrieMapSearchResultHandler {
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNameSearchHandler(uint32_t types);
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~ZNameSearchHandler();
802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
804103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint32_t fTypes;
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fMaxMatchLen;
809103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* fResults;
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::ZNameSearchHandler(uint32_t types)
813103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius: fTypes(types), fMaxMatchLen(0), fResults(NULL) {
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::~ZNameSearchHandler() {
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fResults != NULL) {
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fResults;
819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node->hasValues()) {
828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t valuesCount = node->countValues();
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < valuesCount; i++) {
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ZNameInfo *nameinfo = (ZNameInfo *)node->getValue(i);
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (nameinfo == NULL) {
832f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                continue;
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if ((nameinfo->type & fTypes) != 0) {
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // matches a requested type
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (fResults == NULL) {
837103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    fResults = new TimeZoneNames::MatchInfoCollection();
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (fResults == NULL) {
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        status = U_MEMORY_ALLOCATION_ERROR;
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (U_SUCCESS(status)) {
843103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    U_ASSERT(fResults != NULL);
844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    if (nameinfo->tzID) {
845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        fResults->addZone(nameinfo->type, matchLength, UnicodeString(nameinfo->tzID, -1), status);
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else {
847103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        U_ASSERT(nameinfo->mzID);
848103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        fResults->addMetaZone(nameinfo->type, matchLength, UnicodeString(nameinfo->mzID, -1), status);
849103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    }
850103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
851103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        fMaxMatchLen = matchLength;
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
860103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames::MatchInfoCollection*
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::getMatches(int32_t& maxMatchLen) {
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // give the ownership to the caller
863103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* results = fResults;
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    maxMatchLen = fMaxMatchLen;
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // reset
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fResults = NULL;
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fMaxMatchLen = 0;
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return results;
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneNamesImpl
874b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneNames implementation class. This is the main
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// part of this module.
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for ZNames
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteZNames(void *obj) {
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (obj != EMPTY) {
886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete (ZNames *)obj;
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for TZNames
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteTZNames(void *obj) {
894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (obj != EMPTY) {
895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete (TZNames *)obj;
896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for ZNameInfo
901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteZNameInfo(void *obj) {
904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(obj);
905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
908b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
90954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gLock = U_MUTEX_INITIALIZER;
91054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::TimeZoneNamesImpl(const Locale& locale, UErrorCode& status)
912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLocale(locale),
913b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fZoneStrings(NULL),
914b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fTZNamesMap(NULL),
915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fMZNamesMap(NULL),
916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fNamesTrieFullyLoaded(FALSE),
917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fNamesTrie(TRUE, deleteZNameInfo) {
918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    initialize(locale, status);
919b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
920b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::initialize(const Locale& locale, UErrorCode& status) {
923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Load zoneStrings bundle
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode tmpsts = U_ZERO_ERROR;   // OK with fallback warning..
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fZoneStrings = ures_open(U_ICUDATA_ZONE, locale.getName(), &tmpsts);
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fZoneStrings = ures_getByKeyWithFallback(fZoneStrings, gZoneStrings, fZoneStrings, &tmpsts);
931b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(tmpsts)) {
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = tmpsts;
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
937b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Initialize hashtables holding time zone/meta zone names
938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fMZNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTZNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_setValueDeleter(fMZNamesMap, deleteZNames);
946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_setValueDeleter(fTZNamesMap, deleteTZNames);
947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // no key deleters for name maps
948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // preload zone strings for the default zone
950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZone *tz = TimeZone::createDefault();
951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz);
952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID != NULL) {
953b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        loadStrings(UnicodeString(tzID));
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete tz;
956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return;
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock,
962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * except initializer.
963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::loadStrings(const UnicodeString& tzCanonicalID) {
966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    loadTimeZoneNames(tzCanonicalID);
967b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
968b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
969b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringEnumeration *mzIDs = getAvailableMetaZoneIDs(tzCanonicalID, status);
970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status) && mzIDs != NULL) {
971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UnicodeString *mzID;
972b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while ((mzID = mzIDs->snext(status))) {
973b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            loadMetaZoneNames(*mzID);
977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
978b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete mzIDs;
979b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
982b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::~TimeZoneNamesImpl() {
983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cleanup();
984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::cleanup() {
988b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fZoneStrings != NULL) {
989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ures_close(fZoneStrings);
990b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fZoneStrings = NULL;
991b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
992b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fMZNamesMap != NULL) {
993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_close(fMZNamesMap);
994b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fMZNamesMap = NULL;
995b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fTZNamesMap != NULL) {
997b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_close(fTZNamesMap);
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fTZNamesMap = NULL;
999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1002103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUBool
1003103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNamesImpl::operator==(const TimeZoneNames& other) const {
1004103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (this == &other) {
1005103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return TRUE;
1006103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1007103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // No implementation for now
1008103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return FALSE;
1009103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1010103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1011103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames*
1012103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNamesImpl::clone() const {
1013103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UErrorCode status = U_ZERO_ERROR;
1014103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return new TimeZoneNamesImpl(fLocale, status);
1015103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1016103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration*
1018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
1019f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
1020f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1021f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1022f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// static implementation of getAvailableMetaZoneIDs(UErrorCode&)
1023f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusStringEnumeration*
1024f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTimeZoneNamesImpl::_getAvailableMetaZoneIDs(UErrorCode& status) {
1025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UVector* mzIDs = ZoneMeta::getAvailableMetazoneIDs();
1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzIDs == NULL) {
1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return new MetaZoneIDsEnumeration();
1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return new MetaZoneIDsEnumeration(*mzIDs);
1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration*
1036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
1037f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
1038f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1039f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1040f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// static implementation of getAvailableMetaZoneIDs(const UnicodeString&, UErrorCode&)
1041f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusStringEnumeration*
1042f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTimeZoneNamesImpl::_getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) {
1043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UVector* mappings = ZoneMeta::getMetazoneMappings(tzID);
1047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mappings == NULL) {
1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return new MetaZoneIDsEnumeration();
1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration *senum = NULL;
1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector* mzIDs = new UVector(NULL, uhash_compareUChars, status);
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzIDs == NULL) {
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
1057103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U_ASSERT(mzIDs != NULL);
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; U_SUCCESS(status) && i < mappings->size(); i++) {
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            OlsonToMetaMappingEntry *map = (OlsonToMetaMappingEntry *)mappings->elementAt(i);
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UChar *mzID = map->mzid;
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!mzIDs->contains((void *)mzID)) {
1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                mzIDs->addElement((void *)mzID, status);
1064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status)) {
1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            senum = new MetaZoneIDsEnumeration(mzIDs);
1068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            delete mzIDs;
1070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return senum;
1073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1074b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1075b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
1077f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
1078f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1079f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1080f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// static implementation of getMetaZoneID
1081f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUnicodeString&
1082f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTimeZoneNamesImpl::_getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) {
1083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZoneMeta::getMetazoneID(tzID, date, mzID);
1084b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return mzID;
1085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1087b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
1089f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
1090f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1091f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1092f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// static implementaion of getReferenceZoneID
1093f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUnicodeString&
1094f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTimeZoneNamesImpl::_getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) {
1095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZoneMeta::getZoneIdByMetazone(mzID, UnicodeString(region, -1, US_INV), tzID);
1096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tzID;
1097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1099f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
1102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          UTimeZoneNameType type,
1103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          UnicodeString& name) const {
1104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();  // cleanup result.
1105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzID.isEmpty()) {
1106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNames *znames = NULL;
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
111254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        znames = nonConstThis->loadMetaZoneNames(mzID);
1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
111654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (znames != NULL) {
1119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* s = znames->getName(type);
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (s != NULL) {
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            name.setTo(TRUE, s, -1);
1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const {
1129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();  // cleanup result.
1130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID.isEmpty()) {
1131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
1132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZNames *tznames = NULL;
1135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
113754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tznames = nonConstThis->loadTimeZoneNames(tzID);
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
114154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tznames != NULL) {
1144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar *s = tznames->getName(type);
1145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (s != NULL) {
1146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            name.setTo(TRUE, s, -1);
1147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
1150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const {
11548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    name.setToBogus();  // cleanup result.
1155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* locName = NULL;
1156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZNames *tznames = NULL;
1157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
115954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tznames = nonConstThis->loadTimeZoneNames(tzID);
1162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
116354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tznames != NULL) {
11668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        locName = tznames->getName(UTZNM_EXEMPLAR_LOCATION);
1167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (locName != NULL) {
1169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setTo(TRUE, locName, -1);
1170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
11728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return name;
1173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Merge the MZ_PREFIX and mzId
1177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void mergeTimeZoneKey(const UnicodeString& mzID, char* result) {
1178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzID.isEmpty()) {
1179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result[0] = '\0';
1180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    char mzIdChar[ZID_KEY_MAX + 1];
1184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t keyLen;
1185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prefixLen = uprv_strlen(gMZPrefix);
1186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    keyLen = mzID.extract(0, mzID.length(), mzIdChar, ZID_KEY_MAX + 1, US_INV);
1187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memcpy((void *)result, (void *)gMZPrefix, prefixLen);
1188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memcpy((void *)(result + prefixLen), (void *)mzIdChar, keyLen);
1189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    result[keyLen + prefixLen] = '\0';
1190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
1193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock
1194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
1195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames*
1196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID) {
1197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzID.length() > (ZID_KEY_MAX - MZ_PREFIX_LEN)) {
1198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNames *znames = NULL;
1202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar mzIDKey[ZID_KEY_MAX + 1];
1205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
1206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
1207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    mzIDKey[mzID.length()] = 0;
1208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void *cacheVal = uhash_get(fMZNamesMap, mzIDKey);
1210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cacheVal == NULL) {
1211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char key[ZID_KEY_MAX + 1];
1212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        mergeTimeZoneKey(mzID, key);
1213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        znames = ZNames::createInstance(fZoneStrings, key);
1214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (znames == NULL) {
1216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = (void *)EMPTY;
1217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = znames;
1219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Use the persistent ID as the resource key, so we can
1221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // avoid duplications.
1222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
1223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (newKey != NULL) {
1224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fMZNamesMap, (void *)newKey, cacheVal, &status);
1225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
1226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (znames != NULL) {
1227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete znames;
1228f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    znames = NULL;
1229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (znames != NULL) {
1231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // put the name info into the trie
1232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) {
1233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    const UChar* name = znames->getName(ALL_NAME_TYPES[i]);
1234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (name != NULL) {
1235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZNameInfo));
1236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (nameinfo != NULL) {
1237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->type = ALL_NAME_TYPES[i];
1238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->tzID = NULL;
1239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->mzID = newKey;
1240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            fNamesTrie.put(name, nameinfo, status);
1241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
1242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Should never happen with a valid input
1248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (znames != NULL) {
1249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // It's not possible that we get a valid ZNames with unknown ID.
1250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // But just in case..
1251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete znames;
1252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                znames = NULL;
1253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (cacheVal != EMPTY) {
1256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        znames = (ZNames *)cacheVal;
1257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return znames;
1260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
1263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock
1264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
1265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTZNames*
1266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) {
1267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID.length() > ZID_KEY_MAX) {
1268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZNames *tznames = NULL;
1272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar tzIDKey[ZID_KEY_MAX + 1];
1275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t tzIDKeyLen = tzID.extract(tzIDKey, ZID_KEY_MAX + 1, status);
1276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
1277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    tzIDKey[tzIDKeyLen] = 0;
1278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void *cacheVal = uhash_get(fTZNamesMap, tzIDKey);
1280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cacheVal == NULL) {
1281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char key[ZID_KEY_MAX + 1];
1282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UErrorCode status = U_ZERO_ERROR;
1283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Replace "/" with ":".
1284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString uKey(tzID);
1285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < uKey.length(); i++) {
1286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (uKey.charAt(i) == (UChar)0x2F) {
1287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uKey.setCharAt(i, (UChar)0x3A);
1288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uKey.extract(0, uKey.length(), key, sizeof(key), US_INV);
12918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames = TZNames::createInstance(fZoneStrings, key, tzID);
1292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (tznames == NULL) {
1294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = (void *)EMPTY;
1295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = tznames;
1297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Use the persistent ID as the resource key, so we can
1299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // avoid duplications.
1300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* newKey = ZoneMeta::findTimeZoneID(tzID);
1301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (newKey != NULL) {
1302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fTZNamesMap, (void *)newKey, cacheVal, &status);
1303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
1304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (tznames != NULL) {
1305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete tznames;
1306f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    tznames = NULL;
1307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (tznames != NULL) {
1309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // put the name info into the trie
1310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) {
1311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    const UChar* name = tznames->getName(ALL_NAME_TYPES[i]);
1312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (name != NULL) {
1313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZNameInfo));
1314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (nameinfo != NULL) {
1315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->type = ALL_NAME_TYPES[i];
1316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->tzID = newKey;
1317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->mzID = NULL;
1318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            fNamesTrie.put(name, nameinfo, status);
1319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
1320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Should never happen with a valid input
1325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tznames != NULL) {
1326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // It's not possible that we get a valid TZNames with unknown ID.
1327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // But just in case..
1328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete tznames;
1329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                tznames = NULL;
1330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (cacheVal != EMPTY) {
1333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tznames = (TZNames *)cacheVal;
1334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tznames;
1337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1339103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames::MatchInfoCollection*
1340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
1341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNameSearchHandler handler(types);
1342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
134554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
1348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
134954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t maxLen = 0;
1356103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* matches = handler.getMatches(maxLen);
1357103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (matches != NULL && ((maxLen == (text.length() - start)) || fNamesTrieFullyLoaded)) {
1358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // perfect match
1359103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return matches;
1360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1362103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    delete matches;
1363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // All names are not yet loaded into the trie
136554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!fNamesTrieFullyLoaded) {
1368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UnicodeString *id;
1369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // load strings for all zones
1371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
1372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                while ((id = tzIDs->snext(status))) {
1374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(status)) {
1375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
1376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // loadStrings also load related metazone strings
1378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nonConstThis->loadStrings(*id);
1379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tzIDs != NULL) {
1382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete tzIDs;
1383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                nonConstThis->fNamesTrieFullyLoaded = TRUE;
1386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
138954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
139554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // now try it again
1398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
1399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
140054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1402103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return handler.getMatches(maxLen);
1403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
14058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar gEtcPrefix[]         = { 0x45, 0x74, 0x63, 0x2F }; // "Etc/"
14068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const int32_t gEtcPrefixLen      = 4;
14078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar gSystemVPrefix[]     = { 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x56, 0x2F }; // "SystemV/
14088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const int32_t gSystemVPrefixLen  = 8;
14098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar gRiyadh8[]           = { 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, 0x38 }; // "Riyadh8"
14108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const int32_t gRiyadh8Len       = 7;
14118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
14128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusUnicodeString& U_EXPORT2
14138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTimeZoneNamesImpl::getDefaultExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) {
14148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (tzID.isEmpty() || tzID.startsWith(gEtcPrefix, gEtcPrefixLen)
14158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        || tzID.startsWith(gSystemVPrefix, gSystemVPrefixLen) || tzID.indexOf(gRiyadh8, gRiyadh8Len, 0) > 0) {
14168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.setToBogus();
14178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return name;
14188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
14198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
14208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int32_t sep = tzID.lastIndexOf((UChar)0x2F /* '/' */);
14218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (sep > 0 && sep + 1 < tzID.length()) {
14228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.setTo(tzID, sep + 1);
14238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.findAndReplace(UnicodeString((UChar)0x5f /* _ */),
14248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            UnicodeString((UChar)0x20 /* space */));
14258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    } else {
14268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.setToBogus();
14278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
14288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return name;
14298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
14308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1431f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// ---------------------------------------------------
1432f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// TZDBTimeZoneNames and its supporting classes
1433f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius//
1434f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// TZDBTimeZoneNames is an implementation class of
1435f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// TimeZoneNames holding the IANA tz database abbreviations.
1436f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// ---------------------------------------------------
1437f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1438f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusclass TZDBNames : public UMemory {
1439f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliuspublic:
1440f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    virtual ~TZDBNames();
1441f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1442f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    static TZDBNames* createInstance(UResourceBundle* rb, const char* key);
1443f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UChar* getName(UTimeZoneNameType type) const;
1444f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const char** getParseRegions(int32_t& numRegions) const;
1445f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1446f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusprotected:
1447f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TZDBNames(const UChar** names, char** regions, int32_t numRegions);
1448f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1449f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusprivate:
1450f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UChar** fNames;
1451f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    char** fRegions;
1452f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t fNumRegions;
1453f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
1454f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1455f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNames::TZDBNames(const UChar** names, char** regions, int32_t numRegions)
1456f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    :   fNames(names),
1457f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        fRegions(regions),
1458f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        fNumRegions(numRegions) {
1459f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1460f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1461f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNames::~TZDBNames() {
1462f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (fNames != NULL) {
1463f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_free(fNames);
1464f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1465f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (fRegions != NULL) {
1466f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        char **p = fRegions;
1467f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        for (int32_t i = 0; i < fNumRegions; p++, i++) {
1468f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            uprv_free(*p);
1469f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1470f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_free(fRegions);
1471f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1472f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1473f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1474f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNames*
1475f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNames::createInstance(UResourceBundle* rb, const char* key) {
1476f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (rb == NULL || key == NULL || *key == 0) {
1477f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1478f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1479f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1480f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UErrorCode status = U_ZERO_ERROR;
1481f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1482f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UChar **names = NULL;
1483f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    char** regions = NULL;
1484f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t numRegions = 0;
1485f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1486f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t len = 0;
1487f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1488f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UResourceBundle* rbTable = NULL;
1489f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    rbTable = ures_getByKey(rb, key, rbTable, &status);
1490f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1491f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1492f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1493f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1494f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    names = (const UChar **)uprv_malloc(sizeof(const UChar*) * TZDBNAMES_KEYS_SIZE);
1495f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UBool isEmpty = TRUE;
1496f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (names != NULL) {
1497f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        for (int32_t i = 0; i < TZDBNAMES_KEYS_SIZE; i++) {
1498f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            status = U_ZERO_ERROR;
1499f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const UChar *value = ures_getStringByKey(rbTable, TZDBNAMES_KEYS[i], &len, &status);
1500f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (U_FAILURE(status) || len == 0) {
1501f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                names[i] = NULL;
1502f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            } else {
1503f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                names[i] = value;
1504f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                isEmpty = FALSE;
1505f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1506f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1507f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1508f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1509f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (isEmpty) {
1510f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (names != NULL) {
1511f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            uprv_free(names);
1512f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1513f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1514f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1515f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1516f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UResourceBundle *regionsRes = ures_getByKey(rbTable, "parseRegions", NULL, &status);
1517f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UBool regionError = FALSE;
1518f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_SUCCESS(status)) {
1519f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        numRegions = ures_getSize(regionsRes);
1520f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (numRegions > 0) {
1521f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            regions = (char**)uprv_malloc(sizeof(char*) * numRegions);
1522f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (regions != NULL) {
1523f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                char **pRegion = regions;
1524f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                for (int32_t i = 0; i < numRegions; i++, pRegion++) {
1525f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    *pRegion = NULL;
1526f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1527f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // filling regions
1528f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                pRegion = regions;
1529f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                for (int32_t i = 0; i < numRegions; i++, pRegion++) {
1530f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    status = U_ZERO_ERROR;
1531f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    const UChar *uregion = ures_getStringByIndex(regionsRes, i, &len, &status);
1532f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (U_FAILURE(status)) {
1533f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        regionError = TRUE;
1534f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        break;
1535f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1536f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    *pRegion = (char*)uprv_malloc(sizeof(char) * (len + 1));
1537f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (*pRegion == NULL) {
1538f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        regionError = TRUE;
1539f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        break;
1540f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1541f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    u_UCharsToChars(uregion, *pRegion, len);
1542f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    (*pRegion)[len] = 0;
1543f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1544f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1545f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1546f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1547f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ures_close(regionsRes);
1548f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ures_close(rbTable);
1549f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1550f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (regionError) {
1551f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (names != NULL) {
1552f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            uprv_free(names);
1553f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1554f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (regions != NULL) {
1555f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            char **p = regions;
1556f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            for (int32_t i = 0; i < numRegions; p++, i++) {
1557f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                uprv_free(p);
1558f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1559f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            uprv_free(regions);
1560f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1561f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1562f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1563f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1564f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return new TZDBNames(names, regions, numRegions);
1565f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1566f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1567f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusconst UChar*
1568f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNames::getName(UTimeZoneNameType type) const {
1569f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (fNames == NULL) {
1570f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1571f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1572f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UChar *name = NULL;
1573f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    switch(type) {
1574f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    case UTZNM_SHORT_STANDARD:
1575f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        name = fNames[0];
1576f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        break;
1577f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    case UTZNM_SHORT_DAYLIGHT:
1578f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        name = fNames[1];
1579f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        break;
1580f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    default:
1581f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        name = NULL;
1582f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1583f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return name;
1584f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1585f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1586f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusconst char**
1587f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNames::getParseRegions(int32_t& numRegions) const {
1588f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (fRegions == NULL) {
1589f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        numRegions = 0;
1590f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    } else {
1591f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        numRegions = fNumRegions;
1592f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1593f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return (const char**)fRegions;
1594f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1595f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1596f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CDECL_BEGIN
1597f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius/**
1598f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * TZDBNameInfo stores metazone name information for the IANA abbreviations
1599f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * in the trie
1600f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */
1601f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliustypedef struct TZDBNameInfo {
1602f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UChar*        mzID;
1603f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UTimeZoneNameType   type;
1604f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UBool               ambiguousType;
1605f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const char**        parseRegions;
1606f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t             nRegions;
1607f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius} TZDBNameInfo;
1608f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CDECL_END
1609f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1610f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1611f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusclass TZDBNameSearchHandler : public TextTrieMapSearchResultHandler {
1612f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliuspublic:
1613f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TZDBNameSearchHandler(uint32_t types, const char* region);
1614f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    virtual ~TZDBNameSearchHandler();
1615f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1616f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
1617f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
1618f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1619f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusprivate:
1620f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    uint32_t fTypes;
1621f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t fMaxMatchLen;
1622f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TimeZoneNames::MatchInfoCollection* fResults;
1623f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const char* fRegion;
1624f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius};
1625f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1626f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNameSearchHandler::TZDBNameSearchHandler(uint32_t types, const char* region)
1627f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius: fTypes(types), fMaxMatchLen(0), fResults(NULL), fRegion(region) {
1628f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1629f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1630f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNameSearchHandler::~TZDBNameSearchHandler() {
1631f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (fResults != NULL) {
1632f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        delete fResults;
1633f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1634f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1635f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1636f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUBool
1637f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
1638f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1639f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return FALSE;
1640f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1641f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1642f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TZDBNameInfo *match = NULL;
1643f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TZDBNameInfo *defaultRegionMatch = NULL;
1644f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1645f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (node->hasValues()) {
1646f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        int32_t valuesCount = node->countValues();
1647f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        for (int32_t i = 0; i < valuesCount; i++) {
1648f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            TZDBNameInfo *ninfo = (TZDBNameInfo *)node->getValue(i);
1649f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (ninfo == NULL) {
1650f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                continue;
1651f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1652f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if ((ninfo->type & fTypes) != 0) {
1653f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // Some tz database abbreviations are ambiguous. For example,
1654f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // CST means either Central Standard Time or China Standard Time.
1655f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // Unlike CLDR time zone display names, this implementation
1656f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // does not use unique names. And TimeZoneFormat does not expect
1657f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // multiple results returned for the same time zone type.
1658f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // For this reason, this implementation resolve one among same
1659f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // zone type with a same name at this level.
1660f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (ninfo->parseRegions == NULL) {
1661f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // parseRegions == null means this is the default metazone
1662f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // mapping for the abbreviation.
1663f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (defaultRegionMatch == NULL) {
1664f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        match = defaultRegionMatch = ninfo;
1665f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1666f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                } else {
1667f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    UBool matchRegion = FALSE;
1668f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // non-default metazone mapping for an abbreviation
1669f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // comes with applicable regions. For example, the default
1670f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // metazone mapping for "CST" is America_Central,
1671f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // but if region is one of CN/MO/TW, "CST" is parsed
1672f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // as metazone China (China Standard Time).
1673f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    for (int32_t i = 0; i < ninfo->nRegions; i++) {
1674f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        const char *region = ninfo->parseRegions[i];
1675f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        if (uprv_strcmp(fRegion, region) == 0) {
1676f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                            match = ninfo;
1677f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                            matchRegion = TRUE;
1678f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                            break;
1679f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        }
1680f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1681f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (matchRegion) {
1682f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        break;
1683f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1684f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (match == NULL) {
1685f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        match = ninfo;
1686f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1687f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1688f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1689f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1690f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1691f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (match != NULL) {
1692f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            UTimeZoneNameType ntype = match->type;
1693f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // Note: Workaround for duplicated standard/daylight names
1694f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // The tz database contains a few zones sharing a
1695f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // same name for both standard time and daylight saving
1696f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // time. For example, Australia/Sydney observes DST,
1697f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // but "EST" is used for both standard and daylight.
1698f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // When both SHORT_STANDARD and SHORT_DAYLIGHT are included
1699f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // in the find operation, we cannot tell which one was
1700f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // actually matched.
1701f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // TimeZoneFormat#parse returns a matched name type (standard
1702f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // or daylight) and DateFormat implementation uses the info to
1703f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // to adjust actual time. To avoid false type information,
1704f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // this implementation replaces the name type with SHORT_GENERIC.
1705f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (match->ambiguousType
1706f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    && (ntype == UTZNM_SHORT_STANDARD || ntype == UTZNM_SHORT_DAYLIGHT)
1707f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    && (fTypes & UTZNM_SHORT_STANDARD) != 0
1708f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    && (fTypes & UTZNM_SHORT_DAYLIGHT) != 0) {
1709f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                ntype = UTZNM_SHORT_GENERIC;
1710f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1711f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1712f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (fResults == NULL) {
1713f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                fResults = new TimeZoneNames::MatchInfoCollection();
1714f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (fResults == NULL) {
1715f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    status = U_MEMORY_ALLOCATION_ERROR;
1716f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1717f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1718f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (U_SUCCESS(status)) {
1719f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                U_ASSERT(fResults != NULL);
1720f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                U_ASSERT(match->mzID != NULL);
1721f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                fResults->addMetaZone(ntype, matchLength, UnicodeString(match->mzID, -1), status);
1722f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
1723f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    fMaxMatchLen = matchLength;
1724f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1725f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1726f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1727f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1728f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TRUE;
1729f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1730f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1731f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTimeZoneNames::MatchInfoCollection*
1732f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBNameSearchHandler::getMatches(int32_t& maxMatchLen) {
1733f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // give the ownership to the caller
1734f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TimeZoneNames::MatchInfoCollection* results = fResults;
1735f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    maxMatchLen = fMaxMatchLen;
1736f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1737f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // reset
1738f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    fResults = NULL;
1739f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    fMaxMatchLen = 0;
1740f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return results;
1741f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1742f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1743f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CDECL_BEGIN
1744f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius/**
1745f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Deleter for TZDBNames
1746f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */
1747f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV
1748f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusdeleteTZDBNames(void *obj) {
1749f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (obj != EMPTY) {
1750f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        delete (TZDBNames *)obj;
1751f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1752f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1753f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1754f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV initTZDBNamesMap(UErrorCode &status) {
1755f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTZDBNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
1756f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1757f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        gTZDBNamesMap = NULL;
1758f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1759f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1760f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // no key deleters for tzdb name maps
1761f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    uhash_setValueDeleter(gTZDBNamesMap, deleteTZDBNames);
1762f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cleanup);
1763f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1764f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1765f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius/**
1766f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Deleter for TZDBNameInfo
1767f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */
1768f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV
1769f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusdeleteTZDBNameInfo(void *obj) {
1770f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (obj != NULL) {
1771f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_free(obj);
1772f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1773f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1774f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1775f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusstatic void U_CALLCONV prepareFind(UErrorCode &status) {
1776f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1777f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1778f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1779f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTZDBNamesTrie = new TextTrieMap(TRUE, deleteTZDBNameInfo);
1780f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (gTZDBNamesTrie == NULL) {
1781f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        status = U_MEMORY_ALLOCATION_ERROR;
1782f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1783f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1784f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1785f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const UnicodeString *mzID;
1786f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    StringEnumeration *mzIDs = TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
1787f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_SUCCESS(status)) {
1788f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        while ((mzID = mzIDs->snext(status)) && U_SUCCESS(status)) {
1789f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const TZDBNames *names = TZDBTimeZoneNames::getMetaZoneNames(*mzID, status);
1790f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (names == NULL) {
1791f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                continue;
1792f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1793f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const UChar *std = names->getName(UTZNM_SHORT_STANDARD);
1794f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const UChar *dst = names->getName(UTZNM_SHORT_DAYLIGHT);
1795f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (std == NULL && dst == NULL) {
1796f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                continue;
1797f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1798f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            int32_t numRegions = 0;
1799f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const char **parseRegions = names->getParseRegions(numRegions);
1800f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1801f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // The tz database contains a few zones sharing a
1802f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // same name for both standard time and daylight saving
1803f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // time. For example, Australia/Sydney observes DST,
1804f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // but "EST" is used for both standard and daylight.
1805f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            // we need to store the information for later processing.
1806f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            UBool ambiguousType = (std != NULL && dst != NULL && u_strcmp(std, dst) == 0);
1807f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1808f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            const UChar *uMzID = ZoneMeta::findMetaZoneID(*mzID);
1809f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (std != NULL) {
1810f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                TZDBNameInfo *stdInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNameInfo));
1811f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (stdInf == NULL) {
1812f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    status = U_MEMORY_ALLOCATION_ERROR;
1813f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    break;
1814f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1815f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                stdInf->mzID = uMzID;
1816f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                stdInf->type = UTZNM_SHORT_STANDARD;
1817f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                stdInf->ambiguousType = ambiguousType;
1818f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                stdInf->parseRegions = parseRegions;
1819f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                stdInf->nRegions = numRegions;
1820f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                gTZDBNamesTrie->put(std, stdInf, status);
1821f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1822f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (U_SUCCESS(status) && dst != NULL) {
1823f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                TZDBNameInfo *dstInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNameInfo));
1824f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (dstInf == NULL) {
1825f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    status = U_MEMORY_ALLOCATION_ERROR;
1826f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    break;
1827f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1828f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                dstInf->mzID = uMzID;
1829f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                dstInf->type = UTZNM_SHORT_DAYLIGHT;
1830f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                dstInf->ambiguousType = ambiguousType;
1831f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                dstInf->parseRegions = parseRegions;
1832f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                dstInf->nRegions = numRegions;
1833f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                gTZDBNamesTrie->put(dst, dstInf, status);
1834f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
1835f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1836f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1837f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    delete mzIDs;
1838f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1839f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1840f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        delete gTZDBNamesTrie;
1841f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        gTZDBNamesTrie = NULL;
1842f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return;
1843f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1844f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1845f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cleanup);
1846f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1847f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1848f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusU_CDECL_END
1849f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1850f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale)
1851f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius: fLocale(locale) {
1852f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UBool useWorld = TRUE;
1853f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const char* region = fLocale.getCountry();
1854f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t regionLen = uprv_strlen(region);
1855f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (regionLen == 0) {
1856f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        UErrorCode status = U_ZERO_ERROR;
1857f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        char loc[ULOC_FULLNAME_CAPACITY];
1858f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status);
1859f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        regionLen = uloc_getCountry(loc, fRegion, sizeof(fRegion), &status);
1860f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (U_SUCCESS(status) && regionLen < (int32_t)sizeof(fRegion)) {
1861f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            useWorld = FALSE;
1862f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1863f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    } else if (regionLen < (int32_t)sizeof(fRegion)) {
1864f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_strcpy(fRegion, region);
1865f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        useWorld = FALSE;
1866f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1867f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (useWorld) {
1868f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        uprv_strcpy(fRegion, "001");
1869f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1870f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1871f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1872f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::~TZDBTimeZoneNames() {
1873f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1874f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1875f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUBool
1876f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::operator==(const TimeZoneNames& other) const {
1877f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (this == &other) {
1878f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return TRUE;
1879f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1880f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // No implementation for now
1881f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return FALSE;
1882f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1883f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1884f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTimeZoneNames*
1885f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::clone() const {
1886f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return new TZDBTimeZoneNames(fLocale);
1887f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1888f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1889f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusStringEnumeration*
1890f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getAvailableMetaZoneIDs(UErrorCode& status) const {
1891f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
1892f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1893f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1894f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusStringEnumeration*
1895f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
1896f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
1897f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1898f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1899f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUnicodeString&
1900f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
1901f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
1902f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1903f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1904f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUnicodeString&
1905f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
1906f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
1907f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1908f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1909f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUnicodeString&
1910f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getMetaZoneDisplayName(const UnicodeString& mzID,
1911f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                                          UTimeZoneNameType type,
1912f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                                          UnicodeString& name) const {
1913f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    name.setToBogus();
1914f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (mzID.isEmpty()) {
1915f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return name;
1916f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1917f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1918f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UErrorCode status = U_ZERO_ERROR;
1919f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    const TZDBNames *tzdbNames = TZDBTimeZoneNames::getMetaZoneNames(mzID, status);
1920f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_SUCCESS(status)) {
1921f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        const UChar *s = tzdbNames->getName(type);
1922f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (s != NULL) {
1923f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            name.setTo(TRUE, s, -1);
1924f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
1925f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1926f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1927f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return name;
1928f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1929f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1930f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusUnicodeString&
1931f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getTimeZoneDisplayName(const UnicodeString& /* tzID */, UTimeZoneNameType /* type */, UnicodeString& name) const {
1932f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    // No abbreviations associated a zone directly for now.
1933f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    name.setToBogus();
1934f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return name;
1935f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1936f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1937f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::MatchInfoCollection*
1938f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
1939f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_initOnce(gTZDBNamesTrieInitOnce, &prepareFind, status);
1940f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1941f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1942f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1943f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1944f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TZDBNameSearchHandler handler(types, fRegion);
1945f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    gTZDBNamesTrie->search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
1946f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1947f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1948f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1949f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    int32_t maxLen = 0;
1950f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return handler.getMatches(maxLen);
1951f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1952f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1953f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusconst TZDBNames*
1954f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusTZDBTimeZoneNames::getMetaZoneNames(const UnicodeString& mzID, UErrorCode& status) {
1955f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_initOnce(gTZDBNamesMapInitOnce, &initTZDBNamesMap, status);
1956f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    if (U_FAILURE(status)) {
1957f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        return NULL;
1958f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
1959f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1960f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    TZDBNames* tzdbNames = NULL;
1961f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1962f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    UChar mzIDKey[ZID_KEY_MAX + 1];
1963f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
1964f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
1965f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    mzIDKey[mzID.length()] = 0;
1966f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1967f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_lock(&gTZDBNamesMapLock);
1968f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    {
1969f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey);
1970f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        if (cacheVal == NULL) {
1971f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            UResourceBundle *zoneStringsRes = ures_openDirect(U_ICUDATA_ZONE, "tzdbNames", &status);
1972f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            zoneStringsRes = ures_getByKey(zoneStringsRes, gZoneStrings, zoneStringsRes, &status);
1973f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            if (U_SUCCESS(status)) {
1974f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                char key[ZID_KEY_MAX + 1];
1975f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                mergeTimeZoneKey(mzID, key);
1976f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                tzdbNames = TZDBNames::createInstance(zoneStringsRes, key);
1977f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1978f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (tzdbNames == NULL) {
1979f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    cacheVal = (void *)EMPTY;
1980f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                } else {
1981f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    cacheVal = tzdbNames;
1982f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
1983f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // Use the persistent ID as the resource key, so we can
1984f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                // avoid duplications.
1985f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
1986f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                if (newKey != NULL) {
1987f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    uhash_put(gTZDBNamesMap, (void *)newKey, cacheVal, &status);
1988f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (U_FAILURE(status)) {
1989f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        if (tzdbNames != NULL) {
1990f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                            delete tzdbNames;
1991f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                            tzdbNames = NULL;
1992f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        }
1993f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
1994f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                } else {
1995f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    // Should never happen with a valid input
1996f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    if (tzdbNames != NULL) {
1997f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        // It's not possible that we get a valid tzdbNames with unknown ID.
1998f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        // But just in case..
1999f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        delete tzdbNames;
2000f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                        tzdbNames = NULL;
2001f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                    }
2002f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                }
2003f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            }
2004f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            ures_close(zoneStringsRes);
2005f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        } else if (cacheVal != EMPTY) {
2006f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius            tzdbNames = (TZDBNames *)cacheVal;
2007f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        }
2008f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    }
2009f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    umtx_unlock(&gTZDBNamesMapLock);
2010f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
2011f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return tzdbNames;
2012f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
2013f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
2014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_END
2015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif /* #if !UCONFIG_NO_FORMATTING */
2018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
2019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//eof
2020