1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*******************************************************************************
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 2007-2010, International Business Machines Corporation and    *
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* others. All Rights Reserved.                                                *
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*******************************************************************************
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h"
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_FORMATTING
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "zstrfmt.h"
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ustring.h"
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/putil.h"
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/msgfmt.h"
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/basictz.h"
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/simpletz.h"
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/rbtz.h"
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/vtzone.h"
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uvector.h"
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cstring.h"
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h"
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uresimp.h"
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "zonemeta.h"
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "olsontz.h"
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "umutex.h"
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ucln_in.h"
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uassert.h"
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ureslocs.h"
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * global ZoneStringFormatCache stuffs
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UMTX gZSFCacheLock = NULL;
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static U_NAMESPACE_QUALIFIER ZSFCache *gZoneStringFormatCache = NULL;
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_BEGIN
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ZoneStringFormatCache cleanup callback func
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UBool U_CALLCONV zoneStringFormat_cleanup(void)
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_destroy(&gZSFCacheLock);
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (gZoneStringFormatCache != NULL) {
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete gZoneStringFormatCache;
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        gZoneStringFormatCache = NULL;
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    gZoneStringFormatCache = NULL;
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return TRUE;
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Deleter for ZoneStringInfo
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)deleteZoneStringInfo(void *obj) {
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete (U_NAMESPACE_QUALIFIER ZoneStringInfo*)obj;
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Deleter for ZoneStrings
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void U_CALLCONV
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)deleteZoneStrings(void *obj) {
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete (U_NAMESPACE_QUALIFIER ZoneStrings*)obj;
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CDECL_END
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_BEGIN
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define ZID_KEY_MAX 128
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gCountriesTag[]       = "Countries";
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gZoneStringsTag[]     = "zoneStrings";
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gShortGenericTag[]    = "sg";
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gShortStandardTag[]   = "ss";
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gShortDaylightTag[]   = "sd";
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gLongGenericTag[]     = "lg";
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gLongStandardTag[]    = "ls";
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gLongDaylightTag[]    = "ld";
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gExemplarCityTag[]    = "ec";
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gCommonlyUsedTag[]    = "cu";
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gFallbackFormatTag[]  = "fallbackFormat";
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gRegionFormatTag[]    = "regionFormat";
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MZID_PREFIX_LEN 5
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const char gMetazoneIdPrefix[]   = "meta:";
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MAX_METAZONES_PER_ZONE 10
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar gDefFallbackPattern[]    = {0x7B, 0x31, 0x7D, 0x20, 0x28, 0x7B, 0x30, 0x7D, 0x29, 0x00}; // "{1} ({0})"
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar gDefRegionPattern[]      = {0x7B, 0x30, 0x7D, 0x00}; // "{0}"
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar gCommonlyUsedTrue[]      = {0x31, 0x00}; // "1"
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const double kDstCheckRange      = (double)184*U_MILLIS_PER_DAY;
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)getTimeZoneTranslationTypeIndex(TimeZoneTranslationType type) {
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t typeIdx = 0;
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    switch (type) {
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case LOCATION:
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_LOCATION;
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case GENERIC_LONG:
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_LONG_GENERIC;
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case GENERIC_SHORT:
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_SHORT_GENERIC;
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case STANDARD_LONG:
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_LONG_STANDARD;
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case STANDARD_SHORT:
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_SHORT_STANDARD;
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case DAYLIGHT_LONG:
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_LONG_DAYLIGHT;
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case DAYLIGHT_SHORT:
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typeIdx = ZSIDX_SHORT_DAYLIGHT;
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return typeIdx;
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)getTimeZoneTranslationType(TimeZoneTranslationTypeIndex typeIdx) {
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t type = 0;
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    switch (typeIdx) {
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_LOCATION:
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = LOCATION;
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_LONG_GENERIC:
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = GENERIC_LONG;
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_SHORT_GENERIC:
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = GENERIC_SHORT;
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_LONG_STANDARD:
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = STANDARD_LONG;
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_SHORT_STANDARD:
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = STANDARD_SHORT;
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_LONG_DAYLIGHT:
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = DAYLIGHT_LONG;
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_COUNT:
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ZSIDX_SHORT_DAYLIGHT:
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            type = DAYLIGHT_SHORT;
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        default:
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return type;
158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DEFAULT_CHARACTERNODE_CAPACITY 1
161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ----------------------------------------------------------------------------
163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void CharacterNode::clear() {
164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_memset(this, 0, sizeof(*this));
165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void CharacterNode::deleteValues() {
168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fValues == NULL) {
169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Do nothing.
170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else if (!fHasValuesVector) {
171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        deleteZoneStringInfo(fValues);
172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete (UVector *)fValues;
174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CharacterNode::addValue(void *value, UErrorCode &status) {
179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        deleteZoneStringInfo(value);
181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fValues == NULL) {
184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fValues = value;
185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // At least one value already.
187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (!fHasValuesVector) {
188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // There is only one value so far, and not in a vector yet.
189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Create a vector and add the old value.
190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UVector *values = new UVector(deleteZoneStringInfo, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status);
191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (U_FAILURE(status)) {
192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                deleteZoneStringInfo(value);
193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return;
194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            values->addElement(fValues, status);
196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fValues = values;
197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fHasValuesVector = TRUE;
198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Add the new value.
200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ((UVector *)fValues)->addElement(value, status);
201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//----------------------------------------------------------------------------
205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Virtual destructor to avoid warning
206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMapSearchResultHandler::~TextTrieMapSearchResultHandler(){
207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ----------------------------------------------------------------------------
210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::TextTrieMap(UBool ignoreCase)
211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fIgnoreCase(ignoreCase), fNodes(NULL), fNodesCapacity(0), fNodesCount(0),
212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fLazyContents(NULL), fIsEmpty(TRUE) {
213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::~TextTrieMap() {
216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t index;
217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (index = 0; index < fNodesCount; ++index) {
218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fNodes[index].deleteValues();
219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(fNodes);
221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fLazyContents != NULL) {
222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t i=0; i<fLazyContents->size(); i+=2) {
223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ZoneStringInfo *zsinf = (ZoneStringInfo *)fLazyContents->elementAt(i+1);
224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete zsinf;
225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete fLazyContents;
227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t TextTrieMap::isEmpty() const {
231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Use a separate field for fIsEmpty because it will remain unchanged once the
232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //   Trie is built, while fNodes and fLazyContents change with the lazy init
233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //   of the nodes structure.  Trying to test the changing fields has
234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //   thread safety complications.
235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return fIsEmpty;
236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//  We defer actually building the TextTrieMap node structure until the first time a
240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//     search is performed.  put() simply saves the parameters in case we do
241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//     eventually need to build it.
242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::put(const UnicodeString &key, void *value, ZSFStringPool &sp, UErrorCode &status) {
245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fIsEmpty = FALSE;
246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fLazyContents == NULL) {
247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fLazyContents = new UVector(status);
248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (fLazyContents == NULL) {
249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_MEMORY_ALLOCATION_ERROR;
250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *s = const_cast<UChar *>(sp.get(key, status));
256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fLazyContents->addElement(s, status);
257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fLazyContents->addElement(value, status);
258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::putImpl(const UnicodeString &key, void *value, UErrorCode &status) {
263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fNodes == NULL) {
264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fNodesCapacity = 512;
265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fNodes = (CharacterNode *)uprv_malloc(fNodesCapacity * sizeof(CharacterNode));
266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fNodes[0].clear();  // Init root node.
267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fNodesCount = 1;
268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString foldedKey;
271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *keyBuffer;
272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t keyLength;
273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fIgnoreCase) {
274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Ok to use fastCopyFrom() because we discard the copy when we return.
275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        foldedKey.fastCopyFrom(key).foldCase();
276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        keyBuffer = foldedKey.getBuffer();
277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        keyLength = foldedKey.length();
278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        keyBuffer = key.getBuffer();
280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        keyLength = key.length();
281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    CharacterNode *node = fNodes;
284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t index;
285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (index = 0; index < keyLength; ++index) {
286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        node = addChildNode(node, keyBuffer[index], status);
287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    node->addValue(value, status);
289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool
292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::growNodes() {
293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fNodesCapacity == 0xffff) {
294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;  // We use 16-bit node indexes.
295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t newCapacity = fNodesCapacity + 1000;
297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (newCapacity > 0xffff) {
298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        newCapacity = 0xffff;
299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    CharacterNode *newNodes = (CharacterNode *)uprv_malloc(newCapacity * sizeof(CharacterNode));
301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (newNodes == NULL) {
302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;
303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_memcpy(newNodes, fNodes, fNodesCount * sizeof(CharacterNode));
305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(fNodes);
306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fNodes = newNodes;
307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fNodesCapacity = newCapacity;
308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return TRUE;
309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CharacterNode*
312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::addChildNode(CharacterNode *parent, UChar c, UErrorCode &status) {
313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Linear search of the sorted list of children.
317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uint16_t prevIndex = 0;
318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uint16_t nodeIndex = parent->fFirstChild;
319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (nodeIndex > 0) {
320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        CharacterNode *current = fNodes + nodeIndex;
321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UChar childCharacter = current->fCharacter;
322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (childCharacter == c) {
323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return current;
324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else if (childCharacter > c) {
325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        prevIndex = nodeIndex;
328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        nodeIndex = current->fNextSibling;
329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Ensure capacity. Grow fNodes[] if needed.
332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fNodesCount == fNodesCapacity) {
333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t parentIndex = (int32_t)(parent - fNodes);
334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (!growNodes()) {
335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_MEMORY_ALLOCATION_ERROR;
336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return NULL;
337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        parent = fNodes + parentIndex;
339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Insert a new child node with c in sorted order.
342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    CharacterNode *node = fNodes + fNodesCount;
343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    node->clear();
344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    node->fCharacter = c;
345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    node->fNextSibling = nodeIndex;
346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (prevIndex == 0) {
347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        parent->fFirstChild = (uint16_t)fNodesCount;
348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fNodes[prevIndex].fNextSibling = (uint16_t)fNodesCount;
350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ++fNodesCount;
352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return node;
353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)CharacterNode*
356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::getChildNode(CharacterNode *parent, UChar c) const {
357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Linear search of the sorted list of children.
358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uint16_t nodeIndex = parent->fFirstChild;
359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (nodeIndex > 0) {
360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        CharacterNode *current = fNodes + nodeIndex;
361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UChar childCharacter = current->fCharacter;
362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (childCharacter == c) {
363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return current;
364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else if (childCharacter > c) {
365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        nodeIndex = current->fNextSibling;
368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return NULL;
370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Mutex for protecting the lazy creation of the Trie node structure on the first call to search().
373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UMTX TextTrieMutex;
374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// buildTrie() - The Trie node structure is needed.  Create it from the data that was
376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//               saved at the time the ZoneStringFormatter was created.  The Trie is only
377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//               needed for parsing operations, which are less common than formatting,
378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//               and the Trie is big, which is why its creation is deferred until first use.
379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void TextTrieMap::buildTrie(UErrorCode &status) {
380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_lock(&TextTrieMutex);
381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fLazyContents != NULL) {
382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t i=0; i<fLazyContents->size(); i+=2) {
383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const UChar *key = (UChar *)fLazyContents->elementAt(i);
384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            void  *val = fLazyContents->elementAt(i+1);
385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UnicodeString keyString(TRUE, key, -1);  // Aliasing UnicodeString constructor.
386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            putImpl(keyString, val, status);
387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete fLazyContents;
389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fLazyContents = NULL;
390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_unlock(&TextTrieMutex);
392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::search(const UnicodeString &text, int32_t start,
397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool trieNeedsInitialization = FALSE;
399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UMTX_CHECK(&TextTrieMutex, fLazyContents != NULL, trieNeedsInitialization);
400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (trieNeedsInitialization) {
401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        nonConstThis->buildTrie(status);
403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fNodes == NULL) {
405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    search(fNodes, text, start, start, handler, status);
408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)TextTrieMap::search(CharacterNode *node, const UnicodeString &text, int32_t start,
412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                  int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (node->hasValues()) {
417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (!handler->handleMatch(index - start, node, status)) {
418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return;
419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return;
422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c = text.char32At(index);
425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fIgnoreCase) {
426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // size of character may grow after fold operation
427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString tmp(c);
428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        tmp.foldCase();
429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t tmpidx = 0;
430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while (tmpidx < tmp.length()) {
431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            c = tmp.char32At(tmpidx);
432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            node = getChildNode(node, c);
433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (node == NULL) {
434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            tmpidx = tmp.moveIndex32(tmpidx, 1);
437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        node = getChildNode(node, c);
440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (node != NULL) {
442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        search(node, text, start, index+1, handler, status);
443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ----------------------------------------------------------------------------
447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringInfo::ZoneStringInfo(const UnicodeString &id, const UnicodeString &str,
448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                               TimeZoneTranslationType type, ZSFStringPool &sp, UErrorCode &status)
449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fType(type) {
450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fId = sp.get(id, status);
451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fStr = sp.get(str, status);
452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringInfo::~ZoneStringInfo() {
455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ----------------------------------------------------------------------------
459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringSearchResultHandler::ZoneStringSearchResultHandler(UErrorCode &status)
460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fResults(status)
461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    clear();
463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringSearchResultHandler::~ZoneStringSearchResultHandler() {
466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    clear();
467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool
470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringSearchResultHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;
473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (node->hasValues()) {
475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t valuesCount = node->countValues();
476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t i = 0; i < valuesCount; i++) {
477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ZoneStringInfo *zsinfo = (ZoneStringInfo*)node->getValue(i);
478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (zsinfo == NULL) {
479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Update the results
482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UBool foundType = FALSE;
483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            for (int32_t j = 0; j < fResults.size(); j++) {
484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                ZoneStringInfo *tmp = (ZoneStringInfo*)fResults.elementAt(j);
485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (zsinfo->fType == tmp->fType) {
486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    int32_t lenidx = getTimeZoneTranslationTypeIndex(tmp->fType);
487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (matchLength > fMatchLen[lenidx]) {
488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // Same type, longer match
489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        fResults.setElementAt(zsinfo, j);
490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        fMatchLen[lenidx] = matchLength;
491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    foundType = TRUE;
493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (!foundType) {
497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // not found in the current list
498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                fResults.addElement(zsinfo, status);
499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                fMatchLen[getTimeZoneTranslationTypeIndex(zsinfo->fType)] = matchLength;
500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return TRUE;
504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)int32_t
507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringSearchResultHandler::countMatches(void) {
508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return fResults.size();
509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringSearchResultHandler::getMatch(int32_t index, int32_t &matchLength) {
513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZoneStringInfo *zsinfo = NULL;
514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (index < fResults.size()) {
515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        zsinfo = (ZoneStringInfo*)fResults.elementAt(index);
516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        matchLength = fMatchLen[getTimeZoneTranslationTypeIndex(zsinfo->fType)];
517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return zsinfo;
519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringSearchResultHandler::clear(void) {
523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fResults.removeAllElements();
524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (int32_t i = 0; i < (int32_t)(sizeof(fMatchLen)/sizeof(fMatchLen[0])); i++) {
525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fMatchLen[i] = 0;
526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Mutex for protecting the lazy load of a zone ID (or a full load) to ZoneStringFormat structures.
530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UMTX ZoneStringFormatMutex;
531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ----------------------------------------------------------------------------
534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::ZoneStringFormat(const UnicodeString* const* strings,
535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                   int32_t rowCount, int32_t columnCount, UErrorCode &status)
536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fLocale(""),
537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fTzidToStrings(NULL),
538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fMzidToStrings(NULL),
539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fZoneStringsTrie(TRUE),
540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fStringPool(status),
541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fZoneStringsArray(NULL),
542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fMetazoneItem(NULL),
543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fZoneItem(NULL),
544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fIsFullyLoaded(FALSE)
545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fLocale.setToBogus();
550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (strings == NULL || columnCount <= 0 || rowCount <= 0) {
551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = U_ILLEGAL_ARGUMENT_ERROR;
552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fTzidToStrings = uhash_open(uhash_hashUChars,     // key hash function
555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                uhash_compareUChars,  // key comparison function
556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                NULL,                 // Value comparison function
557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                &status);
558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fMzidToStrings = uhash_open(uhash_hashUChars,
559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                uhash_compareUChars,
560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                NULL,
561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                &status);
562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_setValueDeleter(fTzidToStrings, deleteZoneStrings);
564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_setValueDeleter(fMzidToStrings, deleteZoneStrings);
565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (int32_t row = 0; row < rowCount; row++) {
567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (strings[row][0].isEmpty()) {
568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            continue;
569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString *names = new UnicodeString[ZSIDX_COUNT];
571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t col = 1; col < columnCount; col++) {
572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (!strings[row][col].isEmpty()) {
573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                int32_t typeIdx = -1;
574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                switch (col) {
575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 1:
576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_LONG_STANDARD;
577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 2:
579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_SHORT_STANDARD;
580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 3:
582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_LONG_DAYLIGHT;
583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 4:
585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_SHORT_DAYLIGHT;
586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 5:
588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_LOCATION;
589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 6:
591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_LONG_GENERIC;
592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case 7:
594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        typeIdx = ZSIDX_SHORT_GENERIC;
595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (typeIdx != -1) {
598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    names[typeIdx].setTo(strings[row][col]);
599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // Put the name into the trie
601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    int32_t type = getTimeZoneTranslationType((TimeZoneTranslationTypeIndex)typeIdx);
602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    ZoneStringInfo *zsinf = new ZoneStringInfo(strings[row][0],
603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                               strings[row][col],
604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                               (TimeZoneTranslationType)type,
605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                               fStringPool,
606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                               status);
607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    fZoneStringsTrie.put(strings[row][col], zsinf, fStringPool, status);
608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (U_FAILURE(status)) {
609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        delete zsinf;
610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        goto error_cleanup;
611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Note:  ZoneStrings constructor adopts and delete the names array.
616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZoneStrings *zstrings = new ZoneStrings(names, ZSIDX_COUNT, TRUE, NULL, 0, 0,
617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                fStringPool, status);
618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UChar *utzid = const_cast<UChar *>(fStringPool.get(strings[row][0], status));
619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uhash_put(fTzidToStrings, utzid, zstrings, &status);
620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete zstrings;
622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto error_cleanup;
623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fStringPool.freeze();
626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	fIsFullyLoaded = TRUE;
627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)error_cleanup:
630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return;
631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::ZoneStringFormat(const Locale &locale, UErrorCode &status)
634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fLocale(locale),
635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fTzidToStrings(NULL),
636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fMzidToStrings(NULL),
637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fZoneStringsTrie(TRUE),
638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fStringPool(status),
639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fZoneStringsArray(NULL),
640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fMetazoneItem(NULL),
641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fZoneItem(NULL),
642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  fIsFullyLoaded(FALSE)
643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fTzidToStrings = uhash_open(uhash_hashUChars,     // key hash function
648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                uhash_compareUChars,  // key comparison function
649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                NULL,                 // Value comparison function
650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                &status);
651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fMzidToStrings = uhash_open(uhash_hashUChars,     // key hash function
652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                uhash_compareUChars,  // key comparison function
653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                NULL,                 // Value comparison function
654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                &status);
655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_setValueDeleter(fTzidToStrings, deleteZoneStrings);
656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_setValueDeleter(fMzidToStrings, deleteZoneStrings);
657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Load only a single zone
660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::loadZone(const UnicodeString &utzid, UErrorCode &status)
662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (fIsFullyLoaded) {
664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		return;
665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (U_FAILURE(status)) {
668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		return;
669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	umtx_lock(&ZoneStringFormatMutex);
672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (fZoneStringsArray == NULL) {
674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		fZoneStringsArray = ures_open(U_ICUDATA_ZONE, fLocale.getName(), &status);
675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		fZoneStringsArray = ures_getByKeyWithFallback(fZoneStringsArray, gZoneStringsTag, fZoneStringsArray, &status);
676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (U_FAILURE(status)) {
677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// If no locale bundles are available, zoneStrings will be null.
678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// We still want to go through the rest of zone strings initialization,
679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// because generic location format is generated from tzid for the case.
680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// The rest of code should work even zoneStrings is null.
681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			status = U_ZERO_ERROR;
682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			ures_close(fZoneStringsArray);
683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			fZoneStringsArray = NULL;
684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	// Skip non-canonical IDs
688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	UnicodeString canonicalID;
689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	TimeZone::getCanonicalID(utzid, canonicalID, status);
690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (U_FAILURE(status)) {
691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Ignore unknown ID - we should not get here, but just in case.
692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		//	status = U_ZERO_ERROR;
693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		umtx_unlock(&ZoneStringFormatMutex);
694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		return;
695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_SUCCESS(status)) {
698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (uhash_count(fTzidToStrings) > 0) {
699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			ZoneStrings *zstrings = (ZoneStrings*)uhash_get(fTzidToStrings, canonicalID.getTerminatedBuffer());
700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (zstrings != NULL) {
701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				umtx_unlock(&ZoneStringFormatMutex);
702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				return;	//	We already about this one
703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	addSingleZone(canonicalID, status);
708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	umtx_unlock(&ZoneStringFormatMutex);
710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// Load only a single zone
713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::addSingleZone(UnicodeString &utzid, UErrorCode &status)
715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (U_FAILURE(status)) {
717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		return;
718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (uhash_count(fTzidToStrings) > 0) {
721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		ZoneStrings *zstrings = (ZoneStrings*)uhash_get(fTzidToStrings, utzid.getTerminatedBuffer());
722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (zstrings != NULL) {
723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			return;	//	We already about this one
724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    MessageFormat *fallbackFmt = NULL;
728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    MessageFormat *regionFmt = NULL;
729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fallbackFmt = getFallbackFormat(fLocale, status);
731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto error_cleanup;
733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    regionFmt = getRegionFormat(fLocale, status);
735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        goto error_cleanup;
737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	{
741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		char zidkey[ZID_KEY_MAX+1];
742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		char tzid[ZID_KEY_MAX+1];
743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		utzid.extract(0, utzid.length(), zidkey, ZID_KEY_MAX, US_INV);
744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		utzid.extract(0, utzid.length(), tzid, ZID_KEY_MAX, US_INV);
745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		const UChar *zstrarray[ZSIDX_COUNT];
747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		const UChar *mzstrarray[ZSIDX_COUNT];
748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString mzPartialLoc[MAX_METAZONES_PER_ZONE][4];
749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Replace '/' with ':'
751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		char *pCity = NULL;
752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		char *p = zidkey;
753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		while (*p) {
754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (*p == '/') {
755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				*p = ':';
756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				pCity = p + 1;
757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			p++;
759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (fZoneStringsArray != NULL) {
762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			fZoneItem = ures_getByKeyWithFallback(fZoneStringsArray, zidkey, fZoneItem, &status);
763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (U_FAILURE(status)) {
764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// If failed to open the zone item, create only location string
765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				ures_close(fZoneItem);
766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				fZoneItem = NULL;
767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				status = U_ZERO_ERROR;
768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString region;
772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		getRegion(region);
773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		zstrarray[ZSIDX_LONG_STANDARD]  = getZoneStringFromBundle(fZoneItem, gLongStandardTag);
775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		zstrarray[ZSIDX_SHORT_STANDARD] = getZoneStringFromBundle(fZoneItem, gShortStandardTag);
776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		zstrarray[ZSIDX_LONG_DAYLIGHT]  = getZoneStringFromBundle(fZoneItem, gLongDaylightTag);
777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		zstrarray[ZSIDX_SHORT_DAYLIGHT] = getZoneStringFromBundle(fZoneItem, gShortDaylightTag);
778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		zstrarray[ZSIDX_LONG_GENERIC]   = getZoneStringFromBundle(fZoneItem, gLongGenericTag);
779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		zstrarray[ZSIDX_SHORT_GENERIC]  = getZoneStringFromBundle(fZoneItem, gShortGenericTag);
780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Compose location format string
782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString location;
783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString country;
784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString city;
785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString countryCode;
786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		ZoneMeta::getCanonicalCountry(utzid, countryCode);
787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (!countryCode.isEmpty()) {
788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			const UChar* tmpCity = getZoneStringFromBundle(fZoneItem, gExemplarCityTag);
789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (tmpCity != NULL) {
790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				city.setTo(TRUE, tmpCity, -1);
791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			} else {
792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				city.setTo(UnicodeString(pCity, -1, US_INV));
793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// Replace '_' with ' '
794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				for (int32_t i = 0; i < city.length(); i++) {
795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (city.charAt(i) == (UChar)0x5F /*'_'*/) {
796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						city.setCharAt(i, (UChar)0x20 /*' '*/);
797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			getLocalizedCountry(countryCode, fLocale, country);
801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			UnicodeString singleCountry;
802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			ZoneMeta::getSingleCountry(utzid, singleCountry);
803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			FieldPosition fpos;
804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (singleCountry.isEmpty()) {
805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				Formattable params [] = {
806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					Formattable(city),
807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					Formattable(country)
808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				};
809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				fallbackFmt->format(params, 2, location, fpos, status);
810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			} else {
811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// If the zone is only one zone in the country, do not add city
812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				Formattable params [] = {
813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					Formattable(country)
814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				};
815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				regionFmt->format(params, 1, location, fpos, status);
816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (U_FAILURE(status)) {
818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				goto error_cleanup;
819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			zstrarray[ZSIDX_LOCATION] = location.getTerminatedBuffer();
822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		} else {
823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (uprv_strlen(tzid) > 4 && uprv_strncmp(tzid, "Etc/", 4) == 0) {
824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// "Etc/xxx" is not associated with a specific location, so localized
825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// GMT format is always used as generic location format.
826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				zstrarray[ZSIDX_LOCATION] = NULL;
827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			} else {
828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// When a new time zone ID, which is actually associated with a specific
829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// location, is added in tzdata, but the current CLDR data does not have
830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// the information yet, ICU creates a generic location string based on
831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// the ID.  This implementation supports canonical time zone round trip
832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// with format pattern "VVVV".  See #6602 for the details.
833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				UnicodeString loc(utzid);
834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				int32_t slashIdx = loc.lastIndexOf((UChar)0x2f);
835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				if (slashIdx == -1) {
836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// A time zone ID without slash in the tz database is not
837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// associated with a specific location.  For instances,
838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// MET, CET, EET and WET fall into this category.
839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// In this case, we still use GMT format as fallback.
840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					zstrarray[ZSIDX_LOCATION] = NULL;
841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				} else {
842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					FieldPosition fpos;
843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					Formattable params[] = {
844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						Formattable(loc)
845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					};
846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					regionFmt->format(params, 1, location, fpos, status);
847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (U_FAILURE(status)) {
848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						goto error_cleanup;
849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					zstrarray[ZSIDX_LOCATION] = location.getTerminatedBuffer();
851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UBool commonlyUsed = isCommonlyUsed(fZoneItem);
856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Resolve metazones used by this zone
858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		int32_t mzPartialLocIdx = 0;
859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		const UVector *metazoneMappings = ZoneMeta::getMetazoneMappings(utzid);
860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (metazoneMappings != NULL) {
861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			for (int32_t i = 0; i < metazoneMappings->size(); i++) {
862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				const OlsonToMetaMappingEntry *mzmap =
863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						(const OlsonToMetaMappingEntry*)metazoneMappings->elementAt(i);
864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				UnicodeString mzid(mzmap->mzid);
865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				const ZoneStrings *mzStrings =
866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					(const ZoneStrings*)uhash_get(fMzidToStrings, mzid.getTerminatedBuffer());
867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				if (mzStrings == NULL) {
868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// If the metazone strings are not yet processed, do it now.
869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					char mzidkey[ZID_KEY_MAX];
870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					uprv_strcpy(mzidkey, gMetazoneIdPrefix);
871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					u_UCharsToChars(mzmap->mzid, mzidkey + MZID_PREFIX_LEN, u_strlen(mzmap->mzid) + 1);
872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					fMetazoneItem = ures_getByKeyWithFallback(fZoneStringsArray, mzidkey, fMetazoneItem, &status);
873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (U_FAILURE(status)) {
874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// No resources available for this metazone
875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// Resource bundle will be cleaned up after end of the loop.
876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						status = U_ZERO_ERROR;
877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						continue;
878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					UBool mzCommonlyUsed = isCommonlyUsed(fMetazoneItem);
880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_LONG_STANDARD] = getZoneStringFromBundle(fMetazoneItem, gLongStandardTag);
881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_SHORT_STANDARD] = getZoneStringFromBundle(fMetazoneItem, gShortStandardTag);
882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_LONG_DAYLIGHT] = getZoneStringFromBundle(fMetazoneItem, gLongDaylightTag);
883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_SHORT_DAYLIGHT] = getZoneStringFromBundle(fMetazoneItem, gShortDaylightTag);
884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_LONG_GENERIC] = getZoneStringFromBundle(fMetazoneItem, gLongGenericTag);
885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_SHORT_GENERIC] = getZoneStringFromBundle(fMetazoneItem, gShortGenericTag);
886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzstrarray[ZSIDX_LOCATION] = NULL;
887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					int32_t lastNonNullIdx = ZSIDX_COUNT - 1;
889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					while (lastNonNullIdx >= 0) {
890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						if (mzstrarray[lastNonNullIdx] != NULL) {
891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							break;
892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						}
893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						lastNonNullIdx--;
894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					UnicodeString *strings_mz = NULL;
896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					ZoneStrings *tmp_mzStrings = NULL;
897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (lastNonNullIdx >= 0) {
898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// Create UnicodeString array and put strings to the zone string trie
899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						strings_mz = new UnicodeString[lastNonNullIdx + 1];
900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						UnicodeString preferredIdForLocale;
902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						ZoneMeta::getZoneIdByMetazone(mzid, region, preferredIdForLocale);
903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						for (int32_t typeidx = 0; typeidx <= lastNonNullIdx; typeidx++) {
905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							if (mzstrarray[typeidx] != NULL) {
906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								strings_mz[typeidx].setTo(TRUE, mzstrarray[typeidx], -1);
907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								// Add a metazone string to the zone string trie
909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								int32_t type = getTimeZoneTranslationType((TimeZoneTranslationTypeIndex)typeidx);
910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								ZoneStringInfo *zsinfo = new ZoneStringInfo(
911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																preferredIdForLocale,
912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																strings_mz[typeidx],
913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																(TimeZoneTranslationType)type,
914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																fStringPool,
915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																status);
916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								fZoneStringsTrie.put(strings_mz[typeidx], zsinfo, fStringPool, status);
917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								if (U_FAILURE(status)) {
918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									delete []strings_mz;
919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									goto error_cleanup;
920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								}
921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							}
922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						}
923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// Note: ZoneStrings constructor adopts and deletes the strings_mz array.
924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						tmp_mzStrings = new ZoneStrings(strings_mz, lastNonNullIdx + 1,
925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)														mzCommonlyUsed, NULL, 0, 0, fStringPool, status);
926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					} else {
927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// Create ZoneStrings with empty contents
928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						tmp_mzStrings = new ZoneStrings(NULL, 0, FALSE, NULL, 0, 0, fStringPool, status);
929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					UChar *umzid = const_cast<UChar *>(fStringPool.get(mzid, status));
932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					uhash_put(fMzidToStrings, umzid, tmp_mzStrings, &status);
933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (U_FAILURE(status)) {
934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						goto error_cleanup;
935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					mzStrings = tmp_mzStrings;
938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				// Compose generic partial location format
941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				UnicodeString lg;
942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				UnicodeString sg;
943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				mzStrings->getString(ZSIDX_LONG_GENERIC, lg);
945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				mzStrings->getString(ZSIDX_SHORT_GENERIC, sg);
946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				if (!lg.isEmpty() || !sg.isEmpty()) {
948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					UBool addMzPartialLocationNames = TRUE;
949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					for (int32_t j = 0; j < mzPartialLocIdx; j++) {
950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						if (mzPartialLoc[j][0] == mzid) {
951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							// already processed
952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							addMzPartialLocationNames = FALSE;
953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							break;
954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						}
955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (addMzPartialLocationNames) {
957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						UnicodeString *locationPart = NULL;
958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// Check if the zone is the preferred zone for the territory associated with the zone
959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						UnicodeString preferredID;
960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						ZoneMeta::getZoneIdByMetazone(mzid, countryCode, preferredID);
961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						if (utzid == preferredID) {
962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							// Use country for the location
963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							locationPart = &country;
964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						} else {
965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							// Use city for the location
966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							locationPart = &city;
967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						}
968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						// Reset the partial location string array
969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						mzPartialLoc[mzPartialLocIdx][0].setTo(mzid);
970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						mzPartialLoc[mzPartialLocIdx][1].remove();
971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						mzPartialLoc[mzPartialLocIdx][2].remove();
972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						mzPartialLoc[mzPartialLocIdx][3].remove();
973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						if (locationPart->length() != 0) {
975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							FieldPosition fpos;
976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							if (!lg.isEmpty()) {
977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								Formattable params [] = {
978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									Formattable(*locationPart),
979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									Formattable(lg)
980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								};
981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								fallbackFmt->format(params, 2, mzPartialLoc[mzPartialLocIdx][1], fpos, status);
982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							}
983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							if (!sg.isEmpty()) {
984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								Formattable params [] = {
985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									Formattable(*locationPart),
986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									Formattable(sg)
987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								};
988f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								fallbackFmt->format(params, 2, mzPartialLoc[mzPartialLocIdx][2], fpos, status);
989f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								if (mzStrings->isShortFormatCommonlyUsed()) {
990f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)									mzPartialLoc[mzPartialLocIdx][3].setTo(TRUE, gCommonlyUsedTrue, -1);
991f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								}
992f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							}
993f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							if (U_FAILURE(status)) {
994f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)								goto error_cleanup;
995f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							}
996f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						}
997f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						mzPartialLocIdx++;
998f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
999f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
1000f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
1001f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1002f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Collected names for a zone
1003f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1004f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Create UnicodeString array for localized zone strings
1005f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		int32_t lastIdx = ZSIDX_COUNT - 1;
1006f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		while (lastIdx >= 0) {
1007f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (zstrarray[lastIdx] != NULL) {
1008f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				break;
1009f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
1010f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			lastIdx--;
1011f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1012f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString *strings = NULL;
1013f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		int32_t stringsCount = lastIdx + 1;
1014f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1015f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (stringsCount > 0) {
1016f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			strings = new UnicodeString[stringsCount];
1017f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			for (int32_t i = 0; i < stringsCount; i++) {
1018f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				if (zstrarray[i] != NULL) {
1019f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					strings[i].setTo(zstrarray[i], -1);
1020f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1021f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// Add names to the trie
1022f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					int32_t type = getTimeZoneTranslationType((TimeZoneTranslationTypeIndex)i);
1023f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					ZoneStringInfo *zsinfo = new ZoneStringInfo(utzid,
1024f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																strings[i],
1025f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																(TimeZoneTranslationType)type,
1026f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																fStringPool,
1027f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)																status);
1028f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					fZoneStringsTrie.put(strings[i], zsinfo, fStringPool, status);
1029f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if (U_FAILURE(status)) {
1030f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						delete zsinfo;
1031f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						delete[] strings;
1032f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						goto error_cleanup;
1033f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
1034f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
1035f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
1036f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1037f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1038f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Create UnicodeString array for generic partial location strings
1039f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString **genericPartialLocationNames = NULL;
1040f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		int32_t genericPartialRowCount = mzPartialLocIdx;
1041f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		int32_t genericPartialColCount = 4;
1042f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1043f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (genericPartialRowCount != 0) {
1044f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			genericPartialLocationNames =
1045f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					 (UnicodeString**)uprv_malloc(genericPartialRowCount * sizeof(UnicodeString*));
1046f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (genericPartialLocationNames == NULL) {
1047f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				status = U_MEMORY_ALLOCATION_ERROR;
1048f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				delete[] strings;
1049f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				goto error_cleanup;
1050f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
1051f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			for (int32_t i = 0; i < genericPartialRowCount; i++) {
1052f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				genericPartialLocationNames[i] = new UnicodeString[genericPartialColCount];
1053f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				for (int32_t j = 0; j < genericPartialColCount; j++) {
1054f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					genericPartialLocationNames[i][j].setTo(mzPartialLoc[i][j]);
1055f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					// Add names to the trie
1056f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					if ((j == 1 || j == 2) &&!genericPartialLocationNames[i][j].isEmpty()) {
1057f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						ZoneStringInfo *zsinfo;
1058f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						TimeZoneTranslationType type = (j == 1) ? GENERIC_LONG : GENERIC_SHORT;
1059f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						zsinfo = new ZoneStringInfo(utzid, genericPartialLocationNames[i][j], type,
1060f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)													fStringPool, status);
1061f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						fZoneStringsTrie.put(genericPartialLocationNames[i][j], zsinfo, fStringPool, status);
1062f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						if (U_FAILURE(status)) {
1063f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							delete[] genericPartialLocationNames[i];
1064f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							uprv_free(genericPartialLocationNames);
1065f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							delete[] strings;
1066f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)							goto error_cleanup;
1067f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)						}
1068f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					}
1069f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
1070f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
1071f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1072f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1073f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Finally, create ZoneStrings instance and put it into the tzidToStinrgs map
1074f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		ZoneStrings *zstrings = new ZoneStrings(strings, stringsCount, commonlyUsed,
1075f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)												genericPartialLocationNames, genericPartialRowCount,
1076f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)												genericPartialColCount, fStringPool, status);
1077f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1078f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UChar *uutzid = const_cast<UChar *>(fStringPool.get(utzid, status));
1079f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		uhash_put(fTzidToStrings, uutzid, zstrings, &status);
1080f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (U_FAILURE(status)) {
1081f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			delete zstrings;
1082f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			goto error_cleanup;
1083f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1084f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1085f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1086f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)error_cleanup:
1087f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fallbackFmt != NULL) {
1088f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete fallbackFmt;
1089f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1090f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (regionFmt != NULL) {
1091f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete regionFmt;
1092f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1093f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    //	fStringPool.freeze();
1094f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1095f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1096f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
1097f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::loadFull(UErrorCode &status)
1098f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
1099f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
1101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (fIsFullyLoaded) {
1103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		return;
1104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	umtx_lock(&ZoneStringFormatMutex);
1107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (fZoneStringsArray == NULL) {
1109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		fZoneStringsArray = ures_open(U_ICUDATA_ZONE, fLocale.getName(), &status);
1110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		fZoneStringsArray = ures_getByKeyWithFallback(fZoneStringsArray, gZoneStringsTag, fZoneStringsArray, &status);
1111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (U_FAILURE(status)) {
1112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// If no locale bundles are available, zoneStrings will be null.
1113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// We still want to go through the rest of zone strings initialization,
1114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// because generic location format is generated from tzid for the case.
1115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			// The rest of code should work even zoneStrings is null.
1116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			status = U_ZERO_ERROR;
1117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			ures_close(fZoneStringsArray);
1118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			fZoneStringsArray = NULL;
1119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    StringEnumeration *tzids = NULL;
1123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    tzids = TimeZone::createEnumeration();
1125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const char *tzid;
1126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while ((tzid = tzids->next(NULL, status))) {
1127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            goto error_cleanup;
1129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Skip non-canonical IDs
1131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString utzid(tzid, -1, US_INV);
1132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString canonicalID;
1133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        TimeZone::getCanonicalID(utzid, canonicalID, status);
1134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Ignore unknown ID - we should not get here, but just in case.
1136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_ZERO_ERROR;
1137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            continue;
1138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (U_SUCCESS(status)) {
1141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			if (uhash_count(fTzidToStrings) > 0) {
1142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				ZoneStrings *zstrings = (ZoneStrings*)uhash_get(fTzidToStrings, canonicalID.getTerminatedBuffer());
1143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				if (zstrings != NULL) {
1144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)					continue;	//	We already about this one
1145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)				}
1146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			}
1147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		addSingleZone(canonicalID, status);
1150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			goto error_cleanup;
1153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	fIsFullyLoaded = TRUE;
1157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)error_cleanup:
1159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (tzids != NULL) {
1160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete tzids;
1161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fStringPool.freeze();
1163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	umtx_unlock(&ZoneStringFormatMutex);
1165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::~ZoneStringFormat() {
1169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_close(fTzidToStrings);
1170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_close(fMzidToStrings);
1171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ures_close(fZoneItem);
1172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ures_close(fMetazoneItem);
1173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ures_close(fZoneStringsArray);
1174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)SafeZoneStringFormatPtr*
1177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getZoneStringFormat(const Locale& locale, UErrorCode &status) {
1178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_lock(&gZSFCacheLock);
1179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (gZoneStringFormatCache == NULL) {
1180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        gZoneStringFormatCache = new ZSFCache(10 /* capacity */);
1181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ucln_i18n_registerCleanup(UCLN_I18N_ZSFORMAT, zoneStringFormat_cleanup);
1182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_unlock(&gZSFCacheLock);
1184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return gZoneStringFormatCache->get(locale, status);
1186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString**
1190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::createZoneStringsArray(UDate date, int32_t &rowCount, int32_t &colCount, UErrorCode &status) const {
1191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	ZoneStringFormat *nonConstThis = const_cast<ZoneStringFormat *>(this);
1195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	nonConstThis->loadFull(status);
1196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString **result = NULL;
1198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    rowCount = 0;
1199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    colCount = 0;
1200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Collect canonical time zone IDs
1202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UVector canonicalIDs(uhash_deleteUnicodeString, uhash_compareUnicodeString, status);
1203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    StringEnumeration *tzids = TimeZone::createEnumeration();
1207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *tzid;
1208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while ((tzid = tzids->unext(NULL, status))) {
1209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete tzids;
1211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return NULL;
1212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString utzid(tzid);
1214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString canonicalID;
1215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        TimeZone::getCanonicalID(UnicodeString(tzid), canonicalID, status);
1216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Ignore unknown ID - we should not get here, but just in case.
1218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_ZERO_ERROR;
1219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            continue;
1220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (utzid == canonicalID) {
1222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            canonicalIDs.addElement(new UnicodeString(utzid), status);
1223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (U_FAILURE(status)) {
1224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                delete tzids;
1225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return NULL;
1226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete tzids;
1230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Allocate array
1232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result = (UnicodeString**)uprv_malloc(canonicalIDs.size() * sizeof(UnicodeString*));
1233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (result == NULL) {
1234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = U_MEMORY_ALLOCATION_ERROR;
1235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (int32_t i = 0; i < canonicalIDs.size(); i++) {
1238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result[i] = new UnicodeString[8];
1239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString *id = (UnicodeString*)canonicalIDs.elementAt(i);
1240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result[i][0].setTo(*id);
1241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getLongStandard(*id, date, result[i][1]);
1242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getShortStandard(*id, date, FALSE, result[i][2]);
1243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getLongDaylight(*id, date, result[i][3]);
1244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getShortDaylight(*id, date, FALSE, result[i][4]);
1245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getGenericLocation(*id, result[i][5]);
1246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getLongGenericNonLocation(*id, date, result[i][6]);
1247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getShortGenericNonLocation(*id, date, FALSE, result[i][7]);
1248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    rowCount = canonicalIDs.size();
1251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    colCount = 8;
1252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getSpecificLongString(const Calendar &cal, UnicodeString &result,
1257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                        UErrorCode &status) const {
1258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result.remove();
1259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return result;
1261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString tzid;
1263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    cal.getTimeZone().getID(tzid);
1264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UDate date = cal.getTime(status);
1265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (cal.get(UCAL_DST_OFFSET, status) == 0) {
1266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return getString(tzid, ZSIDX_LONG_STANDARD, date, FALSE /*not used*/, result);
1267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
1268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return getString(tzid, ZSIDX_LONG_DAYLIGHT, date, FALSE /*not used*/, result);
1269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getSpecificShortString(const Calendar &cal, UBool commonlyUsedOnly,
1274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                         UnicodeString &result, UErrorCode &status) const {
1275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result.remove();
1276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return result;
1278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString tzid;
1280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    cal.getTimeZone().getID(tzid);
1281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UDate date = cal.getTime(status);
1282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (cal.get(UCAL_DST_OFFSET, status) == 0) {
1283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return getString(tzid, ZSIDX_SHORT_STANDARD, date, commonlyUsedOnly, result);
1284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
1285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return getString(tzid, ZSIDX_SHORT_DAYLIGHT, date, commonlyUsedOnly, result);
1286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getGenericLongString(const Calendar &cal, UnicodeString &result,
1291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                       UErrorCode &status) const {
1292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return getGenericString(cal, FALSE /*long*/, FALSE /* not used */, result, status);
1293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getGenericShortString(const Calendar &cal, UBool commonlyUsedOnly,
1297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                        UnicodeString &result, UErrorCode &status) const {
1298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return getGenericString(cal, TRUE /*short*/, commonlyUsedOnly, result, status);
1299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getGenericLocationString(const Calendar &cal, UnicodeString &result,
1303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                           UErrorCode &status) const {
1304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString tzid;
1305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    cal.getTimeZone().getID(tzid);
1306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UDate date = cal.getTime(status);
1307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return getString(tzid, ZSIDX_LOCATION, date, FALSE /*not used*/, result);
1308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::findSpecificLong(const UnicodeString &text, int32_t start,
1312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                   int32_t &matchLength, UErrorCode &status) const {
1313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return find(text, start, STANDARD_LONG | DAYLIGHT_LONG, matchLength, status);
1314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::findSpecificShort(const UnicodeString &text, int32_t start,
1318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                    int32_t &matchLength, UErrorCode &status) const {
1319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return find(text, start, STANDARD_SHORT | DAYLIGHT_SHORT, matchLength, status);
1320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::findGenericLong(const UnicodeString &text, int32_t start,
1324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                  int32_t &matchLength, UErrorCode &status) const {
1325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return find(text, start, GENERIC_LONG | STANDARD_LONG | LOCATION, matchLength, status);
1326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::findGenericShort(const UnicodeString &text, int32_t start,
1330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                   int32_t &matchLength, UErrorCode &status) const {
1331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return find(text, start, GENERIC_SHORT | STANDARD_SHORT | LOCATION, matchLength, status);
1332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::findGenericLocation(const UnicodeString &text, int32_t start,
1336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                      int32_t &matchLength, UErrorCode &status) const {
1337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return find(text, start, LOCATION, matchLength, status);
1338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getString(const UnicodeString &tzid, TimeZoneTranslationTypeIndex typeIdx, UDate date,
1342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            UBool commonlyUsedOnly, UnicodeString& result) const {
1343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
1344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result.remove();
1345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (!fIsFullyLoaded) {
1346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Lazy loading
1347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		ZoneStringFormat *nonConstThis = const_cast<ZoneStringFormat *>(this);
1348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		nonConstThis->loadZone(tzid, status);
1349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // ICU's own array does not have entries for aliases
1352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString canonicalID;
1353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    TimeZone::getCanonicalID(tzid, canonicalID, status);
1354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Unknown ID, but users might have their own data.
1356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        canonicalID.setTo(tzid);
1357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (uhash_count(fTzidToStrings) > 0) {
1360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZoneStrings *zstrings = (ZoneStrings*)uhash_get(fTzidToStrings, canonicalID.getTerminatedBuffer());
1361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (zstrings != NULL) {
1362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            switch (typeIdx) {
1363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_LONG_STANDARD:
1364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_LONG_DAYLIGHT:
1365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_LONG_GENERIC:
1366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_LOCATION:
1367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    zstrings->getString(typeIdx, result);
1368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_SHORT_STANDARD:
1370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_SHORT_DAYLIGHT:
1371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_COUNT: //added to avoid warning
1372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ZSIDX_SHORT_GENERIC:
1373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (!commonlyUsedOnly || zstrings->isShortFormatCommonlyUsed()) {
1374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        zstrings->getString(typeIdx, result);
1375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                default:
1378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (result.isEmpty() && uhash_count(fMzidToStrings) > 0 && typeIdx != ZSIDX_LOCATION) {
1383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Try metazone
1384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString mzid;
1385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZoneMeta::getMetazoneID(canonicalID, date, mzid);
1386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (!mzid.isEmpty()) {
1387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ZoneStrings *mzstrings = (ZoneStrings*)uhash_get(fMzidToStrings, mzid.getTerminatedBuffer());
1388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (mzstrings != NULL) {
1389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                switch (typeIdx) {
1390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_LONG_STANDARD:
1391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_LONG_DAYLIGHT:
1392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_LONG_GENERIC:
1393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_LOCATION:
1394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        mzstrings->getString(typeIdx, result);
1395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
1396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_SHORT_STANDARD:
1397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_SHORT_DAYLIGHT:
1398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_COUNT: //added to avoid warning
1399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    case ZSIDX_SHORT_GENERIC:
1400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (!commonlyUsedOnly || mzstrings->isShortFormatCommonlyUsed()) {
1401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            mzstrings->getString(typeIdx, result);
1402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
1404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    default:
1405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
1406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getGenericString(const Calendar &cal, UBool isShort, UBool commonlyUsedOnly,
1415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                   UnicodeString &result, UErrorCode &status) const {
1416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result.remove();
1417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UDate time = cal.getTime(status);
1418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return result;
1420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const TimeZone &tz = cal.getTimeZone();
1422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString tzid;
1423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    tz.getID(tzid);
1424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (!fIsFullyLoaded) {
1426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Lazy loading
1427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		ZoneStringFormat *nonConstThis = const_cast<ZoneStringFormat *>(this);
1428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		nonConstThis->loadZone(tzid, status);
1429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // ICU's own array does not have entries for aliases
1432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString canonicalID;
1433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    TimeZone::getCanonicalID(tzid, canonicalID, status);
1434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Unknown ID, but users might have their own data.
1436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = U_ZERO_ERROR;
1437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        canonicalID.setTo(tzid);
1438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZoneStrings *zstrings = NULL;
1441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (uhash_count(fTzidToStrings) > 0) {
1442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        zstrings = (ZoneStrings*)uhash_get(fTzidToStrings, canonicalID.getTerminatedBuffer());
1443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (zstrings != NULL) {
1444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (isShort) {
1445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (!commonlyUsedOnly || zstrings->isShortFormatCommonlyUsed()) {
1446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    zstrings->getString(ZSIDX_SHORT_GENERIC, result);
1447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
1449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                zstrings->getString(ZSIDX_LONG_GENERIC, result);
1450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (result.isEmpty() && uhash_count(fMzidToStrings) > 0) {
1454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // try metazone
1455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t raw, sav;
1456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UnicodeString mzid;
1457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZoneMeta::getMetazoneID(canonicalID, time, mzid);
1458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (!mzid.isEmpty()) {
1459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UBool useStandard = FALSE;
1460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            sav = cal.get(UCAL_DST_OFFSET, status);
1461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (U_FAILURE(status)) {
1462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return result;
1463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (sav == 0) {
1465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                useStandard = TRUE;
1466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // Check if the zone actually uses daylight saving time around the time
1467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                TimeZone *tmptz = tz.clone();
1468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                BasicTimeZone *btz = NULL;
1469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (dynamic_cast<OlsonTimeZone *>(tmptz) != NULL
1470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    || dynamic_cast<SimpleTimeZone *>(tmptz) != NULL
1471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    || dynamic_cast<RuleBasedTimeZone *>(tmptz) != NULL
1472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    || dynamic_cast<VTimeZone *>(tmptz) != NULL) {
1473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    btz = (BasicTimeZone*)tmptz;
1474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (btz != NULL) {
1477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    TimeZoneTransition before;
1478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UBool beforTrs = btz->getPreviousTransition(time, TRUE, before);
1479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (beforTrs
1480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            && (time - before.getTime() < kDstCheckRange)
1481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            && before.getFrom()->getDSTSavings() != 0) {
1482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        useStandard = FALSE;
1483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    } else {
1484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        TimeZoneTransition after;
1485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        UBool afterTrs = btz->getNextTransition(time, FALSE, after);
1486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (afterTrs
1487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                && (after.getTime() - time < kDstCheckRange)
1488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                && after.getTo()->getDSTSavings() != 0) {
1489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            useStandard = FALSE;
1490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else {
1493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // If not BasicTimeZone... only if the instance is not an ICU's implementation.
1494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // We may get a wrong answer in edge case, but it should practically work OK.
1495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    tmptz->getOffset(time - kDstCheckRange, FALSE, raw, sav, status);
1496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (sav != 0) {
1497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        useStandard = FALSE;
1498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    } else {
1499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        tmptz->getOffset(time + kDstCheckRange, FALSE, raw, sav, status);
1500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (sav != 0){
1501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            useStandard = FALSE;
1502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (U_FAILURE(status)) {
1505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        delete tmptz;
1506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        result.remove();
1507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        return result;
1508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                delete tmptz;
1511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (useStandard) {
1513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                getString(canonicalID, (isShort ? ZSIDX_SHORT_STANDARD : ZSIDX_LONG_STANDARD),
1514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    time, commonlyUsedOnly, result);
1515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // Note:
1517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // In CLDR 1.5.1, a same localization is used for both generic and standard
1518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // for some metazones in some locales.  This is actually data bugs and should
1519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // be resolved in later versions of CLDR.  For now, we check if the standard
1520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // name is different from its generic name below.
1521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (!result.isEmpty()) {
1522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UnicodeString genericNonLocation;
1523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    getString(canonicalID, (isShort ? ZSIDX_SHORT_GENERIC : ZSIDX_LONG_GENERIC),
1524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        time, commonlyUsedOnly, genericNonLocation);
1525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (!genericNonLocation.isEmpty() && result == genericNonLocation) {
1526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        result.remove();
1527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (result.isEmpty()) {
1531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                ZoneStrings *mzstrings = (ZoneStrings*)uhash_get(fMzidToStrings, mzid.getTerminatedBuffer());
1532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (mzstrings != NULL) {
1533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (isShort) {
1534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (!commonlyUsedOnly || mzstrings->isShortFormatCommonlyUsed()) {
1535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            mzstrings->getString(ZSIDX_SHORT_GENERIC, result);
1536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    } else {
1538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        mzstrings->getString(ZSIDX_LONG_GENERIC, result);
1539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (!result.isEmpty()) {
1542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // Check if the offsets at the given time matches the preferred zone's offsets
1543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UnicodeString preferredId;
1544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    UnicodeString region;
1545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    ZoneMeta::getZoneIdByMetazone(mzid, getRegion(region), preferredId);
1546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (canonicalID != preferredId) {
1547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // Check if the offsets at the given time are identical with the preferred zone
1548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        raw = cal.get(UCAL_ZONE_OFFSET, status);
1549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (U_FAILURE(status)) {
1550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            result.remove();
1551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            return result;
1552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        TimeZone *preferredZone = TimeZone::createTimeZone(preferredId);
1554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        int32_t prfRaw, prfSav;
1555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // Check offset in preferred time zone with wall time.
1556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // With getOffset(time, false, preferredOffsets),
1557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // you may get incorrect results because of time overlap at DST->STD
1558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        // transition.
1559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        preferredZone->getOffset(time + raw + sav, TRUE, prfRaw, prfSav, status);
1560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        delete preferredZone;
1561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (U_FAILURE(status)) {
1563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            result.remove();
1564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            return result;
1565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if ((raw != prfRaw || sav != prfSav) && zstrings != NULL) {
1567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            // Use generic partial location string as fallback
1568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            zstrings->getGenericPartialLocationString(mzid, isShort, commonlyUsedOnly, result);
1569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (result.isEmpty()) {
1576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Use location format as the final fallback
1577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        getString(canonicalID, ZSIDX_LOCATION, time, FALSE /*not used*/, result);
1578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getGenericPartialLocationString(const UnicodeString &tzid, UBool isShort,
1585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                                  UDate date, UBool commonlyUsedOnly, UnicodeString &result) const {
1586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
1587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result.remove();
1588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (!fIsFullyLoaded) {
1589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		// Lazy loading
1590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		ZoneStringFormat *nonConstThis = const_cast<ZoneStringFormat *>(this);
1591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		nonConstThis->loadZone(tzid, status);
1592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (uhash_count(fTzidToStrings) <= 0) {
1595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return result;
1596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString canonicalID;
1599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    TimeZone::getCanonicalID(tzid, canonicalID, status);
1600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Unknown ID, so no corresponding meta data.
1602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return result;
1603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString mzid;
1606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZoneMeta::getMetazoneID(canonicalID, date, mzid);
1607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!mzid.isEmpty()) {
1609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZoneStrings *zstrings = (ZoneStrings*)uhash_get(fTzidToStrings, canonicalID.getTerminatedBuffer());
1610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (zstrings != NULL) {
1611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            zstrings->getGenericPartialLocationString(mzid, isShort, commonlyUsedOnly, result);
1612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// This method does lazy zone string loading
1618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::find(const UnicodeString &text, int32_t start, int32_t types,
1620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       int32_t &matchLength, UErrorCode &status) const {
1621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	const ZoneStringInfo *	result = subFind(text, start, types, matchLength, status);
1627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (fIsFullyLoaded) {
1628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		return result;
1629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	// When zone string data is partially loaded,
1631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	// this method return the result only when
1632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	// the input text is fully consumed.
1633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	if (result != NULL) {
1634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		UnicodeString tmpString;
1635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		matchLength = (result->getString(tmpString)).length();
1636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		if (text.length() - start == matchLength) {
1637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)			return result;
1638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)		}
1639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	}
1640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	// Now load all zone strings
1642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	ZoneStringFormat *nonConstThis = const_cast<ZoneStringFormat *>(this);
1643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	nonConstThis->loadFull(status);
1644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)	return subFind(text, start, types, matchLength, status);
1646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
1650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Find a prefix matching time zone for the given zone string types.
1651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param text The text contains a time zone string
1652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param start The start index within the text
1653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param types The bit mask representing a set of requested types
1654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @return If any zone string matched for the requested types, returns a
1655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ZoneStringInfo for the longest match.  If no matches are found for
1656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the requested types, returns a ZoneStringInfo for the longest match
1657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * for any other types.  If nothing matches at all, returns null.
1658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
1659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringInfo*
1660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::subFind(const UnicodeString &text, int32_t start, int32_t types,
1661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       int32_t &matchLength, UErrorCode &status) const {
1662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    matchLength = 0;
1663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fZoneStringsTrie.isEmpty()) {
1667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const ZoneStringInfo *result = NULL;
1671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const ZoneStringInfo *fallback = NULL;
1672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t fallbackMatchLen = 0;
1673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZoneStringSearchResultHandler handler(status);
1675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fZoneStringsTrie.search(text, start, (TextTrieMapSearchResultHandler*)&handler, status);
1676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_SUCCESS(status)) {
1677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t numMatches = handler.countMatches();
1678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t i = 0; i < numMatches; i++) {
1679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t tmpMatchLen = 0; // init. output only param to silence gcc
1680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const ZoneStringInfo *tmp = handler.getMatch(i, tmpMatchLen);
1681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if ((types & tmp->fType) != 0) {
1682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (result == NULL || matchLength < tmpMatchLen) {
1683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    result = tmp;
1684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    matchLength = tmpMatchLen;
1685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else if (matchLength == tmpMatchLen) {
1686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // Tie breaker - there are some examples that a
1687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // long standard name is identical with a location
1688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // name - for example, "Uruguay Time".  In this case,
1689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // we interpret it as generic, not specific.
1690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (tmp->isGeneric() && !result->isGeneric()) {
1691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        result = tmp;
1692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else if (result == NULL) {
1695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (fallback == NULL || fallbackMatchLen < tmpMatchLen) {
1696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    fallback = tmp;
1697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    fallbackMatchLen = tmpMatchLen;
1698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else if (fallbackMatchLen == tmpMatchLen) {
1699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (tmp->isGeneric() && !fallback->isGeneric()) {
1700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        fallback = tmp;
1701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (result == NULL && fallback != NULL) {
1706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            result = fallback;
1707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            matchLength = fallbackMatchLen;
1708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getRegion(UnicodeString &region) const {
1716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const char* country = fLocale.getCountry();
1717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // TODO: Utilize addLikelySubtag in Locale to resolve default region
1718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // when the implementation is ready.
1719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    region.setTo(UnicodeString(country, -1, US_INV));
1720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return region;
1721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)MessageFormat*
1724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getFallbackFormat(const Locale &locale, UErrorCode &status) {
1725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString pattern(TRUE, gDefFallbackPattern, -1);
1729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UResourceBundle *zoneStringsArray = ures_open(U_ICUDATA_ZONE, locale.getName(), &status);
1730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    zoneStringsArray = ures_getByKeyWithFallback(zoneStringsArray, gZoneStringsTag, zoneStringsArray, &status);
1731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t len;
1732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *flbkfmt = ures_getStringByKeyWithFallback(zoneStringsArray, gFallbackFormatTag, &len, &status);
1733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_SUCCESS(status)) {
1734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        pattern.setTo(flbkfmt);
1735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
1736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = U_ZERO_ERROR;
1737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ures_close(zoneStringsArray);
1739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    MessageFormat *fallbackFmt = new MessageFormat(pattern, status);
1741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return fallbackFmt;
1742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)MessageFormat*
1745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getRegionFormat(const Locale& locale, UErrorCode &status) {
1746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString pattern(TRUE, gDefRegionPattern, -1);
1750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UResourceBundle *zoneStringsArray = ures_open(U_ICUDATA_ZONE, locale.getName(), &status);
1751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    zoneStringsArray = ures_getByKeyWithFallback(zoneStringsArray, gZoneStringsTag, zoneStringsArray, &status);
1752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t len;
1753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *regionfmt = ures_getStringByKeyWithFallback(zoneStringsArray, gRegionFormatTag, &len, &status);
1754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_SUCCESS(status)) {
1755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        pattern.setTo(regionfmt);
1756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
1757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = U_ZERO_ERROR;
1758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ures_close(zoneStringsArray);
1760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    MessageFormat *regionFmt = new MessageFormat(pattern, status);
1762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return regionFmt;
1763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UChar*
1766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getZoneStringFromBundle(const UResourceBundle *zoneitem, const char *key) {
1767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *str = NULL;
1768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (zoneitem != NULL) {
1769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode status = U_ZERO_ERROR;
1770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t len;
1771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        str = ures_getStringByKeyWithFallback(zoneitem, key, &len, &status);
1772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        str = fStringPool.adopt(str, status);
1773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            str = NULL;
1775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return str;
1778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UBool
1781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::isCommonlyUsed(const UResourceBundle *zoneitem) {
1782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (zoneitem == NULL) {
1783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return TRUE;
1784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool commonlyUsed = FALSE;
1787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
1788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UResourceBundle *cuRes = ures_getByKey(zoneitem, gCommonlyUsedTag, NULL, &status);
1789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t cuValue = ures_getInt(cuRes, &status);
1790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_SUCCESS(status)) {
1791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (cuValue == 1) {
1792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            commonlyUsed = TRUE;
1793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ures_close(cuRes);
1796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return commonlyUsed;
1797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStringFormat::getLocalizedCountry(const UnicodeString &countryCode, const Locale &locale, UnicodeString &displayCountry) {
1801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // We do not want to use display country names only from the target language bundle
1802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Note: we should do this in better way.
1803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    displayCountry.remove();
1804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t ccLen = countryCode.length();
1805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (ccLen > 0 && ccLen < ULOC_COUNTRY_CAPACITY) {
1806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode status = U_ZERO_ERROR;
1807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status);
1808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_SUCCESS(status)) {
1809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            const char *bundleLocStr = ures_getLocale(localeBundle, &status);
1810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (U_SUCCESS(status) && uprv_strlen(bundleLocStr) > 0) {
1811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                Locale bundleLoc(bundleLocStr);
1812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (uprv_strcmp(bundleLocStr, "root") != 0 &&
1813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    uprv_strcmp(bundleLoc.getLanguage(), locale.getLanguage()) == 0) {
1814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    // Create a fake locale strings
1815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    char tmpLocStr[ULOC_COUNTRY_CAPACITY + 3];
1816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    uprv_strcpy(tmpLocStr, "xx_");
1817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    u_UCharsToChars(countryCode.getBuffer(), &tmpLocStr[3], ccLen);
1818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    tmpLocStr[3 + ccLen] = 0;
1819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    Locale tmpLoc(tmpLocStr);
1821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    tmpLoc.getDisplayCountry(locale, displayCountry);
1822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ures_close(localeBundle);
1826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (displayCountry.isEmpty()) {
1828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Use the country code as the fallback
1829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        displayCountry.setTo(countryCode);
1830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return displayCountry;
1832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// ----------------------------------------------------------------------------
1835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
1836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ZoneStrings constructor adopts (and promptly copies and deletes)
1837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *    the input UnicodeString arrays.
1838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
1839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStrings::ZoneStrings(UnicodeString *strings,
1840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         int32_t stringsCount,
1841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         UBool commonlyUsed,
1842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         UnicodeString **genericPartialLocationStrings,
1843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         int32_t genericRowCount,
1844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         int32_t genericColCount,
1845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         ZSFStringPool &sp,
1846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         UErrorCode &status)
1847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles):   fStrings(NULL),
1848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fStringsCount(stringsCount),
1849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fIsCommonlyUsed(commonlyUsed),
1850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fGenericPartialLocationStrings(NULL),
1851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fGenericPartialLocationRowCount(genericRowCount),
1852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fGenericPartialLocationColCount(genericColCount)
1853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
1854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
1855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
1856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t i, j;
1858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (strings != NULL) {
1859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fStrings = (const UChar **)uprv_malloc(sizeof(const UChar **) * stringsCount);
1860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (fStrings == NULL) {
1861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_MEMORY_ALLOCATION_ERROR;
1862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return;
1863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (i=0; i<fStringsCount; i++) {
1865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fStrings[i] = sp.get(strings[i], status);
1866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete[] strings;
1868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (genericPartialLocationStrings != NULL) {
1870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fGenericPartialLocationStrings =
1871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (const UChar ***)uprv_malloc(sizeof(const UChar ***) * genericRowCount);
1872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (fGenericPartialLocationStrings == NULL) {
1873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_MEMORY_ALLOCATION_ERROR;
1874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return;
1875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (i=0; i < fGenericPartialLocationRowCount; i++) {
1877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fGenericPartialLocationStrings[i] =
1878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                (const UChar **)uprv_malloc(sizeof(const UChar **) * genericColCount);
1879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (fGenericPartialLocationStrings[i] == NULL) {
1880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                status = U_MEMORY_ALLOCATION_ERROR;
1881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                continue;   // Continue so that fGenericPartialLocationStrings will not contain uninitialized junk,
1882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }               //   which would crash the destructor.
1883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            for (j=0; j<genericColCount; j++) {
1884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                fGenericPartialLocationStrings[i][j] =
1885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        sp.get(genericPartialLocationStrings[i][j], status);
1886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete[] genericPartialLocationStrings[i];
1888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(genericPartialLocationStrings);
1890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStrings::~ZoneStrings() {
1894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(fStrings);
1895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fGenericPartialLocationStrings != NULL) {
1896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t i = 0; i < fGenericPartialLocationRowCount; i++) {
1897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_free(fGenericPartialLocationStrings[i]);
1898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(fGenericPartialLocationStrings);
1900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStrings::getString(int32_t typeIdx, UnicodeString &result) const {
1906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (typeIdx >= 0 && typeIdx < fStringsCount) {
1907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result.setTo(fStrings[typeIdx], -1);
1908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
1909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result.remove();
1910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)UnicodeString&
1915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZoneStrings::getGenericPartialLocationString(const UnicodeString &mzid, UBool isShort,
1916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                        UBool commonlyUsedOnly, UnicodeString &result) const {
1917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool isSet = FALSE;
1918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fGenericPartialLocationColCount >= 2) {
1919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        for (int32_t i = 0; i < fGenericPartialLocationRowCount; i++) {
1920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (mzid.compare(fGenericPartialLocationStrings[i][0], -1) == 0) {
1921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (isShort) {
1922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (fGenericPartialLocationColCount >= 3) {
1923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if (!commonlyUsedOnly ||
1924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            fGenericPartialLocationColCount == 3 ||
1925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            fGenericPartialLocationStrings[i][3][0] != 0) {
1926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                result.setTo(fGenericPartialLocationStrings[i][2], -1);
1927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            isSet = TRUE;
1928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
1929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else {
1931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    result.setTo(fGenericPartialLocationStrings[i][1], -1);
1932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    isSet = TRUE;
1933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!isSet) {
1939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result.remove();
1940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
1942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)// --------------------------------------------------------------
1945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)SafeZoneStringFormatPtr::SafeZoneStringFormatPtr(ZSFCacheEntry *cacheEntry)
1946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fCacheEntry(cacheEntry) {
1947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)SafeZoneStringFormatPtr::~SafeZoneStringFormatPtr() {
1950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fCacheEntry->delRef();
1951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringFormat*
1954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)SafeZoneStringFormatPtr::get() const {
1955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return fCacheEntry->getZoneStringFormat();
1956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCacheEntry::ZSFCacheEntry(const Locale &locale, ZoneStringFormat *zsf, ZSFCacheEntry *next)
1959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fLocale(locale), fZoneStringFormat(zsf),
1960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) fNext(next), fRefCount(1)
1961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
1962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCacheEntry::~ZSFCacheEntry () {
1965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete fZoneStringFormat;
1966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const ZoneStringFormat*
1969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCacheEntry::getZoneStringFormat(void) {
1970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return (const ZoneStringFormat*)fZoneStringFormat;
1971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void
1974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCacheEntry::delRef(void) {
1975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_lock(&gZSFCacheLock);
1976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    --fRefCount;
1977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_unlock(&gZSFCacheLock);
1978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCache::ZSFCache(int32_t capacity)
1981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles): fCapacity(capacity), fFirst(NULL) {
1982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCache::~ZSFCache() {
1985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZSFCacheEntry *entry = fFirst;
1986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (entry) {
1987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZSFCacheEntry *next = entry->fNext;
1988f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete entry;
1989f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        entry = next;
1990f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1991f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1992f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1993f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)SafeZoneStringFormatPtr*
1994f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFCache::get(const Locale &locale, UErrorCode &status) {
1995f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    SafeZoneStringFormatPtr *result = NULL;
1996f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1997f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Search the cache entry list
1998f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZSFCacheEntry *entry = NULL;
1999f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZSFCacheEntry *next, *prev;
2000f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2001f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_lock(&gZSFCacheLock);
2002f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    entry = fFirst;
2003f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prev = NULL;
2004f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (entry) {
2005f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        next = entry->fNext;
2006f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (entry->fLocale == locale) {
2007f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Add reference count
2008f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            entry->fRefCount++;
2009f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2010f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // move the entry to the top
2011f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (entry != fFirst) {
2012f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                prev->fNext = next;
2013f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                entry->fNext = fFirst;
2014f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                fFirst = entry;
2015f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
2016f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
2017f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2018f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        prev = entry;
2019f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        entry = next;
2020f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2021f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_unlock(&gZSFCacheLock);
2022f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2023f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Create a new ZoneStringFormat
2024f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (entry == NULL) {
2025f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZoneStringFormat *zsf = new ZoneStringFormat(locale, status);
2026f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
2027f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete zsf;
2028f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return NULL;
2029f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2030f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (zsf == NULL) {
2031f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_MEMORY_ALLOCATION_ERROR;
2032f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return NULL;
2033f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2034f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2035f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Now add the new entry
2036f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        umtx_lock(&gZSFCacheLock);
2037f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        // Make sure no other threads already created the one for the same locale
2038f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        entry = fFirst;
2039f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        prev = NULL;
2040f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while (entry) {
2041f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            next = entry->fNext;
2042f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (entry->fLocale == locale) {
2043f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // Add reference count
2044f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                entry->fRefCount++;
2045f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2046f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                // move the entry to the top
2047f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (entry != fFirst) {
2048f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    prev->fNext = next;
2049f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    entry->fNext = fFirst;
2050f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    fFirst = entry;
2051f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
2052f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
2053f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
2054f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            prev = entry;
2055f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            entry = next;
2056f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2057f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (entry == NULL) {
2058f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Add the new one to the top
2059f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            next = fFirst;
2060f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            entry = new ZSFCacheEntry(locale, zsf, next);
2061f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            fFirst = entry;
2062f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
2063f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete zsf;
2064f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2065f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        umtx_unlock(&gZSFCacheLock);
2066f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2067f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2068f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    result = new SafeZoneStringFormatPtr(entry);
2069f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2070f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    // Now, delete unused cache entries beyond the capacity
2071f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_lock(&gZSFCacheLock);
2072f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    entry = fFirst;
2073f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prev = NULL;
2074f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t idx = 1;
2075f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (entry) {
2076f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        next = entry->fNext;
2077f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (idx >= fCapacity && entry->fRefCount == 0) {
2078f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (entry == fFirst) {
2079f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                fFirst = next;
2080f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
2081f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                prev->fNext = next;
2082f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
2083f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            delete entry;
2084f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
2085f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            prev = entry;
2086f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2087f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        entry = next;
2088f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        idx++;
2089f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2090f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    umtx_unlock(&gZSFCacheLock);
2091f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2092f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
2093f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2094f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2095f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2096f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2097f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Zone String Formatter String Pool Implementation
2098f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
2099f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *    String pool for (UChar *) strings.  Avoids having repeated copies of the same string.
2100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
2101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const int32_t POOL_CHUNK_SIZE = 2000;
2103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)struct ZSFStringPoolChunk: public UMemory {
2104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZSFStringPoolChunk    *fNext;                       // Ptr to next pool chunk
2105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t               fLimit;                       // Index to start of unused area at end of fStrings
2106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar                 fStrings[POOL_CHUNK_SIZE];    //  Strings array
2107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ZSFStringPoolChunk();
2108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)};
2109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFStringPoolChunk::ZSFStringPoolChunk() {
2111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fNext = NULL;
2112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fLimit = 0;
2113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFStringPool::ZSFStringPool(UErrorCode &status) {
2116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fChunks = NULL;
2117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fHash   = NULL;
2118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
2119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
2120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fChunks = new ZSFStringPoolChunk;
2122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fChunks == NULL) {
2123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        status = U_MEMORY_ALLOCATION_ERROR;
2124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
2125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fHash   = uhash_open(uhash_hashUChars      /* keyHash */,
2128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         uhash_compareUChars   /* keyComp */,
2129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         uhash_compareUChars   /* valueComp */,
2130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         &status);
2131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
2132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return;
2133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ZSFStringPool::~ZSFStringPool() {
2138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (fHash != NULL) {
2139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uhash_close(fHash);
2140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fHash = NULL;
2141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while (fChunks != NULL) {
2144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZSFStringPoolChunk *nextChunk = fChunks->fNext;
2145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        delete fChunks;
2146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fChunks = nextChunk;
2147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar EmptyString = 0;
2151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UChar *ZSFStringPool::get(const UChar *s, UErrorCode &status) {
2153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *pooledString;
2154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
2155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return &EmptyString;
2156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    pooledString = static_cast<UChar *>(uhash_get(fHash, s));
2159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (pooledString != NULL) {
2160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return pooledString;
2161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t length = u_strlen(s);
2164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t remainingLength = POOL_CHUNK_SIZE - fChunks->fLimit;
2165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (remainingLength <= length) {
2166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        U_ASSERT(length < POOL_CHUNK_SIZE);
2167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (length >= POOL_CHUNK_SIZE) {
2168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_INTERNAL_PROGRAM_ERROR;
2169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return &EmptyString;
2170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ZSFStringPoolChunk *oldChunk = fChunks;
2172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fChunks = new ZSFStringPoolChunk;
2173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (fChunks == NULL) {
2174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            status = U_MEMORY_ALLOCATION_ERROR;
2175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return &EmptyString;
2176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        fChunks->fNext = oldChunk;
2178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *destString = &fChunks->fStrings[fChunks->fLimit];
2181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_strcpy(destString, s);
2182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fChunks->fLimit += (length + 1);
2183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_put(fHash, destString, destString, &status);
2184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return destString;
2185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//
2189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//  ZSFStringPool::adopt()   Put a string into the hash, but do not copy the string data
2190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//                           into the pool's storage.  Used for strings from resource bundles,
2191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//                           which will perisist for the life of the zone string formatter, and
2192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)//                           therefore can be used directly without copying.
2193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UChar *ZSFStringPool::adopt(const UChar * s, UErrorCode &status) {
2194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *pooledString;
2195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
2196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return &EmptyString;
2197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (s != NULL) {
2199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        pooledString = static_cast<UChar *>(uhash_get(fHash, s));
2200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (pooledString == NULL) {
2201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UChar *ncs = const_cast<UChar *>(s);
2202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uhash_put(fHash, ncs, ncs, &status);
2203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
2204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
2205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return s;
2206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)const UChar *ZSFStringPool::get(const UnicodeString &s, UErrorCode &status) {
2210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString &nonConstStr = const_cast<UnicodeString &>(s);
2211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return this->get(nonConstStr.getTerminatedBuffer(), status);
2212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * freeze().   Close the hash table that maps to the pooled strings.
2216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *             After freezing, the pool can not be searched or added to,
2217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *             but all existing references to pooled strings remain valid.
2218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *
2219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *             The main purpose is to recover the storage used for the hash.
2220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
2221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)void ZSFStringPool::freeze() {
2222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uhash_close(fHash);
2223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    fHash = NULL;
2224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
2225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_END
2227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
2228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif /* #if !UCONFIG_NO_FORMATTING */
2229