1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/*
4*******************************************************************************
5* Copyright (C) 1997-2016, International Business Machines Corporation and *
6* others. All Rights Reserved. *
7*******************************************************************************
8*
9* File DTFMTSYM.CPP
10*
11* Modification History:
12*
13* Date Name Description
14* 02/19/97 aliu Converted from java.
15* 07/21/98 stephen Added getZoneIndex
16* Changed weekdays/short weekdays to be one-based
17* 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix
18* 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars
19* 03/27/00 weiv Keeping resource bundle around!
20* 06/30/05 emmons Added eraNames, narrow month/day, standalone context
21* 10/12/05 emmons Added setters for eraNames, month/day by width/context
22*******************************************************************************
23*/
24
25#include <utility>
26
27#include "unicode/utypes.h"
28
29#if !UCONFIG_NO_FORMATTING
30#include "unicode/ustring.h"
31#include "unicode/localpointer.h"
32#include "unicode/dtfmtsym.h"
33#include "unicode/smpdtfmt.h"
34#include "unicode/msgfmt.h"
35#include "unicode/numsys.h"
36#include "unicode/tznames.h"
37#include "cpputils.h"
38#include "umutex.h"
39#include "cmemory.h"
40#include "cstring.h"
41#include "charstr.h"
42#include "dt_impl.h"
43#include "locbased.h"
44#include "gregoimp.h"
45#include "hash.h"
46#include "uassert.h"
47#include "uresimp.h"
48#include "ureslocs.h"
49#include "uvector.h"
50#include "shareddateformatsymbols.h"
51#include "unicode/calendar.h"
52#include "unifiedcache.h"
53
54// *****************************************************************************
55// class DateFormatSymbols
56// *****************************************************************************
57
58/**
59 * These are static arrays we use only in the case where we have no
60 * resource data.
61 */
62
63#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
64#define PATTERN_CHARS_LEN 38
65#else
66#define PATTERN_CHARS_LEN 37
67#endif
68
69/**
70 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
71 * locales use the same these unlocalized pattern characters.
72 */
73static const UChar gPatternChars[] = {
74 // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
75 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
76 // else:
77 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
78
79 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
80 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
81 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
82 0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
83#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
84 0x3a,
85#endif
86 0
87};
88
89//------------------------------------------------------
90// Strings of last resort. These are only used if we have no resource
91// files. They aren't designed for actual use, just for backup.
92
93// These are the month names and abbreviations of last resort.
94static const UChar gLastResortMonthNames[13][3] =
95{
96 {0x0030, 0x0031, 0x0000}, /* "01" */
97 {0x0030, 0x0032, 0x0000}, /* "02" */
98 {0x0030, 0x0033, 0x0000}, /* "03" */
99 {0x0030, 0x0034, 0x0000}, /* "04" */
100 {0x0030, 0x0035, 0x0000}, /* "05" */
101 {0x0030, 0x0036, 0x0000}, /* "06" */
102 {0x0030, 0x0037, 0x0000}, /* "07" */
103 {0x0030, 0x0038, 0x0000}, /* "08" */
104 {0x0030, 0x0039, 0x0000}, /* "09" */
105 {0x0031, 0x0030, 0x0000}, /* "10" */
106 {0x0031, 0x0031, 0x0000}, /* "11" */
107 {0x0031, 0x0032, 0x0000}, /* "12" */
108 {0x0031, 0x0033, 0x0000} /* "13" */
109};
110
111// These are the weekday names and abbreviations of last resort.
112static const UChar gLastResortDayNames[8][2] =
113{
114 {0x0030, 0x0000}, /* "0" */
115 {0x0031, 0x0000}, /* "1" */
116 {0x0032, 0x0000}, /* "2" */
117 {0x0033, 0x0000}, /* "3" */
118 {0x0034, 0x0000}, /* "4" */
119 {0x0035, 0x0000}, /* "5" */
120 {0x0036, 0x0000}, /* "6" */
121 {0x0037, 0x0000} /* "7" */
122};
123
124// These are the quarter names and abbreviations of last resort.
125static const UChar gLastResortQuarters[4][2] =
126{
127 {0x0031, 0x0000}, /* "1" */
128 {0x0032, 0x0000}, /* "2" */
129 {0x0033, 0x0000}, /* "3" */
130 {0x0034, 0x0000}, /* "4" */
131};
132
133// These are the am/pm and BC/AD markers of last resort.
134static const UChar gLastResortAmPmMarkers[2][3] =
135{
136 {0x0041, 0x004D, 0x0000}, /* "AM" */
137 {0x0050, 0x004D, 0x0000} /* "PM" */
138};
139
140static const UChar gLastResortEras[2][3] =
141{
142 {0x0042, 0x0043, 0x0000}, /* "BC" */
143 {0x0041, 0x0044, 0x0000} /* "AD" */
144};
145
146/* Sizes for the last resort string arrays */
147typedef enum LastResortSize {
148 kMonthNum = 13,
149 kMonthLen = 3,
150
151 kDayNum = 8,
152 kDayLen = 2,
153
154 kAmPmNum = 2,
155 kAmPmLen = 3,
156
157 kQuarterNum = 4,
158 kQuarterLen = 2,
159
160 kEraNum = 2,
161 kEraLen = 3,
162
163 kZoneNum = 5,
164 kZoneLen = 4,
165
166 kGmtHourNum = 4,
167 kGmtHourLen = 10
168} LastResortSize;
169
170U_NAMESPACE_BEGIN
171
172SharedDateFormatSymbols::~SharedDateFormatSymbols() {
173}
174
175template<> U_I18N_API
176const SharedDateFormatSymbols *
177 LocaleCacheKey<SharedDateFormatSymbols>::createObject(
178 const void * /*unusedContext*/, UErrorCode &status) const {
179 char type[256];
180 Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
181 if (U_FAILURE(status)) {
182 return NULL;
183 }
184 SharedDateFormatSymbols *shared
185 = new SharedDateFormatSymbols(fLoc, type, status);
186 if (shared == NULL) {
187 status = U_MEMORY_ALLOCATION_ERROR;
188 return NULL;
189 }
190 if (U_FAILURE(status)) {
191 delete shared;
192 return NULL;
193 }
194 shared->addRef();
195 return shared;
196}
197
198UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
199
200#define kSUPPLEMENTAL "supplementalData"
201
202/**
203 * These are the tags we expect to see in normal resource bundle files associated
204 * with a locale and calendar
205 */
206static const char gCalendarTag[]="calendar";
207static const char gGregorianTag[]="gregorian";
208static const char gErasTag[]="eras";
209static const char gCyclicNameSetsTag[]="cyclicNameSets";
210static const char gNameSetYearsTag[]="years";
211static const char gNameSetZodiacsTag[]="zodiacs";
212static const char gMonthNamesTag[]="monthNames";
213static const char gMonthPatternsTag[]="monthPatterns";
214static const char gDayNamesTag[]="dayNames";
215static const char gNamesWideTag[]="wide";
216static const char gNamesAbbrTag[]="abbreviated";
217static const char gNamesShortTag[]="short";
218static const char gNamesNarrowTag[]="narrow";
219static const char gNamesAllTag[]="all";
220static const char gNamesFormatTag[]="format";
221static const char gNamesStandaloneTag[]="stand-alone";
222static const char gNamesNumericTag[]="numeric";
223static const char gAmPmMarkersTag[]="AmPmMarkers";
224static const char gAmPmMarkersAbbrTag[]="AmPmMarkersAbbr";
225static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
226static const char gQuartersTag[]="quarters";
227static const char gNumberElementsTag[]="NumberElements";
228static const char gSymbolsTag[]="symbols";
229static const char gTimeSeparatorTag[]="timeSeparator";
230static const char gDayPeriodTag[]="dayPeriod";
231
232// static const char gZoneStringsTag[]="zoneStrings";
233
234// static const char gLocalPatternCharsTag[]="localPatternChars";
235
236static const char gContextTransformsTag[]="contextTransforms";
237
238/**
239 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
240 * Work around this.
241 */
242static inline UnicodeString* newUnicodeStringArray(size_t count) {
243 return new UnicodeString[count ? count : 1];
244}
245
246//------------------------------------------------------
247
248DateFormatSymbols * U_EXPORT2
249DateFormatSymbols::createForLocale(
250 const Locale& locale, UErrorCode &status) {
251 const SharedDateFormatSymbols *shared = NULL;
252 UnifiedCache::getByLocale(locale, shared, status);
253 if (U_FAILURE(status)) {
254 return NULL;
255 }
256 DateFormatSymbols *result = new DateFormatSymbols(shared->get());
257 shared->removeRef();
258 if (result == NULL) {
259 status = U_MEMORY_ALLOCATION_ERROR;
260 return NULL;
261 }
262 return result;
263}
264
265DateFormatSymbols::DateFormatSymbols(const Locale& locale,
266 UErrorCode& status)
267 : UObject()
268{
269 initializeData(locale, NULL, status);
270}
271
272DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
273 : UObject()
274{
275 initializeData(Locale::getDefault(), NULL, status, TRUE);
276}
277
278
279DateFormatSymbols::DateFormatSymbols(const Locale& locale,
280 const char *type,
281 UErrorCode& status)
282 : UObject()
283{
284 initializeData(locale, type, status);
285}
286
287DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
288 : UObject()
289{
290 initializeData(Locale::getDefault(), type, status, TRUE);
291}
292
293DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
294 : UObject(other)
295{
296 copyData(other);
297}
298
299void
300DateFormatSymbols::assignArray(UnicodeString*& dstArray,
301 int32_t& dstCount,
302 const UnicodeString* srcArray,
303 int32_t srcCount)
304{
305 // assignArray() is only called by copyData() and initializeData(), which in turn
306 // implements the copy constructor and the assignment operator.
307 // All strings in a DateFormatSymbols object are created in one of the following
308 // three ways that all allow to safely use UnicodeString::fastCopyFrom():
309 // - readonly-aliases from resource bundles
310 // - readonly-aliases or allocated strings from constants
311 // - safely cloned strings (with owned buffers) from setXYZ() functions
312 //
313 // Note that this is true for as long as DateFormatSymbols can be constructed
314 // only from a locale bundle or set via the cloning API,
315 // *and* for as long as all the strings are in *private* fields, preventing
316 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
317 dstCount = srcCount;
318 dstArray = newUnicodeStringArray(srcCount);
319 if(dstArray != NULL) {
320 int32_t i;
321 for(i=0; i<srcCount; ++i) {
322 dstArray[i].fastCopyFrom(srcArray[i]);
323 }
324 }
325}
326
327/**
328 * Create a copy, in fZoneStrings, of the given zone strings array. The
329 * member variables fZoneStringsRowCount and fZoneStringsColCount should
330 * be set already by the caller.
331 */
332void
333DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
334{
335 int32_t row, col;
336 UBool failed = FALSE;
337
338 fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
339 if (fZoneStrings != NULL) {
340 for (row=0; row<fZoneStringsRowCount; ++row)
341 {
342 fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
343 if (fZoneStrings[row] == NULL) {
344 failed = TRUE;
345 break;
346 }
347 for (col=0; col<fZoneStringsColCount; ++col) {
348 // fastCopyFrom() - see assignArray comments
349 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
350 }
351 }
352 }
353 // If memory allocation failed, roll back and delete fZoneStrings
354 if (failed) {
355 for (int i = row; i >= 0; i--) {
356 delete[] fZoneStrings[i];
357 }
358 uprv_free(fZoneStrings);
359 fZoneStrings = NULL;
360 }
361}
362
363/**
364 * Copy all of the other's data to this.
365 */
366void
367DateFormatSymbols::copyData(const DateFormatSymbols& other) {
368 UErrorCode status = U_ZERO_ERROR;
369 U_LOCALE_BASED(locBased, *this);
370 locBased.setLocaleIDs(
371 other.getLocale(ULOC_VALID_LOCALE, status),
372 other.getLocale(ULOC_ACTUAL_LOCALE, status));
373 assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
374 assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
375 assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
376 assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
377 assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
378 assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
379 assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
380 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
381 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
382 assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
383 assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
384 assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
385 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
386 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
387 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
388 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
389 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
390 assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
391 assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
392 fTimeSeparator.fastCopyFrom(other.fTimeSeparator); // fastCopyFrom() - see assignArray comments
393 assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
394 assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
395 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
396 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
397 assignArray(fWideDayPeriods, fWideDayPeriodsCount,
398 other.fWideDayPeriods, other.fWideDayPeriodsCount);
399 assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
400 other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
401 assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
402 other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
403 assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
404 other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
405 assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
406 other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
407 assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
408 other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
409 if (other.fLeapMonthPatterns != NULL) {
410 assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
411 } else {
412 fLeapMonthPatterns = NULL;
413 fLeapMonthPatternsCount = 0;
414 }
415 if (other.fShortYearNames != NULL) {
416 assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
417 } else {
418 fShortYearNames = NULL;
419 fShortYearNamesCount = 0;
420 }
421 if (other.fShortZodiacNames != NULL) {
422 assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
423 } else {
424 fShortZodiacNames = NULL;
425 fShortZodiacNamesCount = 0;
426 }
427
428 if (other.fZoneStrings != NULL) {
429 fZoneStringsColCount = other.fZoneStringsColCount;
430 fZoneStringsRowCount = other.fZoneStringsRowCount;
431 createZoneStrings((const UnicodeString**)other.fZoneStrings);
432
433 } else {
434 fZoneStrings = NULL;
435 fZoneStringsColCount = 0;
436 fZoneStringsRowCount = 0;
437 }
438 fZSFLocale = other.fZSFLocale;
439 // Other zone strings data is created on demand
440 fLocaleZoneStrings = NULL;
441
442 // fastCopyFrom() - see assignArray comments
443 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
444
445 uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
446}
447
448/**
449 * Assignment operator.
450 */
451DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
452{
453 dispose();
454 copyData(other);
455
456 return *this;
457}
458
459DateFormatSymbols::~DateFormatSymbols()
460{
461 dispose();
462}
463
464void DateFormatSymbols::dispose()
465{
466 delete[] fEras;
467 delete[] fEraNames;
468 delete[] fNarrowEras;
469 delete[] fMonths;
470 delete[] fShortMonths;
471 delete[] fNarrowMonths;
472 delete[] fStandaloneMonths;
473 delete[] fStandaloneShortMonths;
474 delete[] fStandaloneNarrowMonths;
475 delete[] fWeekdays;
476 delete[] fShortWeekdays;
477 delete[] fShorterWeekdays;
478 delete[] fNarrowWeekdays;
479 delete[] fStandaloneWeekdays;
480 delete[] fStandaloneShortWeekdays;
481 delete[] fStandaloneShorterWeekdays;
482 delete[] fStandaloneNarrowWeekdays;
483 delete[] fAmPms;
484 delete[] fNarrowAmPms;
485 delete[] fQuarters;
486 delete[] fShortQuarters;
487 delete[] fStandaloneQuarters;
488 delete[] fStandaloneShortQuarters;
489 delete[] fLeapMonthPatterns;
490 delete[] fShortYearNames;
491 delete[] fShortZodiacNames;
492 delete[] fAbbreviatedDayPeriods;
493 delete[] fWideDayPeriods;
494 delete[] fNarrowDayPeriods;
495 delete[] fStandaloneAbbreviatedDayPeriods;
496 delete[] fStandaloneWideDayPeriods;
497 delete[] fStandaloneNarrowDayPeriods;
498
499 disposeZoneStrings();
500}
501
502void DateFormatSymbols::disposeZoneStrings()
503{
504 if (fZoneStrings) {
505 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
506 delete[] fZoneStrings[row];
507 }
508 uprv_free(fZoneStrings);
509 }
510 if (fLocaleZoneStrings) {
511 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
512 delete[] fLocaleZoneStrings[row];
513 }
514 uprv_free(fLocaleZoneStrings);
515 }
516
517 fZoneStrings = NULL;
518 fLocaleZoneStrings = NULL;
519 fZoneStringsRowCount = 0;
520 fZoneStringsColCount = 0;
521}
522
523UBool
524DateFormatSymbols::arrayCompare(const UnicodeString* array1,
525 const UnicodeString* array2,
526 int32_t count)
527{
528 if (array1 == array2) return TRUE;
529 while (count>0)
530 {
531 --count;
532 if (array1[count] != array2[count]) return FALSE;
533 }
534 return TRUE;
535}
536
537UBool
538DateFormatSymbols::operator==(const DateFormatSymbols& other) const
539{
540 // First do cheap comparisons
541 if (this == &other) {
542 return TRUE;
543 }
544 if (fErasCount == other.fErasCount &&
545 fEraNamesCount == other.fEraNamesCount &&
546 fNarrowErasCount == other.fNarrowErasCount &&
547 fMonthsCount == other.fMonthsCount &&
548 fShortMonthsCount == other.fShortMonthsCount &&
549 fNarrowMonthsCount == other.fNarrowMonthsCount &&
550 fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
551 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
552 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
553 fWeekdaysCount == other.fWeekdaysCount &&
554 fShortWeekdaysCount == other.fShortWeekdaysCount &&
555 fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
556 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
557 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
558 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
559 fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
560 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
561 fAmPmsCount == other.fAmPmsCount &&
562 fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
563 fQuartersCount == other.fQuartersCount &&
564 fShortQuartersCount == other.fShortQuartersCount &&
565 fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
566 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
567 fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
568 fShortYearNamesCount == other.fShortYearNamesCount &&
569 fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
570 fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
571 fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
572 fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
573 fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
574 fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
575 fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
576 (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
577 {
578 // Now compare the arrays themselves
579 if (arrayCompare(fEras, other.fEras, fErasCount) &&
580 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
581 arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
582 arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
583 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
584 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
585 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
586 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
587 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
588 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
589 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
590 arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
591 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
592 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
593 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
594 arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
595 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
596 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
597 arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
598 fTimeSeparator == other.fTimeSeparator &&
599 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
600 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
601 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
602 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
603 arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
604 arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
605 arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
606 arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
607 arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
608 arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
609 arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
610 fStandaloneAbbreviatedDayPeriodsCount) &&
611 arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
612 fStandaloneWideDayPeriodsCount) &&
613 arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
614 fStandaloneWideDayPeriodsCount))
615 {
616 // Compare the contents of fZoneStrings
617 if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
618 if (fZSFLocale == other.fZSFLocale) {
619 return TRUE;
620 }
621 } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
622 if (fZoneStringsRowCount == other.fZoneStringsRowCount
623 && fZoneStringsColCount == other.fZoneStringsColCount) {
624 UBool cmpres = TRUE;
625 for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
626 cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
627 }
628 return cmpres;
629 }
630 }
631 return FALSE;
632 }
633 }
634 return FALSE;
635}
636
637//------------------------------------------------------
638
639const UnicodeString*
640DateFormatSymbols::getEras(int32_t &count) const
641{
642 count = fErasCount;
643 return fEras;
644}
645
646const UnicodeString*
647DateFormatSymbols::getEraNames(int32_t &count) const
648{
649 count = fEraNamesCount;
650 return fEraNames;
651}
652
653const UnicodeString*
654DateFormatSymbols::getNarrowEras(int32_t &count) const
655{
656 count = fNarrowErasCount;
657 return fNarrowEras;
658}
659
660const UnicodeString*
661DateFormatSymbols::getMonths(int32_t &count) const
662{
663 count = fMonthsCount;
664 return fMonths;
665}
666
667const UnicodeString*
668DateFormatSymbols::getShortMonths(int32_t &count) const
669{
670 count = fShortMonthsCount;
671 return fShortMonths;
672}
673
674const UnicodeString*
675DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
676{
677 UnicodeString *returnValue = NULL;
678
679 switch (context) {
680 case FORMAT :
681 switch(width) {
682 case WIDE :
683 count = fMonthsCount;
684 returnValue = fMonths;
685 break;
686 case ABBREVIATED :
687 case SHORT : // no month data for this, defaults to ABBREVIATED
688 count = fShortMonthsCount;
689 returnValue = fShortMonths;
690 break;
691 case NARROW :
692 count = fNarrowMonthsCount;
693 returnValue = fNarrowMonths;
694 break;
695 case DT_WIDTH_COUNT :
696 break;
697 }
698 break;
699 case STANDALONE :
700 switch(width) {
701 case WIDE :
702 count = fStandaloneMonthsCount;
703 returnValue = fStandaloneMonths;
704 break;
705 case ABBREVIATED :
706 case SHORT : // no month data for this, defaults to ABBREVIATED
707 count = fStandaloneShortMonthsCount;
708 returnValue = fStandaloneShortMonths;
709 break;
710 case NARROW :
711 count = fStandaloneNarrowMonthsCount;
712 returnValue = fStandaloneNarrowMonths;
713 break;
714 case DT_WIDTH_COUNT :
715 break;
716 }
717 break;
718 case DT_CONTEXT_COUNT :
719 break;
720 }
721 return returnValue;
722}
723
724const UnicodeString*
725DateFormatSymbols::getWeekdays(int32_t &count) const
726{
727 count = fWeekdaysCount;
728 return fWeekdays;
729}
730
731const UnicodeString*
732DateFormatSymbols::getShortWeekdays(int32_t &count) const
733{
734 count = fShortWeekdaysCount;
735 return fShortWeekdays;
736}
737
738const UnicodeString*
739DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
740{
741 UnicodeString *returnValue = NULL;
742 switch (context) {
743 case FORMAT :
744 switch(width) {
745 case WIDE :
746 count = fWeekdaysCount;
747 returnValue = fWeekdays;
748 break;
749 case ABBREVIATED :
750 count = fShortWeekdaysCount;
751 returnValue = fShortWeekdays;
752 break;
753 case SHORT :
754 count = fShorterWeekdaysCount;
755 returnValue = fShorterWeekdays;
756 break;
757 case NARROW :
758 count = fNarrowWeekdaysCount;
759 returnValue = fNarrowWeekdays;
760 break;
761 case DT_WIDTH_COUNT :
762 break;
763 }
764 break;
765 case STANDALONE :
766 switch(width) {
767 case WIDE :
768 count = fStandaloneWeekdaysCount;
769 returnValue = fStandaloneWeekdays;
770 break;
771 case ABBREVIATED :
772 count = fStandaloneShortWeekdaysCount;
773 returnValue = fStandaloneShortWeekdays;
774 break;
775 case SHORT :
776 count = fStandaloneShorterWeekdaysCount;
777 returnValue = fStandaloneShorterWeekdays;
778 break;
779 case NARROW :
780 count = fStandaloneNarrowWeekdaysCount;
781 returnValue = fStandaloneNarrowWeekdays;
782 break;
783 case DT_WIDTH_COUNT :
784 break;
785 }
786 break;
787 case DT_CONTEXT_COUNT :
788 break;
789 }
790 return returnValue;
791}
792
793const UnicodeString*
794DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
795{
796 UnicodeString *returnValue = NULL;
797
798 switch (context) {
799 case FORMAT :
800 switch(width) {
801 case WIDE :
802 count = fQuartersCount;
803 returnValue = fQuarters;
804 break;
805 case ABBREVIATED :
806 case SHORT : // no quarter data for this, defaults to ABBREVIATED
807 count = fShortQuartersCount;
808 returnValue = fShortQuarters;
809 break;
810 case NARROW :
811 count = 0;
812 returnValue = NULL;
813 break;
814 case DT_WIDTH_COUNT :
815 break;
816 }
817 break;
818 case STANDALONE :
819 switch(width) {
820 case WIDE :
821 count = fStandaloneQuartersCount;
822 returnValue = fStandaloneQuarters;
823 break;
824 case ABBREVIATED :
825 case SHORT : // no quarter data for this, defaults to ABBREVIATED
826 count = fStandaloneShortQuartersCount;
827 returnValue = fStandaloneShortQuarters;
828 break;
829 case NARROW :
830 count = 0;
831 returnValue = NULL;
832 break;
833 case DT_WIDTH_COUNT :
834 break;
835 }
836 break;
837 case DT_CONTEXT_COUNT :
838 break;
839 }
840 return returnValue;
841}
842
843UnicodeString&
844DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
845{
846 // fastCopyFrom() - see assignArray comments
847 return result.fastCopyFrom(fTimeSeparator);
848}
849
850const UnicodeString*
851DateFormatSymbols::getAmPmStrings(int32_t &count) const
852{
853 count = fAmPmsCount;
854 return fAmPms;
855}
856
857const UnicodeString*
858DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
859{
860 count = fLeapMonthPatternsCount;
861 return fLeapMonthPatterns;
862}
863
864const UnicodeString*
865DateFormatSymbols::getYearNames(int32_t& count,
866 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
867{
868 count = fShortYearNamesCount;
869 return fShortYearNames;
870}
871
872void
873DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
874 DtContextType context, DtWidthType width)
875{
876 if (context == FORMAT && width == ABBREVIATED) {
877 if (fShortYearNames) {
878 delete[] fShortYearNames;
879 }
880 fShortYearNames = newUnicodeStringArray(count);
881 uprv_arrayCopy(yearNames, fShortYearNames, count);
882 fShortYearNamesCount = count;
883 }
884}
885
886const UnicodeString*
887DateFormatSymbols::getZodiacNames(int32_t& count,
888 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
889{
890 count = fShortZodiacNamesCount;
891 return fShortZodiacNames;
892}
893
894void
895DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
896 DtContextType context, DtWidthType width)
897{
898 if (context == FORMAT && width == ABBREVIATED) {
899 if (fShortZodiacNames) {
900 delete[] fShortZodiacNames;
901 }
902 fShortZodiacNames = newUnicodeStringArray(count);
903 uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
904 fShortZodiacNamesCount = count;
905 }
906}
907
908//------------------------------------------------------
909
910void
911DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
912{
913 // delete the old list if we own it
914 if (fEras)
915 delete[] fEras;
916
917 // we always own the new list, which we create here (we duplicate rather
918 // than adopting the list passed in)
919 fEras = newUnicodeStringArray(count);
920 uprv_arrayCopy(erasArray,fEras, count);
921 fErasCount = count;
922}
923
924void
925DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
926{
927 // delete the old list if we own it
928 if (fEraNames)
929 delete[] fEraNames;
930
931 // we always own the new list, which we create here (we duplicate rather
932 // than adopting the list passed in)
933 fEraNames = newUnicodeStringArray(count);
934 uprv_arrayCopy(eraNamesArray,fEraNames, count);
935 fEraNamesCount = count;
936}
937
938void
939DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
940{
941 // delete the old list if we own it
942 if (fNarrowEras)
943 delete[] fNarrowEras;
944
945 // we always own the new list, which we create here (we duplicate rather
946 // than adopting the list passed in)
947 fNarrowEras = newUnicodeStringArray(count);
948 uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
949 fNarrowErasCount = count;
950}
951
952void
953DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
954{
955 // delete the old list if we own it
956 if (fMonths)
957 delete[] fMonths;
958
959 // we always own the new list, which we create here (we duplicate rather
960 // than adopting the list passed in)
961 fMonths = newUnicodeStringArray(count);
962 uprv_arrayCopy( monthsArray,fMonths,count);
963 fMonthsCount = count;
964}
965
966void
967DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
968{
969 // delete the old list if we own it
970 if (fShortMonths)
971 delete[] fShortMonths;
972
973 // we always own the new list, which we create here (we duplicate rather
974 // than adopting the list passed in)
975 fShortMonths = newUnicodeStringArray(count);
976 uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
977 fShortMonthsCount = count;
978}
979
980void
981DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
982{
983 // delete the old list if we own it
984 // we always own the new list, which we create here (we duplicate rather
985 // than adopting the list passed in)
986
987 switch (context) {
988 case FORMAT :
989 switch (width) {
990 case WIDE :
991 if (fMonths)
992 delete[] fMonths;
993 fMonths = newUnicodeStringArray(count);
994 uprv_arrayCopy( monthsArray,fMonths,count);
995 fMonthsCount = count;
996 break;
997 case ABBREVIATED :
998 if (fShortMonths)
999 delete[] fShortMonths;
1000 fShortMonths = newUnicodeStringArray(count);
1001 uprv_arrayCopy( monthsArray,fShortMonths,count);
1002 fShortMonthsCount = count;
1003 break;
1004 case NARROW :
1005 if (fNarrowMonths)
1006 delete[] fNarrowMonths;
1007 fNarrowMonths = newUnicodeStringArray(count);
1008 uprv_arrayCopy( monthsArray,fNarrowMonths,count);
1009 fNarrowMonthsCount = count;
1010 break;
1011 default :
1012 break;
1013 }
1014 break;
1015 case STANDALONE :
1016 switch (width) {
1017 case WIDE :
1018 if (fStandaloneMonths)
1019 delete[] fStandaloneMonths;
1020 fStandaloneMonths = newUnicodeStringArray(count);
1021 uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
1022 fStandaloneMonthsCount = count;
1023 break;
1024 case ABBREVIATED :
1025 if (fStandaloneShortMonths)
1026 delete[] fStandaloneShortMonths;
1027 fStandaloneShortMonths = newUnicodeStringArray(count);
1028 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
1029 fStandaloneShortMonthsCount = count;
1030 break;
1031 case NARROW :
1032 if (fStandaloneNarrowMonths)
1033 delete[] fStandaloneNarrowMonths;
1034 fStandaloneNarrowMonths = newUnicodeStringArray(count);
1035 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
1036 fStandaloneNarrowMonthsCount = count;
1037 break;
1038 default :
1039 break;
1040 }
1041 break;
1042 case DT_CONTEXT_COUNT :
1043 break;
1044 }
1045}
1046
1047void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
1048{
1049 // delete the old list if we own it
1050 if (fWeekdays)
1051 delete[] fWeekdays;
1052
1053 // we always own the new list, which we create here (we duplicate rather
1054 // than adopting the list passed in)
1055 fWeekdays = newUnicodeStringArray(count);
1056 uprv_arrayCopy(weekdaysArray,fWeekdays,count);
1057 fWeekdaysCount = count;
1058}
1059
1060void
1061DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
1062{
1063 // delete the old list if we own it
1064 if (fShortWeekdays)
1065 delete[] fShortWeekdays;
1066
1067 // we always own the new list, which we create here (we duplicate rather
1068 // than adopting the list passed in)
1069 fShortWeekdays = newUnicodeStringArray(count);
1070 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
1071 fShortWeekdaysCount = count;
1072}
1073
1074void
1075DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
1076{
1077 // delete the old list if we own it
1078 // we always own the new list, which we create here (we duplicate rather
1079 // than adopting the list passed in)
1080
1081 switch (context) {
1082 case FORMAT :
1083 switch (width) {
1084 case WIDE :
1085 if (fWeekdays)
1086 delete[] fWeekdays;
1087 fWeekdays = newUnicodeStringArray(count);
1088 uprv_arrayCopy(weekdaysArray, fWeekdays, count);
1089 fWeekdaysCount = count;
1090 break;
1091 case ABBREVIATED :
1092 if (fShortWeekdays)
1093 delete[] fShortWeekdays;
1094 fShortWeekdays = newUnicodeStringArray(count);
1095 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
1096 fShortWeekdaysCount = count;
1097 break;
1098 case SHORT :
1099 if (fShorterWeekdays)
1100 delete[] fShorterWeekdays;
1101 fShorterWeekdays = newUnicodeStringArray(count);
1102 uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
1103 fShorterWeekdaysCount = count;
1104 break;
1105 case NARROW :
1106 if (fNarrowWeekdays)
1107 delete[] fNarrowWeekdays;
1108 fNarrowWeekdays = newUnicodeStringArray(count);
1109 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
1110 fNarrowWeekdaysCount = count;
1111 break;
1112 case DT_WIDTH_COUNT :
1113 break;
1114 }
1115 break;
1116 case STANDALONE :
1117 switch (width) {
1118 case WIDE :
1119 if (fStandaloneWeekdays)
1120 delete[] fStandaloneWeekdays;
1121 fStandaloneWeekdays = newUnicodeStringArray(count);
1122 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
1123 fStandaloneWeekdaysCount = count;
1124 break;
1125 case ABBREVIATED :
1126 if (fStandaloneShortWeekdays)
1127 delete[] fStandaloneShortWeekdays;
1128 fStandaloneShortWeekdays = newUnicodeStringArray(count);
1129 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
1130 fStandaloneShortWeekdaysCount = count;
1131 break;
1132 case SHORT :
1133 if (fStandaloneShorterWeekdays)
1134 delete[] fStandaloneShorterWeekdays;
1135 fStandaloneShorterWeekdays = newUnicodeStringArray(count);
1136 uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
1137 fStandaloneShorterWeekdaysCount = count;
1138 break;
1139 case NARROW :
1140 if (fStandaloneNarrowWeekdays)
1141 delete[] fStandaloneNarrowWeekdays;
1142 fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
1143 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
1144 fStandaloneNarrowWeekdaysCount = count;
1145 break;
1146 case DT_WIDTH_COUNT :
1147 break;
1148 }
1149 break;
1150 case DT_CONTEXT_COUNT :
1151 break;
1152 }
1153}
1154
1155void
1156DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
1157{
1158 // delete the old list if we own it
1159 // we always own the new list, which we create here (we duplicate rather
1160 // than adopting the list passed in)
1161
1162 switch (context) {
1163 case FORMAT :
1164 switch (width) {
1165 case WIDE :
1166 if (fQuarters)
1167 delete[] fQuarters;
1168 fQuarters = newUnicodeStringArray(count);
1169 uprv_arrayCopy( quartersArray,fQuarters,count);
1170 fQuartersCount = count;
1171 break;
1172 case ABBREVIATED :
1173 if (fShortQuarters)
1174 delete[] fShortQuarters;
1175 fShortQuarters = newUnicodeStringArray(count);
1176 uprv_arrayCopy( quartersArray,fShortQuarters,count);
1177 fShortQuartersCount = count;
1178 break;
1179 case NARROW :
1180 /*
1181 if (fNarrowQuarters)
1182 delete[] fNarrowQuarters;
1183 fNarrowQuarters = newUnicodeStringArray(count);
1184 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1185 fNarrowQuartersCount = count;
1186 */
1187 break;
1188 default :
1189 break;
1190 }
1191 break;
1192 case STANDALONE :
1193 switch (width) {
1194 case WIDE :
1195 if (fStandaloneQuarters)
1196 delete[] fStandaloneQuarters;
1197 fStandaloneQuarters = newUnicodeStringArray(count);
1198 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1199 fStandaloneQuartersCount = count;
1200 break;
1201 case ABBREVIATED :
1202 if (fStandaloneShortQuarters)
1203 delete[] fStandaloneShortQuarters;
1204 fStandaloneShortQuarters = newUnicodeStringArray(count);
1205 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1206 fStandaloneShortQuartersCount = count;
1207 break;
1208 case NARROW :
1209 /*
1210 if (fStandaloneNarrowQuarters)
1211 delete[] fStandaloneNarrowQuarters;
1212 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1213 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1214 fStandaloneNarrowQuartersCount = count;
1215 */
1216 break;
1217 default :
1218 break;
1219 }
1220 break;
1221 case DT_CONTEXT_COUNT :
1222 break;
1223 }
1224}
1225
1226void
1227DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1228{
1229 // delete the old list if we own it
1230 if (fAmPms) delete[] fAmPms;
1231
1232 // we always own the new list, which we create here (we duplicate rather
1233 // than adopting the list passed in)
1234 fAmPms = newUnicodeStringArray(count);
1235 uprv_arrayCopy(amPmsArray,fAmPms,count);
1236 fAmPmsCount = count;
1237}
1238
1239void
1240DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
1241{
1242 fTimeSeparator = newTimeSeparator;
1243}
1244
1245const UnicodeString**
1246DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1247{
1248 const UnicodeString **result = NULL;
1249 static UMutex LOCK;
1250
1251 umtx_lock(&LOCK);
1252 if (fZoneStrings == NULL) {
1253 if (fLocaleZoneStrings == NULL) {
1254 ((DateFormatSymbols*)this)->initZoneStringsArray();
1255 }
1256 result = (const UnicodeString**)fLocaleZoneStrings;
1257 } else {
1258 result = (const UnicodeString**)fZoneStrings;
1259 }
1260 rowCount = fZoneStringsRowCount;
1261 columnCount = fZoneStringsColCount;
1262 umtx_unlock(&LOCK);
1263
1264 return result;
1265}
1266
1267// For now, we include all zones
1268#define ZONE_SET UCAL_ZONE_TYPE_ANY
1269
1270// This code must be called within a synchronized block
1271void
1272DateFormatSymbols::initZoneStringsArray(void) {
1273 if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
1274 return;
1275 }
1276
1277 UErrorCode status = U_ZERO_ERROR;
1278
1279 StringEnumeration *tzids = NULL;
1280 UnicodeString ** zarray = NULL;
1281 TimeZoneNames *tzNames = NULL;
1282 int32_t rows = 0;
1283
1284 static const UTimeZoneNameType TYPES[] = {
1285 UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
1286 UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
1287 };
1288 static const int32_t NUM_TYPES = 4;
1289
1290 do { // dummy do-while
1291
1292 tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
1293 rows = tzids->count(status);
1294 if (U_FAILURE(status)) {
1295 break;
1296 }
1297
1298 // Allocate array
1299 int32_t size = rows * sizeof(UnicodeString*);
1300 zarray = (UnicodeString**)uprv_malloc(size);
1301 if (zarray == NULL) {
1302 status = U_MEMORY_ALLOCATION_ERROR;
1303 break;
1304 }
1305 uprv_memset(zarray, 0, size);
1306
1307 tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1308 tzNames->loadAllDisplayNames(status);
1309 if (U_FAILURE(status)) { break; }
1310
1311 const UnicodeString *tzid;
1312 int32_t i = 0;
1313 UDate now = Calendar::getNow();
1314 UnicodeString tzDispName;
1315
1316 while ((tzid = tzids->snext(status)) != 0) {
1317 if (U_FAILURE(status)) {
1318 break;
1319 }
1320
1321 zarray[i] = new UnicodeString[5];
1322 if (zarray[i] == NULL) {
1323 status = U_MEMORY_ALLOCATION_ERROR;
1324 break;
1325 }
1326
1327 zarray[i][0].setTo(*tzid);
1328 tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
1329 i++;
1330 }
1331
1332 } while (FALSE);
1333
1334 if (U_FAILURE(status)) {
1335 if (zarray) {
1336 for (int32_t i = 0; i < rows; i++) {
1337 if (zarray[i]) {
1338 delete[] zarray[i];
1339 }
1340 }
1341 uprv_free(zarray);
1342 zarray = NULL;
1343 }
1344 }
1345
1346 if (tzNames) {
1347 delete tzNames;
1348 }
1349 if (tzids) {
1350 delete tzids;
1351 }
1352
1353 fLocaleZoneStrings = zarray;
1354 fZoneStringsRowCount = rows;
1355 fZoneStringsColCount = 1 + NUM_TYPES;
1356}
1357
1358void
1359DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1360{
1361 // since deleting a 2-d array is a pain in the butt, we offload that task to
1362 // a separate function
1363 disposeZoneStrings();
1364 // we always own the new list, which we create here (we duplicate rather
1365 // than adopting the list passed in)
1366 fZoneStringsRowCount = rowCount;
1367 fZoneStringsColCount = columnCount;
1368 createZoneStrings((const UnicodeString**)strings);
1369}
1370
1371//------------------------------------------------------
1372
1373const char16_t * U_EXPORT2
1374DateFormatSymbols::getPatternUChars(void)
1375{
1376 return gPatternChars;
1377}
1378
1379UDateFormatField U_EXPORT2
1380DateFormatSymbols::getPatternCharIndex(UChar c) {
1381 const UChar *p = u_strchr(gPatternChars, c);
1382 if (p == NULL) {
1383 return UDAT_FIELD_COUNT;
1384 } else {
1385 return static_cast<UDateFormatField>(p - gPatternChars);
1386 }
1387}
1388
1389static const uint64_t kNumericFieldsAlways =
1390 ((uint64_t)1 << UDAT_YEAR_FIELD) | // y
1391 ((uint64_t)1 << UDAT_DATE_FIELD) | // d
1392 ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) | // k
1393 ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) | // H
1394 ((uint64_t)1 << UDAT_MINUTE_FIELD) | // m
1395 ((uint64_t)1 << UDAT_SECOND_FIELD) | // s
1396 ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) | // S
1397 ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) | // D
1398 ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) | // F
1399 ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) | // w
1400 ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) | // W
1401 ((uint64_t)1 << UDAT_HOUR1_FIELD) | // h
1402 ((uint64_t)1 << UDAT_HOUR0_FIELD) | // K
1403 ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) | // Y
1404 ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) | // u
1405 ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) | // g
1406 ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) | // A
1407 ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD); // r
1408
1409static const uint64_t kNumericFieldsForCount12 =
1410 ((uint64_t)1 << UDAT_MONTH_FIELD) | // M or MM
1411 ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) | // e or ee
1412 ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) | // c or cc
1413 ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) | // L or LL
1414 ((uint64_t)1 << UDAT_QUARTER_FIELD) | // Q or QQ
1415 ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD); // q or qq
1416
1417UBool U_EXPORT2
1418DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1419 if (f == UDAT_FIELD_COUNT) {
1420 return FALSE;
1421 }
1422 uint64_t flag = ((uint64_t)1 << f);
1423 return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1424}
1425
1426UBool U_EXPORT2
1427DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1428 return isNumericField(getPatternCharIndex(c), count);
1429}
1430
1431//------------------------------------------------------
1432
1433UnicodeString&
1434DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1435{
1436 // fastCopyFrom() - see assignArray comments
1437 return result.fastCopyFrom(fLocalPatternChars);
1438}
1439
1440//------------------------------------------------------
1441
1442void
1443DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1444{
1445 fLocalPatternChars = newLocalPatternChars;
1446}
1447
1448//------------------------------------------------------
1449
1450namespace {
1451
1452// Constants declarations
1453static const UChar kCalendarAliasPrefixUChar[] = {
1454 SOLIDUS, CAP_L, CAP_O, CAP_C, CAP_A, CAP_L, CAP_E, SOLIDUS,
1455 LOW_C, LOW_A, LOW_L, LOW_E, LOW_N, LOW_D, LOW_A, LOW_R, SOLIDUS
1456};
1457static const UChar kGregorianTagUChar[] = {
1458 LOW_G, LOW_R, LOW_E, LOW_G, LOW_O, LOW_R, LOW_I, LOW_A, LOW_N
1459};
1460static const UChar kVariantTagUChar[] = {
1461 PERCENT, LOW_V, LOW_A, LOW_R, LOW_I, LOW_A, LOW_N, LOW_T
1462};
1463static const UChar kLeapTagUChar[] = {
1464 LOW_L, LOW_E, LOW_A, LOW_P
1465};
1466static const UChar kCyclicNameSetsTagUChar[] = {
1467 LOW_C, LOW_Y, LOW_C, LOW_L, LOW_I, LOW_C, CAP_N, LOW_A, LOW_M, LOW_E, CAP_S, LOW_E, LOW_T, LOW_S
1468};
1469static const UChar kYearsTagUChar[] = {
1470 SOLIDUS, LOW_Y, LOW_E, LOW_A, LOW_R, LOW_S
1471};
1472static const UChar kZodiacsUChar[] = {
1473 SOLIDUS, LOW_Z, LOW_O, LOW_D, LOW_I, LOW_A, LOW_C, LOW_S
1474};
1475static const UChar kDayPartsTagUChar[] = {
1476 SOLIDUS, LOW_D, LOW_A, LOW_Y, CAP_P, LOW_A, LOW_R, LOW_T, LOW_S
1477};
1478static const UChar kFormatTagUChar[] = {
1479 SOLIDUS, LOW_F, LOW_O, LOW_R, LOW_M, LOW_A, LOW_T
1480};
1481static const UChar kAbbrTagUChar[] = {
1482 SOLIDUS, LOW_A, LOW_B, LOW_B, LOW_R, LOW_E, LOW_V, LOW_I, LOW_A, LOW_T, LOW_E, LOW_D
1483};
1484
1485// ResourceSink to enumerate all calendar resources
1486struct CalendarDataSink : public ResourceSink {
1487
1488 // Enum which specifies the type of alias received, or no alias
1489 enum AliasType {
1490 SAME_CALENDAR,
1491 DIFFERENT_CALENDAR,
1492 GREGORIAN,
1493 NONE
1494 };
1495
1496 // Data structures to store resources from the current resource bundle
1497 Hashtable arrays;
1498 Hashtable arraySizes;
1499 Hashtable maps;
1500 /**
1501 * Whenever there are aliases, the same object will be added twice to 'map'.
1502 * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
1503 * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
1504 */
1505 MemoryPool<Hashtable> mapRefs;
1506
1507 // Paths and the aliases they point to
1508 UVector aliasPathPairs;
1509
1510 // Current and next calendar resource table which should be loaded
1511 UnicodeString currentCalendarType;
1512 UnicodeString nextCalendarType;
1513
1514 // Resources to visit when enumerating fallback calendars
1515 LocalPointer<UVector> resourcesToVisit;
1516
1517 // Alias' relative path populated whenever an alias is read
1518 UnicodeString aliasRelativePath;
1519
1520 // Initializes CalendarDataSink with default values
1521 CalendarDataSink(UErrorCode& status)
1522 : arrays(FALSE, status), arraySizes(FALSE, status), maps(FALSE, status),
1523 mapRefs(),
1524 aliasPathPairs(uprv_deleteUObject, uhash_compareUnicodeString, status),
1525 currentCalendarType(), nextCalendarType(),
1526 resourcesToVisit(NULL), aliasRelativePath() {
1527 if (U_FAILURE(status)) { return; }
1528 }
1529 virtual ~CalendarDataSink();
1530
1531 // Configure the CalendarSink to visit all the resources
1532 void visitAllResources() {
1533 resourcesToVisit.adoptInstead(NULL);
1534 }
1535
1536 // Actions to be done before enumerating
1537 void preEnumerate(const UnicodeString &calendarType) {
1538 currentCalendarType = calendarType;
1539 nextCalendarType.setToBogus();
1540 aliasPathPairs.removeAllElements();
1541 }
1542
1543 virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
1544 if (U_FAILURE(errorCode)) { return; }
1545 U_ASSERT(!currentCalendarType.isEmpty());
1546
1547 // Stores the resources to visit on the next calendar.
1548 LocalPointer<UVector> resourcesToVisitNext(NULL);
1549 ResourceTable calendarData = value.getTable(errorCode);
1550 if (U_FAILURE(errorCode)) { return; }
1551
1552 // Enumerate all resources for this calendar
1553 for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
1554 UnicodeString keyUString(key, -1, US_INV);
1555
1556 // == Handle aliases ==
1557 AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
1558 if (U_FAILURE(errorCode)) { return; }
1559 if (aliasType == GREGORIAN) {
1560 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
1561 continue;
1562
1563 } else if (aliasType == DIFFERENT_CALENDAR) {
1564 // Whenever an alias to the next calendar (except gregorian) is encountered, register the
1565 // calendar type it's pointing to
1566 if (resourcesToVisitNext.isNull()) {
1567 resourcesToVisitNext
1568 .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
1569 errorCode);
1570 if (U_FAILURE(errorCode)) { return; }
1571 }
1572 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1573 resourcesToVisitNext->addElement(aliasRelativePathCopy.getAlias(), errorCode);
1574 if (U_FAILURE(errorCode)) { return; }
1575 // Only release ownership after resourcesToVisitNext takes it (no error happened):
1576 aliasRelativePathCopy.orphan();
1577 continue;
1578
1579 } else if (aliasType == SAME_CALENDAR) {
1580 // Register same-calendar alias
1581 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
1582 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1583 aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
1584 if (U_FAILURE(errorCode)) { return; }
1585 // Only release ownership after aliasPathPairs takes it (no error happened):
1586 aliasRelativePathCopy.orphan();
1587 LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode);
1588 aliasPathPairs.addElement(keyUStringCopy.getAlias(), errorCode);
1589 if (U_FAILURE(errorCode)) { return; }
1590 // Only release ownership after aliasPathPairs takes it (no error happened):
1591 keyUStringCopy.orphan();
1592 }
1593 continue;
1594 }
1595
1596 // Only visit the resources that were referenced by an alias on the previous calendar
1597 // (AmPmMarkersAbbr is an exception).
1598 if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1599 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1600
1601 // == Handle data ==
1602 if (uprv_strcmp(key, gAmPmMarkersTag) == 0
1603 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
1604 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1605 if (arrays.get(keyUString) == NULL) {
1606 ResourceArray resourceArray = value.getArray(errorCode);
1607 int32_t arraySize = resourceArray.getSize();
1608 LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1609 value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1610 arrays.put(keyUString, stringArray.orphan(), errorCode);
1611 arraySizes.puti(keyUString, arraySize, errorCode);
1612 if (U_FAILURE(errorCode)) { return; }
1613 }
1614 } else if (uprv_strcmp(key, gErasTag) == 0
1615 || uprv_strcmp(key, gDayNamesTag) == 0
1616 || uprv_strcmp(key, gMonthNamesTag) == 0
1617 || uprv_strcmp(key, gQuartersTag) == 0
1618 || uprv_strcmp(key, gDayPeriodTag) == 0
1619 || uprv_strcmp(key, gMonthPatternsTag) == 0
1620 || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
1621 processResource(keyUString, key, value, errorCode);
1622 }
1623 }
1624
1625 // Apply same-calendar aliases
1626 UBool modified;
1627 do {
1628 modified = false;
1629 for (int32_t i = 0; i < aliasPathPairs.size();) {
1630 UBool mod = false;
1631 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
1632 UnicodeString *aliasArray;
1633 Hashtable *aliasMap;
1634 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
1635 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1636 if (arrays.get(*path) == NULL) {
1637 // Clone the array
1638 int32_t aliasArraySize = arraySizes.geti(*alias);
1639 LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1640 if (U_FAILURE(errorCode)) { return; }
1641 uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1642 // Put the array on the 'arrays' map
1643 arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1644 arraySizes.puti(*path, aliasArraySize, errorCode);
1645 }
1646 if (U_FAILURE(errorCode)) { return; }
1647 mod = true;
1648 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
1649 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1650 if (maps.get(*path) == NULL) {
1651 maps.put(*path, aliasMap, errorCode);
1652 }
1653 if (U_FAILURE(errorCode)) { return; }
1654 mod = true;
1655 }
1656 if (mod) {
1657 aliasPathPairs.removeElementAt(i + 1);
1658 aliasPathPairs.removeElementAt(i);
1659 modified = true;
1660 } else {
1661 i += 2;
1662 }
1663 }
1664 } while (modified && !aliasPathPairs.isEmpty());
1665
1666 // Set the resources to visit on the next calendar
1667 if (!resourcesToVisitNext.isNull()) {
1668 resourcesToVisit = std::move(resourcesToVisitNext);
1669 }
1670 }
1671
1672 // Process the nested resource bundle tables
1673 void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1674 if (U_FAILURE(errorCode)) return;
1675
1676 ResourceTable table = value.getTable(errorCode);
1677 if (U_FAILURE(errorCode)) return;
1678 Hashtable* stringMap = NULL;
1679
1680 // Iterate over all the elements of the table and add them to the map
1681 for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1682 UnicodeString keyUString(key, -1, US_INV);
1683
1684 // Ignore '%variant' keys
1685 if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
1686 continue;
1687 }
1688
1689 // == Handle String elements ==
1690 if (value.getType() == URES_STRING) {
1691 // We are on a leaf, store the map elements into the stringMap
1692 if (i == 0) {
1693 // mapRefs will keep ownership of 'stringMap':
1694 stringMap = mapRefs.create(FALSE, errorCode);
1695 if (stringMap == NULL) {
1696 errorCode = U_MEMORY_ALLOCATION_ERROR;
1697 return;
1698 }
1699 maps.put(path, stringMap, errorCode);
1700 if (U_FAILURE(errorCode)) { return; }
1701 stringMap->setValueDeleter(uprv_deleteUObject);
1702 }
1703 U_ASSERT(stringMap != NULL);
1704 int32_t valueStringSize;
1705 const UChar *valueString = value.getString(valueStringSize, errorCode);
1706 if (U_FAILURE(errorCode)) { return; }
1707 LocalPointer<UnicodeString> valueUString(new UnicodeString(TRUE, valueString, valueStringSize), errorCode);
1708 stringMap->put(keyUString, valueUString.orphan(), errorCode);
1709 if (U_FAILURE(errorCode)) { return; }
1710 continue;
1711 }
1712 U_ASSERT(stringMap == NULL);
1713
1714 // Store the current path's length and append the current key to the path.
1715 int32_t pathLength = path.length();
1716 path.append(SOLIDUS).append(keyUString);
1717
1718 // In cyclicNameSets ignore everything but years/format/abbreviated
1719 // and zodiacs/format/abbreviated
1720 if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
1721 UBool skip = TRUE;
1722 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
1723 int32_t length = 0;
1724 if (startIndex == path.length()
1725 || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
1726 || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
1727 || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
1728 startIndex += length;
1729 length = 0;
1730 if (startIndex == path.length()
1731 || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
1732 startIndex += length;
1733 length = 0;
1734 if (startIndex == path.length()
1735 || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
1736 skip = FALSE;
1737 }
1738 }
1739 }
1740 if (skip) {
1741 // Drop the latest key on the path and continue
1742 path.retainBetween(0, pathLength);
1743 continue;
1744 }
1745 }
1746
1747 // == Handle aliases ==
1748 if (arrays.get(path) != NULL || maps.get(path) != NULL) {
1749 // Drop the latest key on the path and continue
1750 path.retainBetween(0, pathLength);
1751 continue;
1752 }
1753
1754 AliasType aliasType = processAliasFromValue(path, value, errorCode);
1755 if (U_FAILURE(errorCode)) { return; }
1756 if (aliasType == SAME_CALENDAR) {
1757 // Store the alias path and the current path on aliasPathPairs
1758 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1759 aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
1760 if (U_FAILURE(errorCode)) { return; }
1761 // Only release ownership after aliasPathPairs takes it (no error happened):
1762 aliasRelativePathCopy.orphan();
1763 LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode);
1764 aliasPathPairs.addElement(pathCopy.getAlias(), errorCode);
1765 if (U_FAILURE(errorCode)) { return; }
1766 // Only release ownership after aliasPathPairs takes it (no error happened):
1767 pathCopy.orphan();
1768
1769 // Drop the latest key on the path and continue
1770 path.retainBetween(0, pathLength);
1771 continue;
1772 }
1773 U_ASSERT(aliasType == NONE);
1774
1775 // == Handle data ==
1776 if (value.getType() == URES_ARRAY) {
1777 // We are on a leaf, store the array
1778 ResourceArray rDataArray = value.getArray(errorCode);
1779 int32_t dataArraySize = rDataArray.getSize();
1780 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1781 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1782 arrays.put(path, dataArray.orphan(), errorCode);
1783 arraySizes.puti(path, dataArraySize, errorCode);
1784 if (U_FAILURE(errorCode)) { return; }
1785 } else if (value.getType() == URES_TABLE) {
1786 // We are not on a leaf, recursively process the subtable.
1787 processResource(path, key, value, errorCode);
1788 if (U_FAILURE(errorCode)) { return; }
1789 }
1790
1791 // Drop the latest key on the path
1792 path.retainBetween(0, pathLength);
1793 }
1794 }
1795
1796 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
1797 AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
1798 UErrorCode &errorCode) {
1799 if (U_FAILURE(errorCode)) { return NONE; }
1800
1801 if (value.getType() == URES_ALIAS) {
1802 int32_t aliasPathSize;
1803 const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1804 if (U_FAILURE(errorCode)) { return NONE; }
1805 UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1806 const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
1807 if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1808 && aliasPath.length() > aliasPrefixLength) {
1809 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
1810 if (typeLimit > aliasPrefixLength) {
1811 const UnicodeString aliasCalendarType =
1812 aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1813 aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1814
1815 if (currentCalendarType == aliasCalendarType
1816 && currentRelativePath != aliasRelativePath) {
1817 // If we have an alias to the same calendar, the path to the resource must be different
1818 return SAME_CALENDAR;
1819
1820 } else if (currentCalendarType != aliasCalendarType
1821 && currentRelativePath == aliasRelativePath) {
1822 // If we have an alias to a different calendar, the path to the resource must be the same
1823 if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
1824 return GREGORIAN;
1825 } else if (nextCalendarType.isBogus()) {
1826 nextCalendarType = aliasCalendarType;
1827 return DIFFERENT_CALENDAR;
1828 } else if (nextCalendarType == aliasCalendarType) {
1829 return DIFFERENT_CALENDAR;
1830 }
1831 }
1832 }
1833 }
1834 errorCode = U_INTERNAL_PROGRAM_ERROR;
1835 return NONE;
1836 }
1837 return NONE;
1838 }
1839
1840 // Deleter function to be used by 'arrays'
1841 static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1842 delete[] static_cast<UnicodeString *>(uArray);
1843 }
1844};
1845// Virtual destructors have to be defined out of line
1846CalendarDataSink::~CalendarDataSink() {
1847 arrays.setValueDeleter(deleteUnicodeStringArray);
1848}
1849}
1850
1851//------------------------------------------------------
1852
1853static void
1854initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1855 if (U_SUCCESS(status)) {
1856 length = numStr;
1857 *field = newUnicodeStringArray((size_t)numStr);
1858 if (*field) {
1859 for(int32_t i = 0; i<length; i++) {
1860 // readonly aliases - all "data" strings are constant
1861 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1862 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1863 }
1864 }
1865 else {
1866 length = 0;
1867 status = U_MEMORY_ALLOCATION_ERROR;
1868 }
1869 }
1870}
1871
1872static void
1873initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1874 if (U_SUCCESS(status)) {
1875 UnicodeString keyUString(key.data(), -1, US_INV);
1876 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1877
1878 if (array != NULL) {
1879 length = sink.arraySizes.geti(keyUString);
1880 *field = array;
1881 // DateFormatSymbols takes ownership of the array:
1882 sink.arrays.remove(keyUString);
1883 } else {
1884 length = 0;
1885 status = U_MISSING_RESOURCE_ERROR;
1886 }
1887 }
1888}
1889
1890static void
1891initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1892 if (U_SUCCESS(status)) {
1893 UnicodeString keyUString(key.data(), -1, US_INV);
1894 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1895
1896 if (array != NULL) {
1897 int32_t arrayLength = sink.arraySizes.geti(keyUString);
1898 length = arrayLength + arrayOffset;
1899 *field = new UnicodeString[length];
1900 if (*field == NULL) {
1901 status = U_MEMORY_ALLOCATION_ERROR;
1902 return;
1903 }
1904 uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1905 } else {
1906 length = 0;
1907 status = U_MISSING_RESOURCE_ERROR;
1908 }
1909 }
1910}
1911
1912static void
1913initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
1914 field[index].remove();
1915 if (U_SUCCESS(status)) {
1916 UnicodeString pathUString(path.data(), -1, US_INV);
1917 Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
1918 if (leapMonthTable != NULL) {
1919 UnicodeString leapLabel(FALSE, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
1920 UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
1921 if (leapMonthPattern != NULL) {
1922 field[index].fastCopyFrom(*leapMonthPattern);
1923 } else {
1924 field[index].setToBogus();
1925 }
1926 return;
1927 }
1928 status = U_MISSING_RESOURCE_ERROR;
1929 }
1930}
1931
1932static CharString
1933&buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
1934 return path.clear().append(segment1, -1, errorCode);
1935}
1936
1937static CharString
1938&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1939 UErrorCode &errorCode) {
1940 return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
1941 .append(segment2, -1, errorCode);
1942}
1943
1944static CharString
1945&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1946 const char* segment3, UErrorCode &errorCode) {
1947 return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
1948 .append(segment3, -1, errorCode);
1949}
1950
1951static CharString
1952&buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1953 const char* segment3, const char* segment4, UErrorCode &errorCode) {
1954 return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
1955 .append(segment4, -1, errorCode);
1956}
1957
1958typedef struct {
1959 const char * usageTypeName;
1960 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1961} ContextUsageTypeNameToEnumValue;
1962
1963static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1964 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1965 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1966 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
1967 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1968 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
1969 { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
1970 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
1971 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
1972 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1973 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1974 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
1975 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1976 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
1977 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
1978 { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1979};
1980
1981// Resource keys to look up localized strings for day periods.
1982// The first one must be midnight and the second must be noon, so that their indices coincide
1983// with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1984static const char *dayPeriodKeys[] = {"midnight", "noon",
1985 "morning1", "afternoon1", "evening1", "night1",
1986 "morning2", "afternoon2", "evening2", "night2"};
1987
1988UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
1989 int32_t &stringCount, UErrorCode &status) {
1990 if (U_FAILURE(status)) { return NULL; }
1991
1992 UnicodeString pathUString(path.data(), -1, US_INV);
1993 Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
1994
1995 stringCount = UPRV_LENGTHOF(dayPeriodKeys);
1996 UnicodeString *strings = new UnicodeString[stringCount];
1997 if (strings == NULL) {
1998 status = U_MEMORY_ALLOCATION_ERROR;
1999 return NULL;
2000 }
2001
2002 if (map != NULL) {
2003 for (int32_t i = 0; i < stringCount; ++i) {
2004 UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
2005 UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2006 if (dayPeriod != NULL) {
2007 strings[i].fastCopyFrom(*dayPeriod);
2008 } else {
2009 strings[i].setToBogus();
2010 }
2011 }
2012 } else {
2013 for (int32_t i = 0; i < stringCount; i++) {
2014 strings[i].setToBogus();
2015 }
2016 }
2017 return strings;
2018}
2019
2020
2021void
2022DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2023{
2024 int32_t len = 0;
2025 /* In case something goes wrong, initialize all of the data to NULL. */
2026 fEras = NULL;
2027 fErasCount = 0;
2028 fEraNames = NULL;
2029 fEraNamesCount = 0;
2030 fNarrowEras = NULL;
2031 fNarrowErasCount = 0;
2032 fMonths = NULL;
2033 fMonthsCount=0;
2034 fShortMonths = NULL;
2035 fShortMonthsCount=0;
2036 fNarrowMonths = NULL;
2037 fNarrowMonthsCount=0;
2038 fStandaloneMonths = NULL;
2039 fStandaloneMonthsCount=0;
2040 fStandaloneShortMonths = NULL;
2041 fStandaloneShortMonthsCount=0;
2042 fStandaloneNarrowMonths = NULL;
2043 fStandaloneNarrowMonthsCount=0;
2044 fWeekdays = NULL;
2045 fWeekdaysCount=0;
2046 fShortWeekdays = NULL;
2047 fShortWeekdaysCount=0;
2048 fShorterWeekdays = NULL;
2049 fShorterWeekdaysCount=0;
2050 fNarrowWeekdays = NULL;
2051 fNarrowWeekdaysCount=0;
2052 fStandaloneWeekdays = NULL;
2053 fStandaloneWeekdaysCount=0;
2054 fStandaloneShortWeekdays = NULL;
2055 fStandaloneShortWeekdaysCount=0;
2056 fStandaloneShorterWeekdays = NULL;
2057 fStandaloneShorterWeekdaysCount=0;
2058 fStandaloneNarrowWeekdays = NULL;
2059 fStandaloneNarrowWeekdaysCount=0;
2060 fAmPms = NULL;
2061 fAmPmsCount=0;
2062 fNarrowAmPms = NULL;
2063 fNarrowAmPmsCount=0;
2064 fTimeSeparator.setToBogus();
2065 fQuarters = NULL;
2066 fQuartersCount = 0;
2067 fShortQuarters = NULL;
2068 fShortQuartersCount = 0;
2069 fStandaloneQuarters = NULL;
2070 fStandaloneQuartersCount = 0;
2071 fStandaloneShortQuarters = NULL;
2072 fStandaloneShortQuartersCount = 0;
2073 fLeapMonthPatterns = NULL;
2074 fLeapMonthPatternsCount = 0;
2075 fShortYearNames = NULL;
2076 fShortYearNamesCount = 0;
2077 fShortZodiacNames = NULL;
2078 fShortZodiacNamesCount = 0;
2079 fZoneStringsRowCount = 0;
2080 fZoneStringsColCount = 0;
2081 fZoneStrings = NULL;
2082 fLocaleZoneStrings = NULL;
2083 fAbbreviatedDayPeriods = NULL;
2084 fAbbreviatedDayPeriodsCount = 0;
2085 fWideDayPeriods = NULL;
2086 fWideDayPeriodsCount = 0;
2087 fNarrowDayPeriods = NULL;
2088 fNarrowDayPeriodsCount = 0;
2089 fStandaloneAbbreviatedDayPeriods = NULL;
2090 fStandaloneAbbreviatedDayPeriodsCount = 0;
2091 fStandaloneWideDayPeriods = NULL;
2092 fStandaloneWideDayPeriodsCount = 0;
2093 fStandaloneNarrowDayPeriods = NULL;
2094 fStandaloneNarrowDayPeriodsCount = 0;
2095 uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
2096
2097 // We need to preserve the requested locale for
2098 // lazy ZoneStringFormat instantiation. ZoneStringFormat
2099 // is region sensitive, thus, bundle locale bundle's locale
2100 // is not sufficient.
2101 fZSFLocale = locale;
2102
2103 if (U_FAILURE(status)) return;
2104
2105 // Create a CalendarDataSink to process this data and the resouce bundles
2106 CalendarDataSink calendarSink(status);
2107 UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
2108 UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
2109
2110 if (U_FAILURE(status)) return;
2111
2112 // Iterate over the resource bundle data following the fallbacks through different calendar types
2113 UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
2114 while (!calendarType.isBogus()) {
2115 CharString calendarTypeBuffer;
2116 calendarTypeBuffer.appendInvariantChars(calendarType, status);
2117 if (U_FAILURE(status)) { return; }
2118 const char *calendarTypeCArray = calendarTypeBuffer.data();
2119
2120 // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2121 UErrorCode oldStatus = status;
2122 UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
2123 if (status == U_MISSING_RESOURCE_ERROR) {
2124 ures_close(ctb);
2125 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
2126 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2127 calendarSink.visitAllResources();
2128 status = oldStatus;
2129 continue;
2130 }
2131 return;
2132 }
2133
2134 calendarSink.preEnumerate(calendarType);
2135 ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
2136 ures_close(ctb);
2137 if (U_FAILURE(status)) break;
2138
2139 // Stop loading when gregorian was loaded
2140 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2141 break;
2142 }
2143
2144 // Get the next calendar type to process from the sink
2145 calendarType = calendarSink.nextCalendarType;
2146
2147 // Gregorian is always the last fallback
2148 if (calendarType.isBogus()) {
2149 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2150 calendarSink.visitAllResources();
2151 }
2152 }
2153
2154 // CharString object to build paths
2155 CharString path;
2156
2157 // Load Leap Month Patterns
2158 UErrorCode tempStatus = status;
2159 fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2160 if (fLeapMonthPatterns) {
2161 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2162 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2163 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2164 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2165 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2166 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2167 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2168 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2169 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2170 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2171 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2172 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2173 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2174 buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2175 if (U_SUCCESS(tempStatus)) {
2176 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2177 // The ordering of the following statements is important.
2178 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
2179 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2180 }
2181 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
2182 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
2183 }
2184 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
2185 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2186 }
2187 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
2188 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
2189 }
2190 // end of hack
2191 fLeapMonthPatternsCount = kMonthPatternsCount;
2192 } else {
2193 delete[] fLeapMonthPatterns;
2194 fLeapMonthPatterns = NULL;
2195 }
2196 }
2197
2198 // Load cyclic names sets
2199 tempStatus = status;
2200 initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2201 buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2202 initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2203 buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2204
2205 // Load context transforms and capitalization
2206 tempStatus = U_ZERO_ERROR;
2207 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
2208 if (U_SUCCESS(tempStatus)) {
2209 UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
2210 if (U_SUCCESS(tempStatus)) {
2211 UResourceBundle *contextTransformUsage;
2212 while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
2213 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
2214 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
2215 const char* usageType = ures_getKey(contextTransformUsage);
2216 if (usageType != NULL) {
2217 const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2218 int32_t compResult = 0;
2219 // linear search; list is short and we cannot be sure that bsearch is available
2220 while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2221 ++typeMapPtr;
2222 }
2223 if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
2224 fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2225 fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2226 }
2227 }
2228 }
2229 tempStatus = U_ZERO_ERROR;
2230 ures_close(contextTransformUsage);
2231 }
2232 ures_close(contextTransforms);
2233 }
2234
2235 tempStatus = U_ZERO_ERROR;
2236 const LocalPointer<NumberingSystem> numberingSystem(
2237 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2238 if (U_SUCCESS(tempStatus)) {
2239 // These functions all fail gracefully if passed NULL pointers and
2240 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2241 // to check for errors once after all calls are made.
2242 const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
2243 localeBundle, gNumberElementsTag, NULL, &tempStatus));
2244 const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
2245 numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
2246 const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
2247 nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
2248 fTimeSeparator = ures_getUnicodeStringByKey(
2249 symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2250 if (U_FAILURE(tempStatus)) {
2251 fTimeSeparator.setToBogus();
2252 }
2253 }
2254
2255 ures_close(localeBundle);
2256 }
2257
2258 if (fTimeSeparator.isBogus()) {
2259 fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2260 }
2261
2262 // Load day periods
2263 fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2264 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2265 fWideDayPeriodsCount, status);
2266 fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2267 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2268 fNarrowDayPeriodsCount, status);
2269 fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2270 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2271 fAbbreviatedDayPeriodsCount, status);
2272 fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2273 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2274 fStandaloneWideDayPeriodsCount, status);
2275 fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2276 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2277 fStandaloneNarrowDayPeriodsCount, status);
2278 fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2279 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2280 fStandaloneAbbreviatedDayPeriodsCount, status);
2281
2282 U_LOCALE_BASED(locBased, *this);
2283 // if we make it to here, the resource data is cool, and we can get everything out
2284 // of it that we need except for the time-zone and localized-pattern data, which
2285 // are stored in a separate file
2286 locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
2287 ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
2288
2289 // Load eras
2290 initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
2291 UErrorCode oldStatus = status;
2292 initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
2293 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2294 status = oldStatus;
2295 assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
2296 }
2297 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2298 oldStatus = status;
2299 initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
2300 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2301 status = oldStatus;
2302 assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
2303 }
2304
2305 // Load month names
2306 initField(&fMonths, fMonthsCount, calendarSink,
2307 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2308 initField(&fShortMonths, fShortMonthsCount, calendarSink,
2309 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2310 initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2311 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2312 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
2313 status = U_ZERO_ERROR;
2314 assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
2315 }
2316 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2317 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2318 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
2319 status = U_ZERO_ERROR;
2320 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
2321 }
2322
2323 UErrorCode narrowMonthsEC = status;
2324 UErrorCode standaloneNarrowMonthsEC = status;
2325 initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2326 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2327 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2328 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2329 if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
2330 // If format/narrow not available, use standalone/narrow
2331 assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
2332 } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2333 // If standalone/narrow not availabe, use format/narrow
2334 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
2335 } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2336 // If neither is available, use format/abbreviated
2337 assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2338 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2339 }
2340
2341 // Load AM/PM markers; if wide or narrow not available, use short
2342 UErrorCode ampmStatus = U_ZERO_ERROR;
2343 initField(&fAmPms, fAmPmsCount, calendarSink,
2344 buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2345 if (U_FAILURE(ampmStatus)) {
2346 initField(&fAmPms, fAmPmsCount, calendarSink,
2347 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2348 }
2349 ampmStatus = U_ZERO_ERROR;
2350 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2351 buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2352 if (U_FAILURE(ampmStatus)) {
2353 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2354 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2355 }
2356
2357 // Load quarters
2358 initField(&fQuarters, fQuartersCount, calendarSink,
2359 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2360 initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2361 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2362
2363 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2364 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2365 if(status == U_MISSING_RESOURCE_ERROR) {
2366 status = U_ZERO_ERROR;
2367 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2368 }
2369 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2370 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2371 if(status == U_MISSING_RESOURCE_ERROR) {
2372 status = U_ZERO_ERROR;
2373 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
2374 }
2375
2376 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2377 /*
2378 // fastCopyFrom()/setTo() - see assignArray comments
2379 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2380 fLocalPatternChars.setTo(TRUE, resStr, len);
2381 // If the locale data does not include new pattern chars, use the defaults
2382 // TODO: Consider making this an error, since this may add conflicting characters.
2383 if (len < PATTERN_CHARS_LEN) {
2384 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2385 }
2386 */
2387 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2388
2389 // Format wide weekdays -> fWeekdays
2390 // {sfb} fixed to handle 1-based weekdays
2391 initField(&fWeekdays, fWeekdaysCount, calendarSink,
2392 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2393
2394 // Format abbreviated weekdays -> fShortWeekdays
2395 initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2396 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2397
2398 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2399 initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2400 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2401 if (status == U_MISSING_RESOURCE_ERROR) {
2402 status = U_ZERO_ERROR;
2403 assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2404 }
2405
2406 // Stand-alone wide weekdays -> fStandaloneWeekdays
2407 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2408 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2409 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
2410 status = U_ZERO_ERROR;
2411 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
2412 }
2413
2414 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2415 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2416 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2417 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
2418 status = U_ZERO_ERROR;
2419 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2420 }
2421
2422 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2423 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2424 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2425 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
2426 status = U_ZERO_ERROR;
2427 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
2428 }
2429
2430 // Format narrow weekdays -> fNarrowWeekdays
2431 UErrorCode narrowWeeksEC = status;
2432 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2433 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2434 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2435 UErrorCode standaloneNarrowWeeksEC = status;
2436 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2437 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2438
2439 if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
2440 // If format/narrow not available, use standalone/narrow
2441 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
2442 } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
2443 // If standalone/narrow not available, use format/narrow
2444 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
2445 } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
2446 // If neither is available, use format/abbreviated
2447 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2448 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2449 }
2450
2451 // Last resort fallback in case previous data wasn't loaded
2452 if (U_FAILURE(status))
2453 {
2454 if (useLastResortData)
2455 {
2456 // Handle the case in which there is no resource data present.
2457 // We don't have to generate usable patterns in this situation;
2458 // we just need to produce something that will be semi-intelligible
2459 // in most locales.
2460
2461 status = U_USING_FALLBACK_WARNING;
2462 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2463 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2464 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2465 initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2466 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2467 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2468 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2469 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2470 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2471 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2472 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2473 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2474 initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2475 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2476 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2477 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2478 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2479 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2480 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2481 initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2482 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2483 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2484 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2485 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2486 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2487 }
2488 }
2489
2490 // Close resources
2491 ures_close(cb);
2492 ures_close(rb);
2493}
2494
2495Locale
2496DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
2497 U_LOCALE_BASED(locBased, *this);
2498 return locBased.getLocale(type, status);
2499}
2500
2501U_NAMESPACE_END
2502
2503#endif /* #if !UCONFIG_NO_FORMATTING */
2504
2505//eof
2506