]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/dtfmtsym.cpp
ICU-8.11.tar.gz
[apple/icu.git] / icuSources / i18n / dtfmtsym.cpp
CommitLineData
b75a7d8f
A
1/*
2*******************************************************************************
73c04bcf 3* Copyright (C) 1997-2006, International Business Machines Corporation and *
b75a7d8f
A
4* others. All Rights Reserved. *
5*******************************************************************************
6*
7* File DTFMTSYM.CPP
8*
9* Modification History:
10*
11* Date Name Description
12* 02/19/97 aliu Converted from java.
13* 07/21/98 stephen Added getZoneIndex
14* Changed weekdays/short weekdays to be one-based
15* 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix
16* 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars
17* 03/27/00 weiv Keeping resource bundle around!
73c04bcf
A
18* 06/30/05 emmons Added eraNames, narrow month/day, standalone context
19* 10/12/05 emmons Added setters for eraNames, month/day by width/context
b75a7d8f
A
20*******************************************************************************
21*/
22
23#include "unicode/utypes.h"
24
25#if !UCONFIG_NO_FORMATTING
26
27#include "unicode/dtfmtsym.h"
b75a7d8f 28#include "unicode/smpdtfmt.h"
73c04bcf 29#include "cpputils.h"
b75a7d8f
A
30#include "ucln_in.h"
31#include "mutex.h"
32#include "cmemory.h"
33#include "cstring.h"
374ca955
A
34#include "locbased.h"
35#include "gregoimp.h"
73c04bcf
A
36#include "hash.h"
37#include "uresimp.h"
38
b75a7d8f
A
39// *****************************************************************************
40// class DateFormatSymbols
41// *****************************************************************************
42/**
43 * These are static arrays we use only in the case where we have no
44 * resource data.
45 */
46
73c04bcf 47#define PATTERN_CHARS_LEN 26
b75a7d8f
A
48
49/**
50 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
51 * locales use the same these unlocalized pattern characters.
52 */
374ca955 53static const UChar gPatternChars[] = {
73c04bcf 54 // GyMdkHmsSEDFwWahKzYeugAZvcLQq
b75a7d8f 55 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
374ca955 56 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
73c04bcf 57 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0
b75a7d8f
A
58};
59
73c04bcf
A
60/* length of an array */
61#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
62
b75a7d8f
A
63//------------------------------------------------------
64// Strings of last resort. These are only used if we have no resource
65// files. They aren't designed for actual use, just for backup.
66
67// These are the month names and abbreviations of last resort.
68static const UChar gLastResortMonthNames[13][3] =
69{
70 {0x0030, 0x0031, 0x0000}, /* "01" */
71 {0x0030, 0x0032, 0x0000}, /* "02" */
72 {0x0030, 0x0033, 0x0000}, /* "03" */
73 {0x0030, 0x0034, 0x0000}, /* "04" */
74 {0x0030, 0x0035, 0x0000}, /* "05" */
75 {0x0030, 0x0036, 0x0000}, /* "06" */
76 {0x0030, 0x0037, 0x0000}, /* "07" */
77 {0x0030, 0x0038, 0x0000}, /* "08" */
78 {0x0030, 0x0039, 0x0000}, /* "09" */
79 {0x0031, 0x0030, 0x0000}, /* "10" */
80 {0x0031, 0x0031, 0x0000}, /* "11" */
81 {0x0031, 0x0032, 0x0000}, /* "12" */
82 {0x0031, 0x0033, 0x0000} /* "13" */
83};
84
85// These are the weekday names and abbreviations of last resort.
86static const UChar gLastResortDayNames[8][2] =
87{
73c04bcf 88 {0x0030, 0x0000}, /* "0" */
b75a7d8f
A
89 {0x0031, 0x0000}, /* "1" */
90 {0x0032, 0x0000}, /* "2" */
91 {0x0033, 0x0000}, /* "3" */
92 {0x0034, 0x0000}, /* "4" */
93 {0x0035, 0x0000}, /* "5" */
94 {0x0036, 0x0000}, /* "6" */
95 {0x0037, 0x0000} /* "7" */
96};
97
73c04bcf
A
98// These are the quarter names and abbreviations of last resort.
99static const UChar gLastResortQuarters[4][2] =
100{
101 {0x0031, 0x0000}, /* "1" */
102 {0x0032, 0x0000}, /* "2" */
103 {0x0033, 0x0000}, /* "3" */
104 {0x0034, 0x0000}, /* "4" */
105};
106
b75a7d8f
A
107// These are the am/pm and BC/AD markers of last resort.
108static const UChar gLastResortAmPmMarkers[2][3] =
109{
110 {0x0041, 0x004D, 0x0000}, /* "AM" */
111 {0x0050, 0x004D, 0x0000} /* "PM" */
112};
113
114static const UChar gLastResortEras[2][3] =
115{
116 {0x0042, 0x0043, 0x0000}, /* "BC" */
117 {0x0041, 0x0044, 0x0000} /* "AD" */
118};
119
120
121// These are the zone strings of last resort.
73c04bcf 122static const UChar gLastResortZoneStrings[7][4] =
b75a7d8f
A
123{
124 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
125 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
126 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
127 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
73c04bcf
A
128 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
129 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */
b75a7d8f
A
130 {0x0047, 0x004D, 0x0054, 0x0000} /* "GMT" */
131};
132
73c04bcf
A
133/* Sizes for the last resort string arrays */
134typedef enum LastResortSize {
135 kMonthNum = 13,
136 kMonthLen = 3,
137
138 kDayNum = 8,
139 kDayLen = 2,
140
141 kAmPmNum = 2,
142 kAmPmLen = 3,
143
144 kQuarterNum = 4,
145 kQuarterLen = 2,
146
147 kEraNum = 2,
148 kEraLen = 3,
149
150 kZoneNum = 5,
151 kZoneLen = 4
152} LastResortSize;
153
b75a7d8f
A
154U_NAMESPACE_BEGIN
155
374ca955 156UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
b75a7d8f
A
157
158/**
159 * These are the tags we expect to see in normal resource bundle files associated
374ca955 160 * with a locale and calendar
b75a7d8f 161 */
73c04bcf
A
162static const char gErasTag[]="eras";
163static const char gAbbreviatedTag[] = "abbreviated";
164static const char gMonthNamesTag[]="monthNames";
165static const char gDayNamesTag[]="dayNames";
166static const char gNamesWideTag[]="wide";
167static const char gNamesAbbrTag[]="abbreviated";
168static const char gNamesNarrowTag[]="narrow";
169static const char gNamesStandaloneTag[]="stand-alone";
170static const char gAmPmMarkersTag[]="AmPmMarkers";
171static const char gQuartersTag[]="quarters";
b75a7d8f
A
172
173/**
174 * These are the tags we expect to see in time zone data resource bundle files
175 * associated with a locale.
176 */
73c04bcf
A
177static const char gZoneStringsTag[]="zoneStrings";
178static const char gLocalPatternCharsTag[]="localPatternChars";
179
180static UMTX LOCK;
181
182/*
183 * Keep this variable in synch with max length of display strings
184 */
185#define UTZ_MAX_DISPLAY_STRINGS_LENGTH 7
186#define UTZ_SHORT_GENERIC "sg"
187#define UTZ_SHORT_STANDARD "ss"
188#define UTZ_SHORT_DAYLIGHT "sd"
189#define UTZ_LONG_GENERIC "lg"
190#define UTZ_LONG_STANDARD "ls"
191#define UTZ_LONG_DAYLIGHT "ld"
192#define UTZ_EXEMPLAR_CITY "ec"
b75a7d8f
A
193
194/**
195 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
196 * Work around this.
197 */
198static inline UnicodeString* newUnicodeStringArray(size_t count) {
199 return new UnicodeString[count ? count : 1];
200}
201
73c04bcf
A
202U_CDECL_BEGIN
203static void deleteUnicodeStringArray(void* obj) {
204 delete[] (UnicodeString*)obj;
205}
206U_CDECL_END
207
b75a7d8f
A
208//------------------------------------------------------
209
210DateFormatSymbols::DateFormatSymbols(const Locale& locale,
211 UErrorCode& status)
212 : UObject()
213{
214 initializeData(locale, NULL, status);
215}
216
217DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
218 : UObject()
219{
220 initializeData(Locale::getDefault(), NULL, status, TRUE);
221}
222
223
224DateFormatSymbols::DateFormatSymbols(const Locale& locale,
225 const char *type,
226 UErrorCode& status)
227 : UObject()
228{
229 initializeData(locale, type, status);
230}
231
232DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
233 : UObject()
234{
235 initializeData(Locale::getDefault(), type, status, TRUE);
236}
237
238DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
239 : UObject(other)
240{
241 copyData(other);
242}
243
244void
245DateFormatSymbols::assignArray(UnicodeString*& dstArray,
246 int32_t& dstCount,
247 const UnicodeString* srcArray,
248 int32_t srcCount)
249{
250 // assignArray() is only called by copyData(), which in turn implements the
251 // copy constructor and the assignment operator.
252 // All strings in a DateFormatSymbols object are created in one of the following
253 // three ways that all allow to safely use UnicodeString::fastCopyFrom():
254 // - readonly-aliases from resource bundles
255 // - readonly-aliases or allocated strings from constants
256 // - safely cloned strings (with owned buffers) from setXYZ() functions
257 //
258 // Note that this is true for as long as DateFormatSymbols can be constructed
259 // only from a locale bundle or set via the cloning API,
260 // *and* for as long as all the strings are in *private* fields, preventing
261 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
262 dstCount = srcCount;
263 dstArray = newUnicodeStringArray(srcCount);
264 if(dstArray != NULL) {
265 int32_t i;
266 for(i=0; i<srcCount; ++i) {
267 dstArray[i].fastCopyFrom(srcArray[i]);
268 }
269 }
270}
271
272/**
273 * Create a copy, in fZoneStrings, of the given zone strings array. The
274 * member variables fZoneStringsRowCount and fZoneStringsColCount should
275 * be set already by the caller.
276 */
277void
278DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
279{
280 int32_t row, col;
281
282 fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
283 for (row=0; row<fZoneStringsRowCount; ++row)
284 {
285 fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
286 for (col=0; col<fZoneStringsColCount; ++col) {
287 // fastCopyFrom() - see assignArray comments
288 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
289 }
290 }
291}
292
293/**
294 * Copy all of the other's data to this.
295 */
296void
297DateFormatSymbols::copyData(const DateFormatSymbols& other) {
298 assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
73c04bcf 299 assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
b75a7d8f
A
300 assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
301 assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
73c04bcf
A
302 assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
303 assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
304 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
305 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
b75a7d8f
A
306 assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
307 assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
73c04bcf
A
308 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
309 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
310 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
311 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
b75a7d8f 312 assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
73c04bcf
A
313 assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
314 assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
315 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
316 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
317 // the zoneStrings data is initialized on demand
318 //fZoneStringsRowCount = other.fZoneStringsRowCount;
319 //fZoneStringsColCount = other.fZoneStringsColCount;
320 //createZoneStrings((const UnicodeString**)other.fZoneStrings);
321 // initialize on demand
322 fZoneStringsHash = NULL;
323 fZoneIDEnumeration = NULL;
324 fZoneStrings = NULL;
325 fZoneStringsColCount = 0;
326 fZoneStringsRowCount = 0;
327 fResourceBundle = NULL;
328 if(other.fZoneStringsHash!=NULL){
329 fZoneStringsHash = createZoneStringsHash(other.fZoneStringsHash);
330 fZoneIDEnumeration = other.fZoneIDEnumeration->clone();
331 }else{
332 UErrorCode status =U_ZERO_ERROR;
333 fResourceBundle = ures_clone(other.fResourceBundle, &status);
334 // TODO: what should be done in case of error?
335 }
b75a7d8f
A
336
337 // fastCopyFrom() - see assignArray comments
338 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
339}
340
341/**
342 * Assignment operator.
343 */
344DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
345{
346 dispose();
347 copyData(other);
348
349 return *this;
350}
351
352DateFormatSymbols::~DateFormatSymbols()
353{
354 dispose();
355}
356
357void DateFormatSymbols::dispose()
358{
73c04bcf
A
359 if (fEras) delete[] fEras;
360 if (fEraNames) delete[] fEraNames;
361 if (fMonths) delete[] fMonths;
362 if (fShortMonths) delete[] fShortMonths;
363 if (fNarrowMonths) delete[] fNarrowMonths;
364 if (fStandaloneMonths) delete[] fStandaloneMonths;
365 if (fStandaloneShortMonths) delete[] fStandaloneShortMonths;
366 if (fStandaloneNarrowMonths) delete[] fStandaloneNarrowMonths;
367 if (fWeekdays) delete[] fWeekdays;
368 if (fShortWeekdays) delete[] fShortWeekdays;
369 if (fNarrowWeekdays) delete[] fNarrowWeekdays;
370 if (fStandaloneWeekdays) delete[] fStandaloneWeekdays;
371 if (fStandaloneShortWeekdays) delete[] fStandaloneShortWeekdays;
372 if (fStandaloneNarrowWeekdays) delete[] fStandaloneNarrowWeekdays;
373 if (fAmPms) delete[] fAmPms;
374 if (fQuarters) delete[] fQuarters;
375 if (fShortQuarters) delete[] fShortQuarters;
376 if (fStandaloneQuarters) delete[] fStandaloneQuarters;
377 if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters;
b75a7d8f
A
378
379 disposeZoneStrings();
380}
381
382void DateFormatSymbols::disposeZoneStrings()
383{
384 if (fZoneStrings) {
385 for (int32_t row=0; row<fZoneStringsRowCount; ++row)
386 delete[] fZoneStrings[row];
387 uprv_free(fZoneStrings);
73c04bcf
A
388 }
389 if(fZoneStringsHash){
390 delete fZoneStringsHash;
391 fZoneStringsHash = NULL;
392 }
393 if(fZoneIDEnumeration){
394 delete fZoneIDEnumeration;
395 fZoneIDEnumeration = NULL;
b75a7d8f 396 }
73c04bcf
A
397 ures_close(fResourceBundle);
398 fResourceBundle = NULL;
b75a7d8f
A
399}
400
401UBool
402DateFormatSymbols::arrayCompare(const UnicodeString* array1,
403 const UnicodeString* array2,
404 int32_t count)
405{
406 if (array1 == array2) return TRUE;
407 while (count>0)
408 {
409 --count;
410 if (array1[count] != array2[count]) return FALSE;
411 }
412 return TRUE;
413}
414
415UBool
416DateFormatSymbols::operator==(const DateFormatSymbols& other) const
417{
418 // First do cheap comparisons
419 if (this == &other) {
420 return TRUE;
421 }
422 if (fErasCount == other.fErasCount &&
73c04bcf 423 fEraNamesCount == other.fEraNamesCount &&
b75a7d8f
A
424 fMonthsCount == other.fMonthsCount &&
425 fShortMonthsCount == other.fShortMonthsCount &&
73c04bcf
A
426 fNarrowMonthsCount == other.fNarrowMonthsCount &&
427 fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
428 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
429 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
b75a7d8f
A
430 fWeekdaysCount == other.fWeekdaysCount &&
431 fShortWeekdaysCount == other.fShortWeekdaysCount &&
73c04bcf
A
432 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
433 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
434 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
435 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
b75a7d8f 436 fAmPmsCount == other.fAmPmsCount &&
73c04bcf
A
437 fQuartersCount == other.fQuartersCount &&
438 fShortQuartersCount == other.fShortQuartersCount &&
439 fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
440 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount)
b75a7d8f
A
441 {
442 // Now compare the arrays themselves
443 if (arrayCompare(fEras, other.fEras, fErasCount) &&
73c04bcf 444 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
b75a7d8f
A
445 arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
446 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
73c04bcf
A
447 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
448 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
449 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
450 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
b75a7d8f
A
451 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
452 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
73c04bcf
A
453 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
454 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
455 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
456 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
457 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
458 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
459 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
460 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
461 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount))
b75a7d8f 462 {
73c04bcf
A
463
464 if(fZoneStringsHash == NULL || other.fZoneStringsHash == NULL){
465 // fZoneStringsHash is not initialized compare the resource bundles
466 if(ures_equal(fResourceBundle, other.fResourceBundle)== FALSE){
467 return FALSE;
468 }
469 }else{
470 if(fZoneStringsHash->equals(*other.fZoneStringsHash) == FALSE){
b75a7d8f 471 return FALSE;
73c04bcf
A
472 }
473 // we always make sure that we update the enumeration when the hash is
474 // updated. So we can be sure that once we compare the hashes the
475 // enumerations are also equal
b75a7d8f 476 }
73c04bcf
A
477 // since fZoneStrings data member is deprecated .. and may not be initialized
478 // so don't compare them
b75a7d8f
A
479 return TRUE;
480 }
481 }
482 return FALSE;
483}
484
485//------------------------------------------------------
486
487const UnicodeString*
488DateFormatSymbols::getEras(int32_t &count) const
489{
490 count = fErasCount;
491 return fEras;
492}
493
73c04bcf
A
494const UnicodeString*
495DateFormatSymbols::getEraNames(int32_t &count) const
496{
497 count = fEraNamesCount;
498 return fEraNames;
499}
500
b75a7d8f
A
501const UnicodeString*
502DateFormatSymbols::getMonths(int32_t &count) const
503{
504 count = fMonthsCount;
505 return fMonths;
506}
507
508const UnicodeString*
509DateFormatSymbols::getShortMonths(int32_t &count) const
510{
511 count = fShortMonthsCount;
512 return fShortMonths;
513}
514
73c04bcf
A
515const UnicodeString*
516DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
517{
518 UnicodeString *returnValue = NULL;
519
520 switch (context) {
521 case FORMAT :
522 switch(width) {
523 case WIDE :
524 count = fMonthsCount;
525 returnValue = fMonths;
526 break;
527 case ABBREVIATED :
528 count = fShortMonthsCount;
529 returnValue = fShortMonths;
530 break;
531 case NARROW :
532 count = fNarrowMonthsCount;
533 returnValue = fNarrowMonths;
534 break;
535 case DT_WIDTH_COUNT :
536 break;
537 }
538 break;
539 case STANDALONE :
540 switch(width) {
541 case WIDE :
542 count = fStandaloneMonthsCount;
543 returnValue = fStandaloneMonths;
544 break;
545 case ABBREVIATED :
546 count = fStandaloneShortMonthsCount;
547 returnValue = fStandaloneShortMonths;
548 break;
549 case NARROW :
550 count = fStandaloneNarrowMonthsCount;
551 returnValue = fStandaloneNarrowMonths;
552 break;
553 case DT_WIDTH_COUNT :
554 break;
555 }
556 break;
557 case DT_CONTEXT_COUNT :
558 break;
559 }
560 return returnValue;
561}
562
b75a7d8f
A
563const UnicodeString*
564DateFormatSymbols::getWeekdays(int32_t &count) const
565{
566 count = fWeekdaysCount;
567 return fWeekdays;
568}
569
570const UnicodeString*
571DateFormatSymbols::getShortWeekdays(int32_t &count) const
572{
573 count = fShortWeekdaysCount;
574 return fShortWeekdays;
575}
576
73c04bcf
A
577const UnicodeString*
578DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
579{
580 UnicodeString *returnValue = NULL;
581 switch (context) {
582 case FORMAT :
583 switch(width) {
584 case WIDE :
585 count = fWeekdaysCount;
586 returnValue = fWeekdays;
587 break;
588 case ABBREVIATED :
589 count = fShortWeekdaysCount;
590 returnValue = fShortWeekdays;
591 break;
592 case NARROW :
593 count = fNarrowWeekdaysCount;
594 returnValue = fNarrowWeekdays;
595 break;
596 case DT_WIDTH_COUNT :
597 break;
598 }
599 break;
600 case STANDALONE :
601 switch(width) {
602 case WIDE :
603 count = fStandaloneWeekdaysCount;
604 returnValue = fStandaloneWeekdays;
605 break;
606 case ABBREVIATED :
607 count = fStandaloneShortWeekdaysCount;
608 returnValue = fStandaloneShortWeekdays;
609 break;
610 case NARROW :
611 count = fStandaloneNarrowWeekdaysCount;
612 returnValue = fStandaloneNarrowWeekdays;
613 break;
614 case DT_WIDTH_COUNT :
615 break;
616 }
617 break;
618 case DT_CONTEXT_COUNT :
619 break;
620 }
621 return returnValue;
622}
623
624const UnicodeString*
625DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
626{
627 UnicodeString *returnValue = NULL;
628
629 switch (context) {
630 case FORMAT :
631 switch(width) {
632 case WIDE :
633 count = fQuartersCount;
634 returnValue = fQuarters;
635 break;
636 case ABBREVIATED :
637 count = fShortQuartersCount;
638 returnValue = fShortQuarters;
639 break;
640 case NARROW :
641 count = 0;
642 returnValue = NULL;
643 break;
644 case DT_WIDTH_COUNT :
645 break;
646 }
647 break;
648 case STANDALONE :
649 switch(width) {
650 case WIDE :
651 count = fStandaloneQuartersCount;
652 returnValue = fStandaloneQuarters;
653 break;
654 case ABBREVIATED :
655 count = fStandaloneShortQuartersCount;
656 returnValue = fStandaloneShortQuarters;
657 break;
658 case NARROW :
659 count = 0;
660 returnValue = NULL;
661 break;
662 case DT_WIDTH_COUNT :
663 break;
664 }
665 break;
666 case DT_CONTEXT_COUNT :
667 break;
668 }
669 return returnValue;
670}
671
b75a7d8f
A
672const UnicodeString*
673DateFormatSymbols::getAmPmStrings(int32_t &count) const
674{
675 count = fAmPmsCount;
676 return fAmPms;
677}
678
679//------------------------------------------------------
680
681void
682DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
683{
684 // delete the old list if we own it
73c04bcf
A
685 if (fEras)
686 delete[] fEras;
b75a7d8f
A
687
688 // we always own the new list, which we create here (we duplicate rather
689 // than adopting the list passed in)
690 fEras = newUnicodeStringArray(count);
691 uprv_arrayCopy(erasArray,fEras, count);
692 fErasCount = count;
693}
694
73c04bcf
A
695void
696DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
697{
698 // delete the old list if we own it
699 if (fEraNames)
700 delete[] fEraNames;
701
702 // we always own the new list, which we create here (we duplicate rather
703 // than adopting the list passed in)
704 fEraNames = newUnicodeStringArray(count);
705 uprv_arrayCopy(eraNamesArray,fEraNames, count);
706 fEraNamesCount = count;
707}
708
b75a7d8f
A
709void
710DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
711{
712 // delete the old list if we own it
73c04bcf
A
713 if (fMonths)
714 delete[] fMonths;
b75a7d8f
A
715
716 // we always own the new list, which we create here (we duplicate rather
717 // than adopting the list passed in)
718 fMonths = newUnicodeStringArray(count);
719 uprv_arrayCopy( monthsArray,fMonths,count);
720 fMonthsCount = count;
721}
722
723void
724DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
725{
726 // delete the old list if we own it
73c04bcf
A
727 if (fShortMonths)
728 delete[] fShortMonths;
b75a7d8f
A
729
730 // we always own the new list, which we create here (we duplicate rather
731 // than adopting the list passed in)
732 fShortMonths = newUnicodeStringArray(count);
733 uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
734 fShortMonthsCount = count;
735}
736
73c04bcf
A
737void
738DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
739{
740 // delete the old list if we own it
741 // we always own the new list, which we create here (we duplicate rather
742 // than adopting the list passed in)
743
744 switch (context) {
745 case FORMAT :
746 switch (width) {
747 case WIDE :
748 if (fMonths)
749 delete[] fMonths;
750 fMonths = newUnicodeStringArray(count);
751 uprv_arrayCopy( monthsArray,fMonths,count);
752 fMonthsCount = count;
753 break;
754 case ABBREVIATED :
755 if (fShortMonths)
756 delete[] fShortMonths;
757 fShortMonths = newUnicodeStringArray(count);
758 uprv_arrayCopy( monthsArray,fShortMonths,count);
759 fShortMonthsCount = count;
760 break;
761 case NARROW :
762 if (fNarrowMonths)
763 delete[] fNarrowMonths;
764 fNarrowMonths = newUnicodeStringArray(count);
765 uprv_arrayCopy( monthsArray,fNarrowMonths,count);
766 fNarrowMonthsCount = count;
767 break;
768 case DT_WIDTH_COUNT :
769 break;
770 }
771 break;
772 case STANDALONE :
773 switch (width) {
774 case WIDE :
775 if (fStandaloneMonths)
776 delete[] fStandaloneMonths;
777 fStandaloneMonths = newUnicodeStringArray(count);
778 uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
779 fStandaloneMonthsCount = count;
780 break;
781 case ABBREVIATED :
782 if (fStandaloneShortMonths)
783 delete[] fStandaloneShortMonths;
784 fStandaloneShortMonths = newUnicodeStringArray(count);
785 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
786 fStandaloneShortMonthsCount = count;
787 break;
788 case NARROW :
789 if (fStandaloneNarrowMonths)
790 delete[] fStandaloneNarrowMonths;
791 fStandaloneNarrowMonths = newUnicodeStringArray(count);
792 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
793 fStandaloneNarrowMonthsCount = count;
794 break;
795 case DT_WIDTH_COUNT :
796 break;
797 }
798 break;
799 case DT_CONTEXT_COUNT :
800 break;
801 }
802}
803
b75a7d8f
A
804void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
805{
806 // delete the old list if we own it
73c04bcf
A
807 if (fWeekdays)
808 delete[] fWeekdays;
b75a7d8f
A
809
810 // we always own the new list, which we create here (we duplicate rather
811 // than adopting the list passed in)
812 fWeekdays = newUnicodeStringArray(count);
813 uprv_arrayCopy(weekdaysArray,fWeekdays,count);
814 fWeekdaysCount = count;
815}
816
817void
818DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
819{
820 // delete the old list if we own it
73c04bcf
A
821 if (fShortWeekdays)
822 delete[] fShortWeekdays;
b75a7d8f
A
823
824 // we always own the new list, which we create here (we duplicate rather
825 // than adopting the list passed in)
826 fShortWeekdays = newUnicodeStringArray(count);
73c04bcf 827 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
b75a7d8f
A
828 fShortWeekdaysCount = count;
829}
830
73c04bcf
A
831void
832DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
833{
834 // delete the old list if we own it
835 // we always own the new list, which we create here (we duplicate rather
836 // than adopting the list passed in)
837
838 switch (context) {
839 case FORMAT :
840 switch (width) {
841 case WIDE :
842 if (fWeekdays)
843 delete[] fWeekdays;
844 fWeekdays = newUnicodeStringArray(count);
845 uprv_arrayCopy(weekdaysArray, fWeekdays, count);
846 fWeekdaysCount = count;
847 break;
848 case ABBREVIATED :
849 if (fShortWeekdays)
850 delete[] fShortWeekdays;
851 fShortWeekdays = newUnicodeStringArray(count);
852 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
853 fShortWeekdaysCount = count;
854 break;
855 case NARROW :
856 if (fNarrowWeekdays)
857 delete[] fNarrowWeekdays;
858 fNarrowWeekdays = newUnicodeStringArray(count);
859 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
860 fNarrowWeekdaysCount = count;
861 break;
862 case DT_WIDTH_COUNT :
863 break;
864 }
865 break;
866 case STANDALONE :
867 switch (width) {
868 case WIDE :
869 if (fStandaloneWeekdays)
870 delete[] fStandaloneWeekdays;
871 fStandaloneWeekdays = newUnicodeStringArray(count);
872 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
873 fStandaloneWeekdaysCount = count;
874 break;
875 case ABBREVIATED :
876 if (fStandaloneShortWeekdays)
877 delete[] fStandaloneShortWeekdays;
878 fStandaloneShortWeekdays = newUnicodeStringArray(count);
879 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
880 fStandaloneShortWeekdaysCount = count;
881 break;
882 case NARROW :
883 if (fStandaloneNarrowWeekdays)
884 delete[] fStandaloneNarrowWeekdays;
885 fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
886 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
887 fStandaloneNarrowWeekdaysCount = count;
888 break;
889 case DT_WIDTH_COUNT :
890 break;
891 }
892 break;
893 case DT_CONTEXT_COUNT :
894 break;
895 }
896}
897
898void
899DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
900{
901 // delete the old list if we own it
902 // we always own the new list, which we create here (we duplicate rather
903 // than adopting the list passed in)
904
905 switch (context) {
906 case FORMAT :
907 switch (width) {
908 case WIDE :
909 if (fQuarters)
910 delete[] fQuarters;
911 fQuarters = newUnicodeStringArray(count);
912 uprv_arrayCopy( quartersArray,fQuarters,count);
913 fQuartersCount = count;
914 break;
915 case ABBREVIATED :
916 if (fShortQuarters)
917 delete[] fShortQuarters;
918 fShortQuarters = newUnicodeStringArray(count);
919 uprv_arrayCopy( quartersArray,fShortQuarters,count);
920 fShortQuartersCount = count;
921 break;
922 case NARROW :
923 /*
924 if (fNarrowQuarters)
925 delete[] fNarrowQuarters;
926 fNarrowQuarters = newUnicodeStringArray(count);
927 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
928 fNarrowQuartersCount = count;
929 */
930 break;
931 case DT_WIDTH_COUNT :
932 break;
933 }
934 break;
935 case STANDALONE :
936 switch (width) {
937 case WIDE :
938 if (fStandaloneQuarters)
939 delete[] fStandaloneQuarters;
940 fStandaloneQuarters = newUnicodeStringArray(count);
941 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
942 fStandaloneQuartersCount = count;
943 break;
944 case ABBREVIATED :
945 if (fStandaloneShortQuarters)
946 delete[] fStandaloneShortQuarters;
947 fStandaloneShortQuarters = newUnicodeStringArray(count);
948 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
949 fStandaloneShortQuartersCount = count;
950 break;
951 case NARROW :
952 /*
953 if (fStandaloneNarrowQuarters)
954 delete[] fStandaloneNarrowQuarters;
955 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
956 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
957 fStandaloneNarrowQuartersCount = count;
958 */
959 break;
960 case DT_WIDTH_COUNT :
961 break;
962 }
963 break;
964 case DT_CONTEXT_COUNT :
965 break;
966 }
967}
968
b75a7d8f
A
969void
970DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
971{
972 // delete the old list if we own it
973 if (fAmPms) delete[] fAmPms;
974
975 // we always own the new list, which we create here (we duplicate rather
976 // than adopting the list passed in)
977 fAmPms = newUnicodeStringArray(count);
978 uprv_arrayCopy(amPmsArray,fAmPms,count);
979 fAmPmsCount = count;
980}
981
982//------------------------------------------------------
983
984const UnicodeString**
985DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
986{
73c04bcf
A
987 umtx_lock(&LOCK);
988 UErrorCode status = U_ZERO_ERROR;
989 if(fZoneStrings==NULL){
990 // cast away const to get around the problem for lazy initialization
991 ((DateFormatSymbols*)this)->initZoneStringsArray(status);
992 if(U_FAILURE(status)){
993 return NULL;
994 }
995 }
b75a7d8f
A
996 rowCount = fZoneStringsRowCount;
997 columnCount = fZoneStringsColCount;
73c04bcf 998 umtx_unlock(&LOCK);
b75a7d8f
A
999 return (const UnicodeString**)fZoneStrings; // Compiler requires cast
1000}
1001
1002void
1003DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1004{
1005 // since deleting a 2-d array is a pain in the butt, we offload that task to
1006 // a separate function
1007 disposeZoneStrings();
73c04bcf 1008 UErrorCode status = U_ZERO_ERROR;
b75a7d8f
A
1009 // we always own the new list, which we create here (we duplicate rather
1010 // than adopting the list passed in)
1011 fZoneStringsRowCount = rowCount;
1012 fZoneStringsColCount = columnCount;
1013 createZoneStrings((const UnicodeString**)strings);
73c04bcf 1014 initZoneStrings((const UnicodeString**)strings, rowCount,columnCount, status);
b75a7d8f
A
1015}
1016
1017//------------------------------------------------------
1018
374ca955 1019const UChar * U_EXPORT2
b75a7d8f
A
1020DateFormatSymbols::getPatternUChars(void)
1021{
1022 return gPatternChars;
1023}
1024
1025//------------------------------------------------------
1026
1027UnicodeString&
1028DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1029{
1030 // fastCopyFrom() - see assignArray comments
1031 return result.fastCopyFrom(fLocalPatternChars);
1032}
1033
1034//------------------------------------------------------
1035
1036void
1037DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1038{
1039 fLocalPatternChars = newLocalPatternChars;
1040}
1041
1042//------------------------------------------------------
1043
73c04bcf
A
1044static void
1045initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) {
b75a7d8f 1046 if (U_SUCCESS(status)) {
374ca955
A
1047 int32_t strLen = 0;
1048 length = ures_getSize(data);
b75a7d8f
A
1049 *field = newUnicodeStringArray(length);
1050 if (*field) {
1051 for(int32_t i = 0; i<length; i++) {
374ca955
A
1052 const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status);
1053 // setTo() - see assignArray comments
1054 (*(field)+i)->setTo(TRUE, resStr, strLen);
b75a7d8f
A
1055 }
1056 }
1057 else {
1058 length = 0;
1059 status = U_MEMORY_ALLOCATION_ERROR;
1060 }
1061 }
1062}
1063
73c04bcf
A
1064static void
1065initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
b75a7d8f
A
1066 if (U_SUCCESS(status)) {
1067 length = numStr;
1068 *field = newUnicodeStringArray((size_t)numStr);
1069 if (*field) {
1070 for(int32_t i = 0; i<length; i++) {
1071 // readonly aliases - all "data" strings are constant
1072 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1073 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1074 }
1075 }
1076 else {
1077 length = 0;
1078 status = U_MEMORY_ALLOCATION_ERROR;
1079 }
1080 }
1081}
1082
b75a7d8f
A
1083void
1084DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
1085{
1086 int32_t i;
374ca955
A
1087 int32_t len = 0;
1088 const UChar *resStr;
b75a7d8f
A
1089 /* In case something goes wrong, initialize all of the data to NULL. */
1090 fEras = NULL;
1091 fErasCount = 0;
73c04bcf
A
1092 fEraNames = NULL;
1093 fEraNamesCount = 0;
b75a7d8f
A
1094 fMonths = NULL;
1095 fMonthsCount=0;
1096 fShortMonths = NULL;
1097 fShortMonthsCount=0;
73c04bcf
A
1098 fNarrowMonths = NULL;
1099 fNarrowMonthsCount=0;
1100 fStandaloneMonths = NULL;
1101 fStandaloneMonthsCount=0;
1102 fStandaloneShortMonths = NULL;
1103 fStandaloneShortMonthsCount=0;
1104 fStandaloneNarrowMonths = NULL;
1105 fStandaloneNarrowMonthsCount=0;
b75a7d8f
A
1106 fWeekdays = NULL;
1107 fWeekdaysCount=0;
1108 fShortWeekdays = NULL;
1109 fShortWeekdaysCount=0;
73c04bcf
A
1110 fNarrowWeekdays = NULL;
1111 fNarrowWeekdaysCount=0;
1112 fStandaloneWeekdays = NULL;
1113 fStandaloneWeekdaysCount=0;
1114 fStandaloneShortWeekdays = NULL;
1115 fStandaloneShortWeekdaysCount=0;
1116 fStandaloneNarrowWeekdays = NULL;
1117 fStandaloneNarrowWeekdaysCount=0;
b75a7d8f
A
1118 fAmPms = NULL;
1119 fAmPmsCount=0;
73c04bcf
A
1120 fQuarters = NULL;
1121 fQuartersCount = 0;
1122 fShortQuarters = NULL;
1123 fShortQuartersCount = 0;
1124 fStandaloneQuarters = NULL;
1125 fStandaloneQuartersCount = 0;
1126 fStandaloneShortQuarters = NULL;
1127 fStandaloneShortQuartersCount = 0;
b75a7d8f
A
1128 fZoneStringsRowCount = 0;
1129 fZoneStringsColCount = 0;
1130 fZoneStrings = NULL;
73c04bcf
A
1131 fZoneStringsHash = NULL;
1132 fZoneIDEnumeration = NULL;
1133 fResourceBundle = NULL;
1134
1135
b75a7d8f
A
1136 if (U_FAILURE(status)) return;
1137
1138 /**
1139 * Retrieve the string arrays we need from the resource bundle file.
1140 * We cast away const here, but that's okay; we won't delete any of
1141 * these.
1142 */
374ca955 1143 CalendarData calData(locale, type, status);
73c04bcf 1144 fResourceBundle = ures_open((char*)0, locale.getName(), &status);
374ca955
A
1145
1146 // load the first data item
1147 UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
1148 UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gAbbreviatedTag, NULL, &status);
73c04bcf
A
1149 UErrorCode oldStatus = status;
1150 UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status);
1151 if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3
1152 status = oldStatus;
1153 eraNames = ures_getByKeyWithFallback(erasMain, gAbbreviatedTag, NULL, &status);
1154 }
1155
374ca955
A
1156 UResourceBundle *lsweekdaysData = NULL; // Data closed by calData
1157 UResourceBundle *weekdaysData = NULL; // Data closed by calData
73c04bcf
A
1158 UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData
1159 UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData
1160 UResourceBundle *standaloneShortWeekdaysData = NULL; // Data closed by calData
1161 UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData
1162
374ca955 1163 U_LOCALE_BASED(locBased, *this);
b75a7d8f
A
1164 if (U_FAILURE(status))
1165 {
1166 if (useLastResortData)
1167 {
1168 // Handle the case in which there is no resource data present.
1169 // We don't have to generate usable patterns in this situation;
1170 // we just need to produce something that will be semi-intelligible
1171 // in most locales.
1172
1173 status = U_USING_FALLBACK_WARNING;
1174
1175 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
73c04bcf 1176 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
b75a7d8f
A
1177 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1178 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
73c04bcf
A
1179 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1180 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1181 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1182 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
b75a7d8f
A
1183 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1184 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
73c04bcf
A
1185 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1186 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1187 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1188 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
b75a7d8f 1189 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
73c04bcf
A
1190 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1191 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1192 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1193 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
b75a7d8f
A
1194 fLocalPatternChars = gPatternChars;
1195 }
374ca955 1196 goto cleanup;
b75a7d8f
A
1197 }
1198
1199 // if we make it to here, the resource data is cool, and we can get everything out
1200 // of it that we need except for the time-zone and localized-pattern data, which
374ca955
A
1201 // are stored in a separate file
1202 locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status),
1203 ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status));
73c04bcf 1204
374ca955 1205 initField(&fEras, fErasCount, eras, status);
73c04bcf
A
1206 initField(&fEraNames, fEraNamesCount, eraNames, status);
1207
374ca955
A
1208 initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1209 initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
73c04bcf
A
1210
1211 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1212 if(status == U_MISSING_RESOURCE_ERROR) {
1213 status = U_ZERO_ERROR;
1214 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1215 }
1216 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */
1217 status = U_ZERO_ERROR;
1218 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1219 }
1220
1221 initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1222 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */
1223 status = U_ZERO_ERROR;
1224 initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1225 }
1226 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1227 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/abbreviated not available, use format/abbreviated */
1228 status = U_ZERO_ERROR;
1229 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1230 }
1231 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1232 if ( status == U_MISSING_RESOURCE_ERROR ) { /* if standalone/narrow not availabe, try format/narrow */
1233 status = U_ZERO_ERROR;
1234 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1235 if ( status == U_MISSING_RESOURCE_ERROR ) { /* if still not there, use format/abbreviated */
1236 status = U_ZERO_ERROR;
1237 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1238 }
1239 }
374ca955
A
1240 initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status);
1241
73c04bcf
A
1242 initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1243 initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1244
1245 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1246 if(status == U_MISSING_RESOURCE_ERROR) {
1247 status = U_ZERO_ERROR;
1248 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1249 }
1250
1251 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1252 if(status == U_MISSING_RESOURCE_ERROR) {
1253 status = U_ZERO_ERROR;
1254 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1255 }
1256
374ca955 1257 // fastCopyFrom()/setTo() - see assignArray comments
73c04bcf 1258 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
374ca955
A
1259 fLocalPatternChars.setTo(TRUE, resStr, len);
1260 // If the locale data does not include new pattern chars, use the defaults
1261 // TODO: Consider making this an error, since this may add conflicting characters.
1262 if (len < PATTERN_CHARS_LEN) {
1263 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
1264 }
b75a7d8f 1265
b75a7d8f 1266 // {sfb} fixed to handle 1-based weekdays
374ca955
A
1267 weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1268 fWeekdaysCount = ures_getSize(weekdaysData);
b75a7d8f 1269 fWeekdays = new UnicodeString[fWeekdaysCount+1];
73c04bcf
A
1270 /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/
1271 if (fWeekdays == NULL) {
b75a7d8f 1272 status = U_MEMORY_ALLOCATION_ERROR;
374ca955 1273 goto cleanup;
b75a7d8f
A
1274 }
1275 // leave fWeekdays[0] empty
1276 for(i = 0; i<fWeekdaysCount; i++) {
374ca955
A
1277 resStr = ures_getStringByIndex(weekdaysData, i, &len, &status);
1278 // setTo() - see assignArray comments
1279 fWeekdays[i+1].setTo(TRUE, resStr, len);
b75a7d8f 1280 }
374ca955 1281 fWeekdaysCount++;
b75a7d8f 1282
374ca955
A
1283 lsweekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1284 fShortWeekdaysCount = ures_getSize(lsweekdaysData);
b75a7d8f
A
1285 fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1];
1286 /* test for NULL */
1287 if (fShortWeekdays == 0) {
1288 status = U_MEMORY_ALLOCATION_ERROR;
374ca955 1289 goto cleanup;
b75a7d8f
A
1290 }
1291 // leave fShortWeekdays[0] empty
1292 for(i = 0; i<fShortWeekdaysCount; i++) {
374ca955
A
1293 resStr = ures_getStringByIndex(lsweekdaysData, i, &len, &status);
1294 // setTo() - see assignArray comments
1295 fShortWeekdays[i+1].setTo(TRUE, resStr, len);
b75a7d8f 1296 }
374ca955 1297 fShortWeekdaysCount++;
73c04bcf
A
1298
1299 narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1300 if(status == U_MISSING_RESOURCE_ERROR) {
1301 status = U_ZERO_ERROR;
1302 narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1303 }
1304 if ( status == U_MISSING_RESOURCE_ERROR ) {
1305 status = U_ZERO_ERROR;
1306 narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1307 }
1308 fNarrowWeekdaysCount = ures_getSize(narrowWeekdaysData);
1309 fNarrowWeekdays = new UnicodeString[fNarrowWeekdaysCount+1];
1310 /* test for NULL */
1311 if (fNarrowWeekdays == 0) {
1312 status = U_MEMORY_ALLOCATION_ERROR;
1313 goto cleanup;
1314 }
1315 // leave fNarrowWeekdays[0] empty
1316 for(i = 0; i<fNarrowWeekdaysCount; i++) {
1317 resStr = ures_getStringByIndex(narrowWeekdaysData, i, &len, &status);
1318 // setTo() - see assignArray comments
1319 fNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1320 }
1321 fNarrowWeekdaysCount++;
1322
1323 standaloneWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status);
1324 if ( status == U_MISSING_RESOURCE_ERROR ) {
1325 status = U_ZERO_ERROR;
1326 standaloneWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1327 }
1328 fStandaloneWeekdaysCount = ures_getSize(standaloneWeekdaysData);
1329 fStandaloneWeekdays = new UnicodeString[fStandaloneWeekdaysCount+1];
1330 /* test for NULL */
1331 if (fStandaloneWeekdays == 0) {
1332 status = U_MEMORY_ALLOCATION_ERROR;
1333 goto cleanup;
1334 }
1335 // leave fStandaloneWeekdays[0] empty
1336 for(i = 0; i<fStandaloneWeekdaysCount; i++) {
1337 resStr = ures_getStringByIndex(standaloneWeekdaysData, i, &len, &status);
1338 // setTo() - see assignArray comments
1339 fStandaloneWeekdays[i+1].setTo(TRUE, resStr, len);
1340 }
1341 fStandaloneWeekdaysCount++;
1342
1343 standaloneShortWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status);
1344 if ( status == U_MISSING_RESOURCE_ERROR ) {
1345 status = U_ZERO_ERROR;
1346 standaloneShortWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1347 }
1348 fStandaloneShortWeekdaysCount = ures_getSize(standaloneShortWeekdaysData);
1349 fStandaloneShortWeekdays = new UnicodeString[fStandaloneShortWeekdaysCount+1];
1350 /* test for NULL */
1351 if (fStandaloneShortWeekdays == 0) {
1352 status = U_MEMORY_ALLOCATION_ERROR;
1353 goto cleanup;
1354 }
1355 // leave fStandaloneShortWeekdays[0] empty
1356 for(i = 0; i<fStandaloneShortWeekdaysCount; i++) {
1357 resStr = ures_getStringByIndex(standaloneShortWeekdaysData, i, &len, &status);
1358 // setTo() - see assignArray comments
1359 fStandaloneShortWeekdays[i+1].setTo(TRUE, resStr, len);
1360 }
1361 fStandaloneShortWeekdaysCount++;
1362
1363 standaloneNarrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1364 if ( status == U_MISSING_RESOURCE_ERROR ) {
1365 status = U_ZERO_ERROR;
1366 standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1367 if ( status == U_MISSING_RESOURCE_ERROR ) {
1368 status = U_ZERO_ERROR;
1369 standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1370 }
1371 }
1372 fStandaloneNarrowWeekdaysCount = ures_getSize(standaloneNarrowWeekdaysData);
1373 fStandaloneNarrowWeekdays = new UnicodeString[fStandaloneNarrowWeekdaysCount+1];
1374 /* test for NULL */
1375 if (fStandaloneNarrowWeekdays == 0) {
1376 status = U_MEMORY_ALLOCATION_ERROR;
1377 goto cleanup;
1378 }
1379 // leave fStandaloneNarrowWeekdays[0] empty
1380 for(i = 0; i<fStandaloneNarrowWeekdaysCount; i++) {
1381 resStr = ures_getStringByIndex(standaloneNarrowWeekdaysData, i, &len, &status);
1382 // setTo() - see assignArray comments
1383 fStandaloneNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1384 }
1385 fStandaloneNarrowWeekdaysCount++;
1386
374ca955
A
1387cleanup:
1388 ures_close(eras);
73c04bcf 1389 ures_close(eraNames);
b75a7d8f
A
1390}
1391
1392/**
1393 * Package private: used by SimpleDateFormat
1394 * Gets the index for the given time zone ID to obtain the timezone
1395 * strings for formatting. The time zone ID is just for programmatic
1396 * lookup. NOT LOCALIZED!!!
1397 * @param ID the given time zone ID.
1398 * @return the index of the given time zone ID. Returns -1 if
1399 * the given time zone ID can't be located in the DateFormatSymbols object.
1400 * @see java.util.SimpleTimeZone
1401 */
1402int32_t DateFormatSymbols::getZoneIndex(const UnicodeString& ID) const
1403{
1404 int32_t result = _getZoneIndex(ID);
1405 if (result >= 0) {
1406 return result;
1407 }
1408
1409 // Do a search through the equivalency group for the given ID
1410 int32_t n = TimeZone::countEquivalentIDs(ID);
1411 if (n > 1) {
1412 int32_t i;
1413 for (i=0; i<n; ++i) {
1414 UnicodeString equivID = TimeZone::getEquivalentID(ID, i);
1415 if (equivID != ID) {
1416 int32_t equivResult = _getZoneIndex(equivID);
1417 if (equivResult >= 0) {
1418 return equivResult;
1419 }
1420 }
1421 }
1422 }
1423
1424 return -1;
1425}
1426
1427/**
1428 * Lookup the given ID. Do NOT do an equivalency search.
1429 */
1430int32_t DateFormatSymbols::_getZoneIndex(const UnicodeString& ID) const
1431{
1432 for(int32_t index = 0; index < fZoneStringsRowCount; index++) {
1433 if (0 == ID.caseCompare(fZoneStrings[index][0], 0)) {
1434 return index;
1435 }
1436 }
1437
1438 return -1;
1439}
1440
374ca955
A
1441Locale
1442DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
1443 U_LOCALE_BASED(locBased, *this);
1444 return locBased.getLocale(type, status);
1445}
1446
73c04bcf
A
1447class TimeZoneKeysEnumeration : public StringEnumeration {
1448private:
1449 UnicodeString* strings;
1450 int32_t length;
1451 int32_t current;
1452 int32_t capacity;
1453 TimeZoneKeysEnumeration(UnicodeString* oldStrs, int32_t count){
1454 strings = newUnicodeStringArray(count);
1455 if(strings==NULL){
1456 return;
1457 }
1458 capacity = count;
1459 current = 0;
1460 for(length = 0; length<capacity; length++){
1461 strings[length].setTo(oldStrs[length]);
1462 }
1463 }
1464public:
1465 static UClassID U_EXPORT2 getStaticClassID(void);
1466 virtual UClassID getDynamicClassID(void) const;
1467
1468 TimeZoneKeysEnumeration(int32_t count, UErrorCode status){
1469 strings = newUnicodeStringArray(count);
1470 if(strings == NULL){
1471 status = U_MEMORY_ALLOCATION_ERROR;
1472 }
1473 length = 0;
1474 current = 0;
1475 capacity = count;
1476 }
1477
1478 void put(const UnicodeString& str, UErrorCode& status){
1479 if(length < capacity){
1480 strings[length++].setTo(str);
1481 }else{
1482 status = U_INDEX_OUTOFBOUNDS_ERROR;
1483 }
1484 }
1485 virtual ~TimeZoneKeysEnumeration() {
1486 delete[] strings;
1487 }
1488
1489 virtual StringEnumeration * clone() const
1490 {
1491 return new TimeZoneKeysEnumeration(strings, length);
1492 }
1493
1494 virtual int32_t count(UErrorCode &/*status*/) const {
1495 return length;
1496 }
1497 virtual const UChar* unext(int32_t *resultLength, UErrorCode& /*status*/){
1498 if(current < length){
1499 const UChar* ret = strings[current].getBuffer();
1500 *resultLength = strings[current].length();
1501 current++;
1502 return ret;
1503 }
1504 return NULL;
1505 }
1506
1507 virtual const UnicodeString* snext(UErrorCode& status) {
1508 if(U_FAILURE(status)){
1509 return NULL;
1510 }
1511 if(current < length){
1512 return &strings[current++];
1513 }
1514 return NULL;
1515 }
1516 /* this method is for thread safe iteration */
1517 const UnicodeString* snext(int32_t& pos, UErrorCode& status)const {
1518 if(U_FAILURE(status)){
1519 return NULL;
1520 }
1521 if(pos < length){
1522 return &strings[pos++];
1523 }
1524 return NULL;
1525 }
1526
1527 virtual void reset(UErrorCode& /*status*/) {
1528 current = 0;
1529
1530 }
1531private:
1532 UBool equals(const StringEnumeration& other) const{
1533 if (other.getDynamicClassID() != TimeZoneKeysEnumeration::getStaticClassID()) {
1534 return FALSE;
1535 }
1536 TimeZoneKeysEnumeration& enum2 = (TimeZoneKeysEnumeration&)(other);
1537 UErrorCode status = U_ZERO_ERROR;
1538
1539 int32_t count1 = count(status);
1540 int32_t count2 = other.count(status);
1541 if(count1 != count2){
1542 return FALSE;
1543 }
1544 int32_t pos1 = 0;
1545 int32_t pos2 = 0;
1546 const UnicodeString* str1 = NULL;
1547 const UnicodeString* str2 = NULL;
1548
1549 while((str1 = snext(pos1, status))!=NULL){
1550 str2 = enum2.snext(pos2, status);
1551 if(U_FAILURE(status)){
1552 return FALSE;
1553 }
1554 if(*str1 != *str2){
1555 // bail out at the first failure
1556 return FALSE;
1557 }
1558
1559 }
1560 // if we reached here that means that the enumerations are equal
1561 return TRUE;
1562 }
1563public:
1564 virtual UBool operator==(const StringEnumeration& that)const{
1565 return ((this == &that) ||
1566 (getDynamicClassID() == that.getDynamicClassID() &&
1567 StringEnumeration::operator==(that) &&
1568 equals(that)));
1569 }
1570};
1571
1572UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeZoneKeysEnumeration)
1573
1574void
1575DateFormatSymbols::initZoneStringsArray(UErrorCode& status){
1576 if(fZoneStringsHash == NULL){
1577 initZoneStrings(status);
1578 }
1579 if(U_FAILURE(status)){
1580 return;
1581 }
1582 fZoneStringsRowCount = fZoneIDEnumeration->count(status);
1583 fZoneStringsColCount = 8;
1584 fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
1585 /* if we can't get a chunk of heap then the system is going down. Pin the blame on system*/
1586 if (fZoneStrings == NULL) {
1587 status = U_MEMORY_ALLOCATION_ERROR;
1588 return;
1589 }
1590 const UnicodeString *zid = NULL;
1591 TimeZoneKeysEnumeration *keys = (TimeZoneKeysEnumeration*) fZoneIDEnumeration;
1592 int32_t pos = 0;
1593 int32_t i = 0;
1594 while((zid=keys->snext(pos,status))!=NULL){
1595 *(fZoneStrings+i) = newUnicodeStringArray(fZoneStringsColCount);
1596 /* test for NULL */
1597 if ((*(fZoneStrings+i)) == 0) {
1598 status = U_MEMORY_ALLOCATION_ERROR;
1599 return;
1600 }
1601 UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(*zid);
1602 fZoneStrings[i][0].setTo(*zid);
1603 fZoneStrings[i][1].setTo(strings[TIMEZONE_LONG_STANDARD]);
1604 fZoneStrings[i][2].setTo(strings[TIMEZONE_SHORT_STANDARD]);
1605 fZoneStrings[i][3].setTo(strings[TIMEZONE_LONG_DAYLIGHT]);
1606 fZoneStrings[i][4].setTo(strings[TIMEZONE_SHORT_DAYLIGHT]);
1607 fZoneStrings[i][5].setTo(strings[TIMEZONE_EXEMPLAR_CITY]);
1608 if(fZoneStrings[i][5].length()==0){
1609 fZoneStrings[i][5].setTo(strings[TIMEZONE_LONG_GENERIC]);
1610 }else{
1611 fZoneStrings[i][6].setTo(strings[TIMEZONE_LONG_GENERIC]);
1612 }
1613 if(fZoneStrings[i][6].length()==0){
1614 fZoneStrings[i][6].setTo(strings[TIMEZONE_LONG_GENERIC]);
1615 }else{
1616 fZoneStrings[i][7].setTo(strings[TIMEZONE_LONG_GENERIC]);
1617 }
1618 i++;
1619 }
1620}
1621
1622U_CDECL_BEGIN
1623static UBool U_CALLCONV
1624compareTZHashValues(const UHashTok val1, const UHashTok val2){
1625
1626 const UnicodeString* array1 = (UnicodeString*) val1.pointer;
1627 const UnicodeString* array2 = (UnicodeString*) val2.pointer;
1628 if(array1==array2){
1629 return TRUE;
1630 }
1631 if(array1==NULL || array2==NULL){
1632 return FALSE;
1633 }
1634 for(int32_t j=0; j< UTZ_MAX_DISPLAY_STRINGS_LENGTH; j++){
1635 if(array1[j] != array2[j]){
1636 return FALSE;
1637 }
1638 }
1639 return TRUE;
1640}
1641U_CDECL_END
1642
1643void
1644DateFormatSymbols::initZoneStrings(UErrorCode &status){
1645 if(U_FAILURE(status)){
1646 return;
1647 }
1648
1649 if(fZoneStringsHash != NULL){
1650 return;
1651 }
1652 int32_t i;
1653
1654 fZoneStringsHash = new Hashtable(uhash_compareUnicodeString, compareTZHashValues, status);
1655 if(fZoneStringsHash==NULL){
1656 status = U_MEMORY_ALLOCATION_ERROR;
1657 return;
1658 }
1659 fZoneStringsHash->setValueDeleter(deleteUnicodeStringArray);
1660
1661 if(fResourceBundle != NULL){
1662 UnicodeString solidus = UNICODE_STRING_SIMPLE("/");
1663 UnicodeString colon = UNICODE_STRING_SIMPLE(":");
1664 UResourceBundle zoneArray,zoneItem;
1665 ures_initStackObject(&zoneItem);
1666 ures_initStackObject(&zoneArray);
1667 for(const UResourceBundle* rb = fResourceBundle; rb!=NULL; rb=ures_getParentBundle(rb)){
1668 ures_getByKey(rb, gZoneStringsTag, &zoneArray, &status);
1669 if(U_FAILURE(status)){
1670 break;
1671 }
1672 while(ures_hasNext(&zoneArray)){
1673 UErrorCode tempStatus = U_ZERO_ERROR;
1674 UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH);
1675 ures_getNextResource(&zoneArray, &zoneItem, &status);
1676 UnicodeString key(ures_getKey(&zoneItem), -1, US_INV);
1677 key.findAndReplace(colon, solidus);
1678 int32_t len = 0;
1679 //fetch the strings with fine grained fallback
1680 const UChar* str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_SHORT_STANDARD, &len, &tempStatus);
1681 if(U_SUCCESS(tempStatus)){
1682 array[TIMEZONE_SHORT_STANDARD].setTo(TRUE, str, len);
1683 }else{
1684 tempStatus = U_ZERO_ERROR;
1685 }
1686 str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_SHORT_GENERIC, &len, &tempStatus);
1687 if(U_SUCCESS(tempStatus)){
1688 array[TIMEZONE_SHORT_GENERIC].setTo(TRUE, str, len);
1689 }else{
1690 tempStatus = U_ZERO_ERROR;
1691 }
1692 str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_SHORT_DAYLIGHT, &len, &tempStatus);
1693 if(U_SUCCESS(tempStatus)){
1694 array[TIMEZONE_SHORT_DAYLIGHT].setTo(TRUE, str, len);
1695 }else{
1696 tempStatus = U_ZERO_ERROR;
1697 }
1698 str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_LONG_STANDARD, &len, &tempStatus);
1699 if(U_SUCCESS(tempStatus)){
1700 array[TIMEZONE_LONG_STANDARD].setTo(TRUE, str, len);
1701 }else{
1702 tempStatus = U_ZERO_ERROR;
1703 }
1704 str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_LONG_GENERIC, &len, &tempStatus);
1705 if(U_SUCCESS(tempStatus)){
1706 array[TIMEZONE_LONG_GENERIC].setTo(TRUE, str, len);
1707 }else{
1708 tempStatus = U_ZERO_ERROR;
1709 }
1710 str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_LONG_DAYLIGHT, &len, &tempStatus);
1711 if(U_SUCCESS(tempStatus)){
1712 array[TIMEZONE_LONG_DAYLIGHT].setTo(TRUE, str, len);
1713 }else{
1714 tempStatus = U_ZERO_ERROR;
1715 }
1716 str = ures_getStringByKeyWithFallback(&zoneItem,UTZ_EXEMPLAR_CITY, &len, &tempStatus);
1717 if(U_SUCCESS(tempStatus)){
1718 array[TIMEZONE_EXEMPLAR_CITY].setTo(TRUE, str, len);
1719 }else{
1720 tempStatus = U_ZERO_ERROR;
1721 }
1722 // store the strings in hash
1723 fZoneStringsHash->put(key, array, status);
1724 }
1725 ures_close(&zoneItem);
1726 ures_close(&zoneArray);
1727 }
1728 int32_t length = fZoneStringsHash->count();
1729 TimeZoneKeysEnumeration* keysEnum = new TimeZoneKeysEnumeration(length, status);
1730 fZoneIDEnumeration = keysEnum;
1731 if(fZoneIDEnumeration==NULL){
1732 delete fZoneStringsHash;
1733 fZoneStringsHash = NULL;
1734 status = U_MEMORY_ALLOCATION_ERROR;
1735 return;
1736 }
1737 int32_t pos=-1;
1738 const UnicodeString* key;
1739 const UHashElement* elem = NULL;
1740 while((elem = fZoneStringsHash->nextElement(pos))!= NULL){
1741 const UHashTok keyTok = elem->key;
1742 key = (const UnicodeString*)keyTok.pointer;
1743 keysEnum->put(*key, status);
1744 }
1745 }else{
1746 //last resort strings
1747 UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH);
1748 if(array==NULL){
1749 delete fZoneStringsHash;
1750 status = U_MEMORY_ALLOCATION_ERROR;
1751 return;
1752 }
1753 int32_t length = ARRAY_LENGTH(gLastResortZoneStrings);
1754 UnicodeString key(gLastResortZoneStrings[0]);
1755 TimeZoneKeysEnumeration* keysEnum = new TimeZoneKeysEnumeration(length, status);
1756 fZoneIDEnumeration = keysEnum;
1757 if(fZoneIDEnumeration==NULL){
1758 delete fZoneStringsHash;
1759 delete[] array;
1760 fZoneStringsHash = NULL;
1761 status = U_MEMORY_ALLOCATION_ERROR;
1762 return;
1763 }
1764 keysEnum->put(key, status);
1765 int32_t j=1;
1766 for(i=0; i< length; ){
1767 array[i++].setTo(gLastResortZoneStrings[j++]);
1768 }
1769 fZoneStringsHash->put(key, array, status);
1770 }
1771}
1772void
1773DateFormatSymbols::initZoneStrings(const UnicodeString** strings, int32_t rowCount, int32_t columnCount, UErrorCode& status){
1774 if(strings==NULL || rowCount<0 || columnCount<0){
1775 status = U_ILLEGAL_ARGUMENT_ERROR;
1776 return;
1777 }
1778 TimeZoneKeysEnumeration* keysEnum = new TimeZoneKeysEnumeration(rowCount, status);
1779 fZoneIDEnumeration = keysEnum;
1780 if(U_FAILURE(status)){
1781 return;
1782 }
1783 if(fZoneIDEnumeration==NULL){
1784 status = U_MEMORY_ALLOCATION_ERROR;
1785 return;
1786 }
1787 fZoneStringsHash = new Hashtable(uhash_compareUnicodeString, compareTZHashValues, status);
1788 if(U_FAILURE(status)){
1789 return;
1790 }
1791 if(fZoneStringsHash==NULL){
1792 status = U_MEMORY_ALLOCATION_ERROR;
1793 return;
1794 }
1795 fZoneStringsHash->setValueDeleter(deleteUnicodeStringArray);
1796 for (int32_t row=0; row<rowCount; ++row){
1797 // the first string in the array is the key.
1798 UnicodeString key = strings[row][0];
1799 keysEnum->put(key, status);
1800 UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH);
1801 if(array==NULL){
1802 status = U_MEMORY_ALLOCATION_ERROR;
1803 return;
1804 }
1805 for (int32_t col=1; col<columnCount; ++col) {
1806 // fastCopyFrom() - see assignArray comments
1807 switch (col){
1808 case 1:
1809 array[TIMEZONE_LONG_STANDARD].setTo(strings[row][col]);
1810 break;
1811 case 2:
1812 array[TIMEZONE_SHORT_STANDARD].setTo(strings[row][col]);
1813 break;
1814 case 3:
1815 array[TIMEZONE_LONG_DAYLIGHT].setTo(strings[row][col]);
1816 break;
1817 case 4:
1818 array[TIMEZONE_LONG_DAYLIGHT].setTo(strings[row][col]);
1819 break;
1820 case 5:
1821 if(fZoneStringsColCount==6 || fZoneStringsColCount==8){
1822 array[TIMEZONE_EXEMPLAR_CITY].setTo(strings[row][col]);
1823 }else{
1824 array[TIMEZONE_LONG_GENERIC].setTo(strings[row][col]);
1825 }
1826 break;
1827 case 6:
1828 if(fZoneStringsColCount==8){
1829 array[TIMEZONE_LONG_GENERIC].setTo(strings[row][col]);
1830 }else{
1831 array[TIMEZONE_SHORT_GENERIC].setTo(strings[row][col]);
1832 }
1833 break;
1834 case 7:
1835 array[TIMEZONE_SHORT_GENERIC].setTo(strings[row][col]);
1836 break;
1837 default:
1838 status = U_ILLEGAL_ARGUMENT_ERROR;
1839 }
1840 // populate the hash table
1841 fZoneStringsHash->put(strings[row][0], array, status);
1842 }
1843 }
1844
1845}
1846
1847UnicodeString&
1848DateFormatSymbols::getZoneString(const UnicodeString &zid, const TimeZoneTranslationType type,
1849 UnicodeString &result, UErrorCode &status){
1850
1851 if(fZoneStringsHash == NULL){
1852 //lazy initialization
1853 initZoneStrings(status);
1854 }
1855 if(U_FAILURE(status)){
1856 return result;
1857 }
1858 UnicodeString* stringsArray = (UnicodeString*)fZoneStringsHash->get(zid);
1859 if(stringsArray != NULL){
1860 result.setTo(stringsArray[type],0);
1861 }
1862
1863 return result;
1864}
1865
1866StringEnumeration*
1867DateFormatSymbols::createZoneStringIDs(UErrorCode &status){
1868 if(U_FAILURE(status)){
1869 return NULL;
1870 }
1871 if(fZoneStringsHash == NULL){
1872 //lazy initialization
1873 initZoneStrings(status);
1874 }
1875 return fZoneIDEnumeration->clone();
1876}
1877
1878/**
1879 * Sets timezone strings.
1880 * @draft ICU 3.6
1881 */
1882void
1883DateFormatSymbols::setZoneString(const UnicodeString &zid, const TimeZoneTranslationType type,
1884 const UnicodeString &value, UErrorCode &status){
1885 if(fZoneStringsHash == NULL){
1886 //lazy initialization
1887 initZoneStrings(status);
1888 }
1889 if(U_FAILURE(status)){
1890 return;
1891 }
1892 UnicodeString* stringsArray = (UnicodeString*)fZoneStringsHash->get(zid);
1893 if(stringsArray != NULL){
1894 stringsArray[type].setTo(value);
1895 }else{
1896 stringsArray = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH);
1897 if(stringsArray==NULL){
1898 status = U_MEMORY_ALLOCATION_ERROR;
1899 return;
1900 }
1901 stringsArray[type].setTo(value);
1902 fZoneStringsHash->put(zid, stringsArray, status);
1903 TimeZoneKeysEnumeration* keys = (TimeZoneKeysEnumeration*) fZoneIDEnumeration;
1904 keys->put(zid, status);
1905 }
1906}
1907
1908Hashtable*
1909DateFormatSymbols::createZoneStringsHash(const Hashtable* otherHash){
1910 UErrorCode status = U_ZERO_ERROR;
1911 Hashtable* hash = new Hashtable(uhash_compareUnicodeString, compareTZHashValues, status);
1912 if(hash==NULL){
1913 return NULL;
1914 }
1915 if(U_FAILURE(status)){
1916 return NULL;
1917 }
1918 hash->setValueDeleter(deleteUnicodeStringArray);
1919 int32_t pos = -1;
1920 const UHashElement* elem = NULL;
1921 // walk through the hash table and create a deep clone
1922 while((elem = otherHash->nextElement(pos))!= NULL){
1923 const UHashTok otherKeyTok = elem->key;
1924 const UHashTok otherValueTok = elem->value;
1925 UnicodeString* otherKey = (UnicodeString*)otherKeyTok.pointer;
1926 UnicodeString* otherArray = (UnicodeString*)otherValueTok.pointer;
1927 UnicodeString* array = newUnicodeStringArray(UTZ_MAX_DISPLAY_STRINGS_LENGTH);
1928 if(array==NULL){
1929 return NULL;
1930 }
1931 UnicodeString key(*otherKey);
1932 for(int32_t i=0; i<UTZ_MAX_DISPLAY_STRINGS_LENGTH; i++){
1933 array[i].setTo(otherArray[i]);
1934 }
1935 hash->put(key, array, status);
1936 if(U_FAILURE(status)){
1937 delete[] array;
1938 return NULL;
1939 }
1940 }
1941 return hash;
1942}
1943
1944
1945UnicodeString&
1946DateFormatSymbols::getZoneID(const UnicodeString& zid, UnicodeString& result, UErrorCode& status){
1947 if(fZoneStringsHash == NULL){
1948 initZoneStrings(status);
1949 }
1950 if(U_FAILURE(status)){
1951 return result;
1952 }
1953 UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(zid);
1954 if (strings != NULL) {
1955 return result.setTo(zid,0);
1956 }
1957
1958 // Do a search through the equivalency group for the given ID
1959 int32_t n = TimeZone::countEquivalentIDs(zid);
1960 if (n > 1) {
1961 int32_t i;
1962 for (i=0; i<n; ++i) {
1963 UnicodeString equivID = TimeZone::getEquivalentID(zid, i);
1964 if (equivID != zid) {
1965 strings = (UnicodeString*)fZoneStringsHash->get(equivID);
1966 if (strings != NULL) {
1967 return result.setTo(equivID,0);
1968 }
1969 }
1970 }
1971 }else{
1972 result.setTo(zid);
1973 }
1974 return result;
1975}
1976
1977void
1978DateFormatSymbols::getZoneType(const UnicodeString& zid, const UnicodeString& text, int32_t start,
1979 TimeZoneTranslationType& type, UnicodeString& value, UErrorCode& status){
1980 if(fZoneStringsHash == NULL){
1981 initZoneStrings(status);
1982 }
1983 if(U_FAILURE(status)){
1984 return;
1985 }
1986 type = TIMEZONE_COUNT;
1987 UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(zid);
1988 if(strings != NULL){
1989 for(int32_t j=0; j<UTZ_MAX_DISPLAY_STRINGS_LENGTH; j++){
1990 if(strings[j].length() >0 && text.caseCompare(start, strings[j].length(), strings[j], 0)==0){
1991 type = (TimeZoneTranslationType)j;
1992 value.setTo(strings[j]);
1993 return;
1994 }
1995 }
1996 }
1997}
1998void
1999DateFormatSymbols::findZoneIDTypeValue( UnicodeString& zid, const UnicodeString& text, int32_t start,
2000 TimeZoneTranslationType& type, UnicodeString& value,
2001 UErrorCode& status){
2002 if(fZoneStringsHash == NULL){
2003 initZoneStrings(status);
2004 }
2005 if(U_FAILURE(status)){
2006 return;
2007 }
2008 const UnicodeString* myKey = NULL;
2009 int32_t pos = 0;
2010 TimeZoneKeysEnumeration *keys = (TimeZoneKeysEnumeration*)fZoneIDEnumeration;
2011 while( (myKey=keys->snext(pos, status))!= NULL){
2012 UnicodeString* strings = (UnicodeString*)fZoneStringsHash->get(*myKey);
2013 if(strings != NULL){
2014 for(int32_t j=0; j<UTZ_MAX_DISPLAY_STRINGS_LENGTH; j++){
2015 if(strings[j].length()>0 && text.caseCompare(start, strings[j].length(), strings[j], 0)==0){
2016 type = (TimeZoneTranslationType)j;
2017 value.setTo(strings[j]);
2018 zid.setTo(*myKey);
2019 return;
2020 }
2021 }
2022 }
2023 }
2024}
b75a7d8f
A
2025U_NAMESPACE_END
2026
2027#endif /* #if !UCONFIG_NO_FORMATTING */
2028
2029//eof