1b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
2b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho*******************************************************************************
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius* Copyright (C) 2011-2013, 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"
23b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uresimp.h"
24b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ureslocs.h"
25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "zonemeta.h"
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ucln_in.h"
27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uvector.h"
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "olsontz.h"
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_BEGIN
32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define ZID_KEY_MAX  128
34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define MZ_PREFIX_LEN 5
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gZoneStrings[]        = "zoneStrings";
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gMZPrefix[]           = "meta:";
38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char* KEYS[]               = {"lg", "ls", "ld", "sg", "ss", "sd"};
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t KEYS_SIZE = (sizeof KEYS / sizeof KEYS[0]);
41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char gEcTag[]              = "ec";
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const char EMPTY[]               = "<empty>";   // place holder for empty ZNames/TZNames
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UTimeZoneNameType ALL_NAME_TYPES[] = {
47b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTZNM_LONG_GENERIC, UTZNM_LONG_STANDARD, UTZNM_LONG_DAYLIGHT,
48b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTZNM_SHORT_GENERIC, UTZNM_SHORT_STANDARD, UTZNM_SHORT_DAYLIGHT,
498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UTZNM_EXEMPLAR_LOCATION,
50b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTZNM_UNKNOWN // unknown as the last one
51b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
52b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
53b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define DEFAULT_CHARACTERNODE_CAPACITY 1
54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
55b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
56103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// CharacterNode class implementation
57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid CharacterNode::clear() {
59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memset(this, 0, sizeof(*this));
60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid CharacterNode::deleteValues(UObjectDeleter *valueDeleter) {
63b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fValues == NULL) {
64b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Do nothing.
65b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (!fHasValuesVector) {
66b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (valueDeleter) {
67b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            valueDeleter(fValues);
68b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
69b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete (UVector *)fValues;
71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCharacterNode::addValue(void *value, UObjectDeleter *valueDeleter, UErrorCode &status) {
76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (valueDeleter) {
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            valueDeleter(value);
79b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
81b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
82b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fValues == NULL) {
83b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fValues = value;
84b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
85b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // At least one value already.
86b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!fHasValuesVector) {
87b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // There is only one value so far, and not in a vector yet.
88b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Create a vector and add the old value.
89b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UVector *values = new UVector(valueDeleter, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status);
90b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (valueDeleter) {
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    valueDeleter(value);
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
94b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            values->addElement(fValues, status);
97b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fValues = values;
98b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fHasValuesVector = TRUE;
99b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Add the new value.
101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ((UVector *)fValues)->addElement(value, status);
102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TextTrieMapSearchResultHandler class implementation
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMapSearchResultHandler::~TextTrieMapSearchResultHandler(){
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TextTrieMap class implementation
113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::TextTrieMap(UBool ignoreCase, UObjectDeleter *valueDeleter)
115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fIgnoreCase(ignoreCase), fNodes(NULL), fNodesCapacity(0), fNodesCount(0),
116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fLazyContents(NULL), fIsEmpty(TRUE), fValueDeleter(valueDeleter) {
117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::~TextTrieMap() {
120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t index;
121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (index = 0; index < fNodesCount; ++index) {
122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes[index].deleteValues(fValueDeleter);
123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(fNodes);
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLazyContents != NULL) {
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i=0; i<fLazyContents->size(); i+=2) {
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (fValueDeleter) {
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                fValueDeleter(fLazyContents->elementAt(i+1));
129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLazyContents;
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t TextTrieMap::isEmpty() const {
136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Use a separate field for fIsEmpty because it will remain unchanged once the
137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   Trie is built, while fNodes and fLazyContents change with the lazy init
138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   of the nodes structure.  Trying to test the changing fields has
139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   thread safety complications.
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fIsEmpty;
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//  We defer actually building the TextTrieMap node structure until the first time a
145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//     search is performed.  put() simply saves the parameters in case we do
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//     eventually need to build it.
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::put(const UnicodeString &key, void *value, ZNStringPool &sp, UErrorCode &status) {
150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *s = sp.get(key, status);
151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    put(s, value, status);
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// This method is for designed for a persistent key, such as string key stored in
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// resource bundle.
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::put(const UChar *key, void *value, UErrorCode &status) {
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fIsEmpty = FALSE;
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLazyContents == NULL) {
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLazyContents = new UVector(status);
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (fLazyContents == NULL) {
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
168103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    U_ASSERT(fLazyContents != NULL);
169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar *s = const_cast<UChar *>(key);
170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLazyContents->addElement(s, status);
171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLazyContents->addElement(value, status);
172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::putImpl(const UnicodeString &key, void *value, UErrorCode &status) {
176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodes == NULL) {
177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodesCapacity = 512;
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes = (CharacterNode *)uprv_malloc(fNodesCapacity * sizeof(CharacterNode));
179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes[0].clear();  // Init root node.
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodesCount = 1;
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString foldedKey;
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *keyBuffer;
185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t keyLength;
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fIgnoreCase) {
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Ok to use fastCopyFrom() because we discard the copy when we return.
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        foldedKey.fastCopyFrom(key).foldCase();
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyBuffer = foldedKey.getBuffer();
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyLength = foldedKey.length();
191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyBuffer = key.getBuffer();
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        keyLength = key.length();
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CharacterNode *node = fNodes;
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t index;
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (index = 0; index < keyLength; ++index) {
199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        node = addChildNode(node, keyBuffer[index], status);
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->addValue(value, fValueDeleter, status);
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::growNodes() {
206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodesCapacity == 0xffff) {
207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;  // We use 16-bit node indexes.
208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t newCapacity = fNodesCapacity + 1000;
210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (newCapacity > 0xffff) {
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        newCapacity = 0xffff;
212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CharacterNode *newNodes = (CharacterNode *)uprv_malloc(newCapacity * sizeof(CharacterNode));
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (newNodes == NULL) {
215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memcpy(newNodes, fNodes, fNodesCount * sizeof(CharacterNode));
218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(fNodes);
219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fNodes = newNodes;
220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fNodesCapacity = newCapacity;
221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCharacterNode*
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::addChildNode(CharacterNode *parent, UChar c, UErrorCode &status) {
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Linear search of the sorted list of children.
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint16_t prevIndex = 0;
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint16_t nodeIndex = parent->fFirstChild;
232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (nodeIndex > 0) {
233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        CharacterNode *current = fNodes + nodeIndex;
234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar childCharacter = current->fCharacter;
235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (childCharacter == c) {
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return current;
237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (childCharacter > c) {
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        prevIndex = nodeIndex;
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nodeIndex = current->fNextSibling;
242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Ensure capacity. Grow fNodes[] if needed.
245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodesCount == fNodesCapacity) {
246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t parentIndex = (int32_t)(parent - fNodes);
247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!growNodes()) {
248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parent = fNodes + parentIndex;
252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Insert a new child node with c in sorted order.
255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    CharacterNode *node = fNodes + fNodesCount;
256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->clear();
257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->fCharacter = c;
258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    node->fNextSibling = nodeIndex;
259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (prevIndex == 0) {
260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        parent->fFirstChild = (uint16_t)fNodesCount;
261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNodes[prevIndex].fNextSibling = (uint16_t)fNodesCount;
263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ++fNodesCount;
265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return node;
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoCharacterNode*
269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::getChildNode(CharacterNode *parent, UChar c) const {
270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Linear search of the sorted list of children.
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint16_t nodeIndex = parent->fFirstChild;
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (nodeIndex > 0) {
273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        CharacterNode *current = fNodes + nodeIndex;
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar childCharacter = current->fCharacter;
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (childCharacter == c) {
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return current;
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (childCharacter > c) {
278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nodeIndex = current->fNextSibling;
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Mutex for protecting the lazy creation of the Trie node structure on the first call to search().
28654dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex TextTrieMutex = U_MUTEX_INITIALIZER;
287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// buildTrie() - The Trie node structure is needed.  Create it from the data that was
289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//               saved at the time the ZoneStringFormatter was created.  The Trie is only
290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//               needed for parsing operations, which are less common than formatting,
291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//               and the Trie is big, which is why its creation is deferred until first use.
292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid TextTrieMap::buildTrie(UErrorCode &status) {
293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_lock(&TextTrieMutex);
294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLazyContents != NULL) {
295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i=0; i<fLazyContents->size(); i+=2) {
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UChar *key = (UChar *)fLazyContents->elementAt(i);
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            void  *val = fLazyContents->elementAt(i+1);
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString keyString(TRUE, key, -1);  // Aliasing UnicodeString constructor.
299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            putImpl(keyString, val, status);
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLazyContents;
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLazyContents = NULL;
303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    umtx_unlock(&TextTrieMutex);
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::search(const UnicodeString &text, int32_t start,
309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool trieNeedsInitialization = FALSE;
311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UMTX_CHECK(&TextTrieMutex, fLazyContents != NULL, trieNeedsInitialization);
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (trieNeedsInitialization) {
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        nonConstThis->buildTrie(status);
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNodes == NULL) {
317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    search(fNodes, text, start, start, handler, status);
320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTextTrieMap::search(CharacterNode *node, const UnicodeString &text, int32_t start,
324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                  int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node->hasValues()) {
329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!handler->handleMatch(index - start, node, status)) {
330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar32 c = text.char32At(index);
337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fIgnoreCase) {
338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // size of character may grow after fold operation
339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString tmp(c);
340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tmp.foldCase();
341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t tmpidx = 0;
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while (tmpidx < tmp.length()) {
343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            c = tmp.char32At(tmpidx);
344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            node = getChildNode(node, c);
345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (node == NULL) {
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            tmpidx = tmp.moveIndex32(tmpidx, 1);
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        node = getChildNode(node, c);
352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node != NULL) {
354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        search(node, text, start, index+1, handler, status);
355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ZNStringPool class implementation
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t POOL_CHUNK_SIZE = 2000;
362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct ZNStringPoolChunk: public UMemory {
363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNStringPoolChunk    *fNext;                       // Ptr to next pool chunk
364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t               fLimit;                       // Index to start of unused area at end of fStrings
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar                 fStrings[POOL_CHUNK_SIZE];    //  Strings array
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNStringPoolChunk();
367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNStringPoolChunk::ZNStringPoolChunk() {
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fNext = NULL;
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLimit = 0;
372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNStringPool::ZNStringPool(UErrorCode &status) {
375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fChunks = NULL;
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fHash   = NULL;
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fChunks = new ZNStringPoolChunk;
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fChunks == NULL) {
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fHash   = uhash_open(uhash_hashUChars      /* keyHash */,
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         uhash_compareUChars   /* keyComp */,
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         uhash_compareUChars   /* valueComp */,
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                         &status);
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNStringPool::~ZNStringPool() {
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fHash != NULL) {
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_close(fHash);
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fHash = NULL;
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (fChunks != NULL) {
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZNStringPoolChunk *nextChunk = fChunks->fNext;
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fChunks;
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fChunks = nextChunk;
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar EmptyString = 0;
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar *ZNStringPool::get(const UChar *s, UErrorCode &status) {
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *pooledString;
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return &EmptyString;
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    pooledString = static_cast<UChar *>(uhash_get(fHash, s));
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (pooledString != NULL) {
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return pooledString;
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t length = u_strlen(s);
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t remainingLength = POOL_CHUNK_SIZE - fChunks->fLimit;
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (remainingLength <= length) {
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(length < POOL_CHUNK_SIZE);
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (length >= POOL_CHUNK_SIZE) {
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_INTERNAL_PROGRAM_ERROR;
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return &EmptyString;
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZNStringPoolChunk *oldChunk = fChunks;
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fChunks = new ZNStringPoolChunk;
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (fChunks == NULL) {
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return &EmptyString;
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fChunks->fNext = oldChunk;
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar *destString = &fChunks->fStrings[fChunks->fLimit];
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_strcpy(destString, s);
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fChunks->fLimit += (length + 1);
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_put(fHash, destString, destString, &status);
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return destString;
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//  ZNStringPool::adopt()    Put a string into the hash, but do not copy the string data
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//                           into the pool's storage.  Used for strings from resource bundles,
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//                           which will perisist for the life of the zone string formatter, and
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//                           therefore can be used directly without copying.
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar *ZNStringPool::adopt(const UChar * s, UErrorCode &status) {
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *pooledString;
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return &EmptyString;
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (s != NULL) {
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pooledString = static_cast<UChar *>(uhash_get(fHash, s));
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (pooledString == NULL) {
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UChar *ncs = const_cast<UChar *>(s);
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fHash, ncs, ncs, &status);
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return s;
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar *ZNStringPool::get(const UnicodeString &s, UErrorCode &status) {
468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString &nonConstStr = const_cast<UnicodeString &>(s);
469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return this->get(nonConstStr.getTerminatedBuffer(), status);
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * freeze().   Close the hash table that maps to the pooled strings.
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *             After freezing, the pool can not be searched or added to,
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *             but all existing references to pooled strings remain valid.
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *             The main purpose is to recover the storage used for the hash.
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid ZNStringPool::freeze() {
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(fHash);
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fHash = NULL;
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ZNames - names common for time zone and meta zone
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass ZNames : public UMemory {
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~ZNames();
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static ZNames* createInstance(UResourceBundle* rb, const char* key);
4938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    virtual const UChar* getName(UTimeZoneNameType type);
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprotected:
496103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    ZNames(const UChar** names);
497103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    static const UChar** loadData(UResourceBundle* rb, const char* key);
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar** fNames;
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
503103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZNames::ZNames(const UChar** names)
504103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius: fNames(names) {
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames::~ZNames() {
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNames != NULL) {
509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uprv_free(fNames);
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames*
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames::createInstance(UResourceBundle* rb, const char* key) {
515103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    const UChar** names = loadData(rb, key);
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (names == NULL) {
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // No names data available
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
520103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return new ZNames(names);
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames::getName(UTimeZoneNameType type) {
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fNames == NULL) {
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *name = NULL;
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    switch(type) {
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_LONG_GENERIC:
531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[0];
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_LONG_STANDARD:
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[1];
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_LONG_DAYLIGHT:
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[2];
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_SHORT_GENERIC:
540103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        name = fNames[3];
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_SHORT_STANDARD:
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[4];
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case UTZNM_SHORT_DAYLIGHT:
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = fNames[5];
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        break;
5488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    case UTZNM_EXEMPLAR_LOCATION:   // implemeted by subclass
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    default:
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name = NULL;
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar**
556103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZNames::loadData(UResourceBundle* rb, const char* key) {
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (rb == NULL || key == NULL || *key == 0) {
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar **names = NULL;
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle* rbTable = NULL;
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    rbTable = ures_getByKeyWithFallback(rb, key, rbTable, &status);
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        names = (const UChar **)uprv_malloc(sizeof(const UChar*) * KEYS_SIZE);
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (names != NULL) {
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UBool isEmpty = TRUE;
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int32_t i = 0; i < KEYS_SIZE; i++) {
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                status = U_ZERO_ERROR;
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t len = 0;
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const UChar *value = ures_getStringByKeyWithFallback(rbTable, KEYS[i], &len, &status);
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (U_FAILURE(status) || len == 0) {
575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    names[i] = NULL;
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    names[i] = value;
578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    isEmpty = FALSE;
579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (isEmpty) {
582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // No need to keep the names array
583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_free(names);
584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                names = NULL;
585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
588b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(rbTable);
589b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return names;
590b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
591b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
592b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
593b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TZNames - names for a time zone
594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass TZNames : public ZNames {
596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~TZNames();
598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
5998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    static TZNames* createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID);
6008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    virtual const UChar* getName(UTimeZoneNameType type);
601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
6038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    TZNames(const UChar** names);
604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* fLocationName;
6058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UChar* fLocationNameOwned;
606b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
6088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTZNames::TZNames(const UChar** names)
6098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius: ZNames(names), fLocationName(NULL), fLocationNameOwned(NULL) {
610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTZNames::~TZNames() {
6138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (fLocationNameOwned) {
6148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        uprv_free(fLocationNameOwned);
6158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
6198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTZNames::getName(UTimeZoneNameType type) {
6208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (type == UTZNM_EXEMPLAR_LOCATION) {
6218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return fLocationName;
6228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
6238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return ZNames::getName(type);
624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
626b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTZNames*
6278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTZNames::createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID) {
628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (rb == NULL || key == NULL || *key == 0) {
629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
6318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const UChar** names = loadData(rb, key);
6338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const UChar* locationName = NULL;
6348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UChar* locationNameOwned = NULL;
6358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
6378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int32_t len = 0;
6388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UResourceBundle* table = ures_getByKeyWithFallback(rb, key, NULL, &status);
6408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    locationName = ures_getStringByKeyWithFallback(table, gEcTag, &len, &status);
6418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // ignore missing resource here
6428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    status = U_ZERO_ERROR;
6438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    ures_close(table);
6458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (locationName == NULL) {
6478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        UnicodeString tmpName;
6488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        int32_t tmpNameLen = 0;
6498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        TimeZoneNamesImpl::getDefaultExemplarLocationName(tzID, tmpName);
6508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tmpNameLen = tmpName.length();
6518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (tmpNameLen > 0) {
6538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            locationNameOwned = (UChar*) uprv_malloc(sizeof(UChar) * (tmpNameLen + 1));
6548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (locationNameOwned) {
6558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tmpName.extract(locationNameOwned, tmpNameLen + 1, status);
6568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                locationName = locationNameOwned;
6578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
658b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
6598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
660b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
6618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    TZNames* tznames = NULL;
6628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (locationName != NULL || names != NULL) {
6638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames = new TZNames(names);
6648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (tznames == NULL) {
6658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (locationNameOwned) {
6668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                uprv_free(locationNameOwned);
6678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
6698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames->fLocationName = locationName;
6708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames->fLocationNameOwned = locationNameOwned;
671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
6728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tznames;
674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
676b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
677b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// The meta zone ID enumeration class
678b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
679b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass MetaZoneIDsEnumeration : public StringEnumeration {
680b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
681b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration();
682b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration(const UVector& mzIDs);
683b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration(UVector* mzIDs);
684b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~MetaZoneIDsEnumeration();
685b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static UClassID U_EXPORT2 getStaticClassID(void);
686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual UClassID getDynamicClassID(void) const;
687b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual const UnicodeString* snext(UErrorCode& status);
688b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual void reset(UErrorCode& status);
689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual int32_t count(UErrorCode& status) const;
690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
691b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fLen;
692b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fPos;
693b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UVector* fMetaZoneIDs;
694b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector *fLocalVector;
695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
696b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
697b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUOBJECT_DEFINE_RTTI_IMPLEMENTATION(MetaZoneIDsEnumeration)
698b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
699b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::MetaZoneIDsEnumeration()
700b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLen(0), fPos(0), fMetaZoneIDs(NULL), fLocalVector(NULL) {
701b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
702b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::MetaZoneIDsEnumeration(const UVector& mzIDs)
704b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fPos(0), fMetaZoneIDs(&mzIDs), fLocalVector(NULL) {
705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fLen = fMetaZoneIDs->size();
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::MetaZoneIDsEnumeration(UVector *mzIDs)
709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLen(0), fPos(0), fMetaZoneIDs(mzIDs), fLocalVector(mzIDs) {
710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fMetaZoneIDs) {
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLen = fMetaZoneIDs->size();
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UnicodeString*
716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::snext(UErrorCode& status) {
717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status) && fMetaZoneIDs != NULL && fPos < fLen) {
718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        unistr.setTo((const UChar*)fMetaZoneIDs->elementAt(fPos++), -1);
719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return &unistr;
720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::reset(UErrorCode& /*status*/) {
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fPos = 0;
727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::count(UErrorCode& /*status*/) const {
731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fLen;
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMetaZoneIDsEnumeration::~MetaZoneIDsEnumeration() {
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fLocalVector) {
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fLocalVector;
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * ZNameInfo stores zone name information in the trie
743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct ZNameInfo {
745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UTimeZoneNameType   type;
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar*        tzID;
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar*        mzID;
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZNameInfo;
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * ZMatchInfo stores zone name match information used by find method
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehotypedef struct ZMatchInfo {
754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const ZNameInfo*    znameInfo;
755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t             matchLength;
756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} ZMatchInfo;
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ZNameSearchHandler
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass ZNameSearchHandler : public TextTrieMapSearchResultHandler {
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNameSearchHandler(uint32_t types);
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~ZNameSearchHandler();
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
769103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uint32_t fTypes;
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t fMaxMatchLen;
774103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* fResults;
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::ZNameSearchHandler(uint32_t types)
778103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius: fTypes(types), fMaxMatchLen(0), fResults(NULL) {
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::~ZNameSearchHandler() {
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fResults != NULL) {
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete fResults;
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (node->hasValues()) {
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t valuesCount = node->countValues();
794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < valuesCount; i++) {
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ZNameInfo *nameinfo = (ZNameInfo *)node->getValue(i);
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (nameinfo == NULL) {
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if ((nameinfo->type & fTypes) != 0) {
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // matches a requested type
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (fResults == NULL) {
802103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    fResults = new TimeZoneNames::MatchInfoCollection();
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (fResults == NULL) {
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        status = U_MEMORY_ALLOCATION_ERROR;
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (U_SUCCESS(status)) {
808103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    U_ASSERT(fResults != NULL);
809103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    if (nameinfo->tzID) {
810103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        fResults->addZone(nameinfo->type, matchLength, UnicodeString(nameinfo->tzID, -1), status);
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    } else {
812103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        U_ASSERT(nameinfo->mzID);
813103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        fResults->addMetaZone(nameinfo->type, matchLength, UnicodeString(nameinfo->mzID, -1), status);
814103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    }
815103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                    if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
816103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        fMaxMatchLen = matchLength;
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TRUE;
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
825103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames::MatchInfoCollection*
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNameSearchHandler::getMatches(int32_t& maxMatchLen) {
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // give the ownership to the caller
828103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* results = fResults;
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    maxMatchLen = fMaxMatchLen;
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // reset
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fResults = NULL;
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fMaxMatchLen = 0;
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return results;
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneNamesImpl
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// TimeZoneNames implementation class. This is the main
841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// part of this module.
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------------------
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for ZNames
847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteZNames(void *obj) {
850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (obj != EMPTY) {
851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete (ZNames *)obj;
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for TZNames
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteTZNames(void *obj) {
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (obj != EMPTY) {
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete (TZNames *)obj;
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/**
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Deleter for ZNameInfo
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void U_CALLCONV
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehodeleteZNameInfo(void *obj) {
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(obj);
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
87454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gLock = U_MUTEX_INITIALIZER;
87554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::TimeZoneNamesImpl(const Locale& locale, UErrorCode& status)
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho: fLocale(locale),
878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fZoneStrings(NULL),
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fTZNamesMap(NULL),
880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fMZNamesMap(NULL),
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fNamesTrieFullyLoaded(FALSE),
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fNamesTrie(TRUE, deleteZNameInfo) {
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    initialize(locale, status);
884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::initialize(const Locale& locale, UErrorCode& status) {
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Load zoneStrings bundle
893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode tmpsts = U_ZERO_ERROR;   // OK with fallback warning..
894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fZoneStrings = ures_open(U_ICUDATA_ZONE, locale.getName(), &tmpsts);
895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fZoneStrings = ures_getByKeyWithFallback(fZoneStrings, gZoneStrings, fZoneStrings, &tmpsts);
896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(tmpsts)) {
897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = tmpsts;
898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Initialize hashtables holding time zone/meta zone names
903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fMZNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    fTZNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cleanup();
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
908b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
910b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_setValueDeleter(fMZNamesMap, deleteZNames);
911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_setValueDeleter(fTZNamesMap, deleteTZNames);
912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // no key deleters for name maps
913b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
914b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // preload zone strings for the default zone
915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZone *tz = TimeZone::createDefault();
916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz);
917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID != NULL) {
918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        loadStrings(UnicodeString(tzID));
919b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
920b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete tz;
921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return;
923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock,
927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * except initializer.
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::loadStrings(const UnicodeString& tzCanonicalID) {
931b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    loadTimeZoneNames(tzCanonicalID);
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringEnumeration *mzIDs = getAvailableMetaZoneIDs(tzCanonicalID, status);
935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status) && mzIDs != NULL) {
936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UnicodeString *mzID;
937b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while ((mzID = mzIDs->snext(status))) {
938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            loadMetaZoneNames(*mzID);
942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete mzIDs;
944b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::~TimeZoneNamesImpl() {
948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cleanup();
949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::cleanup() {
953b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fZoneStrings != NULL) {
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ures_close(fZoneStrings);
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fZoneStrings = NULL;
956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fMZNamesMap != NULL) {
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_close(fMZNamesMap);
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fMZNamesMap = NULL;
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (fTZNamesMap != NULL) {
962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_close(fTZNamesMap);
963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fTZNamesMap = NULL;
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
967103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUBool
968103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNamesImpl::operator==(const TimeZoneNames& other) const {
969103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (this == &other) {
970103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return TRUE;
971103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
972103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    // No implementation for now
973103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return FALSE;
974103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
975103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
976103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames*
977103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNamesImpl::clone() const {
978103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UErrorCode status = U_ZERO_ERROR;
979103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return new TimeZoneNamesImpl(fLocale, status);
980103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
981103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
982b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration*
983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UVector* mzIDs = ZoneMeta::getAvailableMetazoneIDs();
988b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzIDs == NULL) {
989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return new MetaZoneIDsEnumeration();
990b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
991b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return new MetaZoneIDsEnumeration(*mzIDs);
992b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
994b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration*
995b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
997b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UVector* mappings = ZoneMeta::getMetazoneMappings(tzID);
1000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mappings == NULL) {
1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return new MetaZoneIDsEnumeration();
1002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MetaZoneIDsEnumeration *senum = NULL;
1005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UVector* mzIDs = new UVector(NULL, uhash_compareUChars, status);
1006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzIDs == NULL) {
1007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
1008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
1010103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U_ASSERT(mzIDs != NULL);
1011b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; U_SUCCESS(status) && i < mappings->size(); i++) {
1012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            OlsonToMetaMappingEntry *map = (OlsonToMetaMappingEntry *)mappings->elementAt(i);
1014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UChar *mzID = map->mzid;
1015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!mzIDs->contains((void *)mzID)) {
1016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                mzIDs->addElement((void *)mzID, status);
1017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status)) {
1020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            senum = new MetaZoneIDsEnumeration(mzIDs);
1021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            delete mzIDs;
1023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return senum;
1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZoneMeta::getMetazoneID(tzID, date, mzID);
1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return mzID;
1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
1036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZoneMeta::getZoneIdByMetazone(mzID, UnicodeString(region, -1, US_INV), tzID);
1037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tzID;
1038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1039b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
1042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          UTimeZoneNameType type,
1043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                          UnicodeString& name) const {
1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();  // cleanup result.
1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzID.isEmpty()) {
1046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
1047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNames *znames = NULL;
1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
105254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        znames = nonConstThis->loadMetaZoneNames(mzID);
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
105654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (znames != NULL) {
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* s = znames->getName(type);
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (s != NULL) {
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            name.setTo(TRUE, s, -1);
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const {
1069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    name.setToBogus();  // cleanup result.
1070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID.isEmpty()) {
1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return name;
1072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1074b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZNames *tznames = NULL;
1075b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
107754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1078b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1079b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tznames = nonConstThis->loadTimeZoneNames(tzID);
1080b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
108154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1082b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tznames != NULL) {
1084b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar *s = tznames->getName(type);
1085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (s != NULL) {
1086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            name.setTo(TRUE, s, -1);
1087b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return name;
1090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1092b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString&
1093b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const {
10948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    name.setToBogus();  // cleanup result.
1095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar* locName = NULL;
1096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZNames *tznames = NULL;
1097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
109954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tznames = nonConstThis->loadTimeZoneNames(tzID);
1102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
110354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tznames != NULL) {
11068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        locName = tznames->getName(UTZNM_EXEMPLAR_LOCATION);
1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (locName != NULL) {
1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        name.setTo(TRUE, locName, -1);
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
11128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return name;
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Merge the MZ_PREFIX and mzId
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic void mergeTimeZoneKey(const UnicodeString& mzID, char* result) {
1118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzID.isEmpty()) {
1119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result[0] = '\0';
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    char mzIdChar[ZID_KEY_MAX + 1];
1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t keyLen;
1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prefixLen = uprv_strlen(gMZPrefix);
1126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    keyLen = mzID.extract(0, mzID.length(), mzIdChar, ZID_KEY_MAX + 1, US_INV);
1127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memcpy((void *)result, (void *)gMZPrefix, prefixLen);
1128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_memcpy((void *)(result + prefixLen), (void *)mzIdChar, keyLen);
1129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    result[keyLen + prefixLen] = '\0';
1130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
1133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock
1134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
1135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZNames*
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID) {
1137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (mzID.length() > (ZID_KEY_MAX - MZ_PREFIX_LEN)) {
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNames *znames = NULL;
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar mzIDKey[ZID_KEY_MAX + 1];
1145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
1146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
1147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    mzIDKey[mzID.length()] = 0;
1148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void *cacheVal = uhash_get(fMZNamesMap, mzIDKey);
1150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cacheVal == NULL) {
1151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char key[ZID_KEY_MAX + 1];
1152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        mergeTimeZoneKey(mzID, key);
1153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        znames = ZNames::createInstance(fZoneStrings, key);
1154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (znames == NULL) {
1156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = (void *)EMPTY;
1157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = znames;
1159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Use the persistent ID as the resource key, so we can
1161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // avoid duplications.
1162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
1163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (newKey != NULL) {
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fMZNamesMap, (void *)newKey, cacheVal, &status);
1165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
1166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (znames != NULL) {
1167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete znames;
1168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (znames != NULL) {
1170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // put the name info into the trie
1171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) {
1172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    const UChar* name = znames->getName(ALL_NAME_TYPES[i]);
1173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (name != NULL) {
1174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZNameInfo));
1175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (nameinfo != NULL) {
1176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->type = ALL_NAME_TYPES[i];
1177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->tzID = NULL;
1178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->mzID = newKey;
1179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            fNamesTrie.put(name, nameinfo, status);
1180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
1181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Should never happen with a valid input
1187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (znames != NULL) {
1188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // It's not possible that we get a valid ZNames with unknown ID.
1189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // But just in case..
1190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete znames;
1191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                znames = NULL;
1192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (cacheVal != EMPTY) {
1195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        znames = (ZNames *)cacheVal;
1196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return znames;
1199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho/*
1202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * This method updates the cache and must be called with a lock
1203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho */
1204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTZNames*
1205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) {
1206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (tzID.length() > ZID_KEY_MAX) {
1207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZNames *tznames = NULL;
1211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UChar tzIDKey[ZID_KEY_MAX + 1];
1214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t tzIDKeyLen = tzID.extract(tzIDKey, ZID_KEY_MAX + 1, status);
1215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
1216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    tzIDKey[tzIDKeyLen] = 0;
1217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void *cacheVal = uhash_get(fTZNamesMap, tzIDKey);
1219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cacheVal == NULL) {
1220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        char key[ZID_KEY_MAX + 1];
1221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UErrorCode status = U_ZERO_ERROR;
1222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Replace "/" with ":".
1223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString uKey(tzID);
1224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t i = 0; i < uKey.length(); i++) {
1225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (uKey.charAt(i) == (UChar)0x2F) {
1226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uKey.setCharAt(i, (UChar)0x3A);
1227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uKey.extract(0, uKey.length(), key, sizeof(key), US_INV);
12308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        tznames = TZNames::createInstance(fZoneStrings, key, tzID);
1231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (tznames == NULL) {
1233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = (void *)EMPTY;
1234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cacheVal = tznames;
1236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Use the persistent ID as the resource key, so we can
1238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // avoid duplications.
1239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* newKey = ZoneMeta::findTimeZoneID(tzID);
1240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (newKey != NULL) {
1241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_put(fTZNamesMap, (void *)newKey, cacheVal, &status);
1242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
1243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (tznames != NULL) {
1244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete tznames;
1245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (tznames != NULL) {
1247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // put the name info into the trie
1248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                for (int32_t i = 0; ALL_NAME_TYPES[i] != UTZNM_UNKNOWN; i++) {
1249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    const UChar* name = tznames->getName(ALL_NAME_TYPES[i]);
1250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (name != NULL) {
1251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ZNameInfo *nameinfo = (ZNameInfo *)uprv_malloc(sizeof(ZNameInfo));
1252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        if (nameinfo != NULL) {
1253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->type = ALL_NAME_TYPES[i];
1254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->tzID = newKey;
1255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            nameinfo->mzID = NULL;
1256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            fNamesTrie.put(name, nameinfo, status);
1257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        }
1258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Should never happen with a valid input
1263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tznames != NULL) {
1264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // It's not possible that we get a valid TZNames with unknown ID.
1265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // But just in case..
1266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete tznames;
1267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                tznames = NULL;
1268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (cacheVal != EMPTY) {
1271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        tznames = (TZNames *)cacheVal;
1272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return tznames;
1275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1277103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZoneNames::MatchInfoCollection*
1278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
1279b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ZNameSearchHandler handler(types);
1280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
1282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
128354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1284b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
1286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
128754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t maxLen = 0;
1294103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    TimeZoneNames::MatchInfoCollection* matches = handler.getMatches(maxLen);
1295103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (matches != NULL && ((maxLen == (text.length() - start)) || fNamesTrieFullyLoaded)) {
1296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // perfect match
1297103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return matches;
1298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1300103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    delete matches;
1301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // All names are not yet loaded into the trie
130354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!fNamesTrieFullyLoaded) {
1306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UnicodeString *id;
1307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // load strings for all zones
1309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
1310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                while ((id = tzIDs->snext(status))) {
1312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(status)) {
1313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
1314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
1315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // loadStrings also load related metazone strings
1316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    nonConstThis->loadStrings(*id);
1317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
1318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tzIDs != NULL) {
1320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                delete tzIDs;
1321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_SUCCESS(status)) {
1323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                nonConstThis->fNamesTrieFullyLoaded = TRUE;
1324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
132754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
133354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_lock(&gLock);
1334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    {
1335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // now try it again
1336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
1337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
133854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    umtx_unlock(&gLock);
1339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1340103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return handler.getMatches(maxLen);
1341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
13438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar gEtcPrefix[]         = { 0x45, 0x74, 0x63, 0x2F }; // "Etc/"
13448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const int32_t gEtcPrefixLen      = 4;
13458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar gSystemVPrefix[]     = { 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x56, 0x2F }; // "SystemV/
13468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const int32_t gSystemVPrefixLen  = 8;
13478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar gRiyadh8[]           = { 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, 0x38 }; // "Riyadh8"
13488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const int32_t gRiyadh8Len       = 7;
13498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
13508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusUnicodeString& U_EXPORT2
13518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTimeZoneNamesImpl::getDefaultExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) {
13528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (tzID.isEmpty() || tzID.startsWith(gEtcPrefix, gEtcPrefixLen)
13538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        || tzID.startsWith(gSystemVPrefix, gSystemVPrefixLen) || tzID.indexOf(gRiyadh8, gRiyadh8Len, 0) > 0) {
13548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.setToBogus();
13558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return name;
13568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
13578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
13588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int32_t sep = tzID.lastIndexOf((UChar)0x2F /* '/' */);
13598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (sep > 0 && sep + 1 < tzID.length()) {
13608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.setTo(tzID, sep + 1);
13618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.findAndReplace(UnicodeString((UChar)0x5f /* _ */),
13628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            UnicodeString((UChar)0x20 /* space */));
13638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    } else {
13648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        name.setToBogus();
13658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
13668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return name;
13678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
13688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
1369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_NAMESPACE_END
1370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif /* #if !UCONFIG_NO_FORMATTING */
1373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//eof
1375