1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2016, International Business Machines Corporation and *
6 * others. All Rights Reserved. *
7 *******************************************************************************
11 * Modification History:
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 *******************************************************************************
24 #include "unicode/utypes.h"
26 #if !UCONFIG_NO_FORMATTING
27 #include "unicode/ustring.h"
28 #include "unicode/localpointer.h"
29 #include "unicode/dtfmtsym.h"
30 #include "unicode/smpdtfmt.h"
31 #include "unicode/msgfmt.h"
32 #include "unicode/numsys.h"
33 #include "unicode/tznames.h"
47 #include "shareddateformatsymbols.h"
48 #include "unicode/calendar.h"
49 #include "unifiedcache.h"
51 // *****************************************************************************
52 // class DateFormatSymbols
53 // *****************************************************************************
56 * These are static arrays we use only in the case where we have no
60 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
61 #define PATTERN_CHARS_LEN 38
63 #define PATTERN_CHARS_LEN 37
67 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
68 * locales use the same these unlocalized pattern characters.
70 static const UChar gPatternChars
[] = {
71 // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
72 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
74 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
76 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
77 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
78 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
79 0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
80 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
86 //------------------------------------------------------
87 // Strings of last resort. These are only used if we have no resource
88 // files. They aren't designed for actual use, just for backup.
90 // These are the month names and abbreviations of last resort.
91 static const UChar gLastResortMonthNames
[13][3] =
93 {0x0030, 0x0031, 0x0000}, /* "01" */
94 {0x0030, 0x0032, 0x0000}, /* "02" */
95 {0x0030, 0x0033, 0x0000}, /* "03" */
96 {0x0030, 0x0034, 0x0000}, /* "04" */
97 {0x0030, 0x0035, 0x0000}, /* "05" */
98 {0x0030, 0x0036, 0x0000}, /* "06" */
99 {0x0030, 0x0037, 0x0000}, /* "07" */
100 {0x0030, 0x0038, 0x0000}, /* "08" */
101 {0x0030, 0x0039, 0x0000}, /* "09" */
102 {0x0031, 0x0030, 0x0000}, /* "10" */
103 {0x0031, 0x0031, 0x0000}, /* "11" */
104 {0x0031, 0x0032, 0x0000}, /* "12" */
105 {0x0031, 0x0033, 0x0000} /* "13" */
108 // These are the weekday names and abbreviations of last resort.
109 static const UChar gLastResortDayNames
[8][2] =
111 {0x0030, 0x0000}, /* "0" */
112 {0x0031, 0x0000}, /* "1" */
113 {0x0032, 0x0000}, /* "2" */
114 {0x0033, 0x0000}, /* "3" */
115 {0x0034, 0x0000}, /* "4" */
116 {0x0035, 0x0000}, /* "5" */
117 {0x0036, 0x0000}, /* "6" */
118 {0x0037, 0x0000} /* "7" */
121 // These are the quarter names and abbreviations of last resort.
122 static const UChar gLastResortQuarters
[4][2] =
124 {0x0031, 0x0000}, /* "1" */
125 {0x0032, 0x0000}, /* "2" */
126 {0x0033, 0x0000}, /* "3" */
127 {0x0034, 0x0000}, /* "4" */
130 // These are the am/pm and BC/AD markers of last resort.
131 static const UChar gLastResortAmPmMarkers
[2][3] =
133 {0x0041, 0x004D, 0x0000}, /* "AM" */
134 {0x0050, 0x004D, 0x0000} /* "PM" */
137 static const UChar gLastResortEras
[2][3] =
139 {0x0042, 0x0043, 0x0000}, /* "BC" */
140 {0x0041, 0x0044, 0x0000} /* "AD" */
143 /* Sizes for the last resort string arrays */
144 typedef enum LastResortSize
{
169 SharedDateFormatSymbols::~SharedDateFormatSymbols() {
172 template<> U_I18N_API
173 const SharedDateFormatSymbols
*
174 LocaleCacheKey
<SharedDateFormatSymbols
>::createObject(
175 const void * /*unusedContext*/, UErrorCode
&status
) const {
177 Calendar::getCalendarTypeFromLocale(fLoc
, type
, UPRV_LENGTHOF(type
), status
);
178 if (U_FAILURE(status
)) {
181 SharedDateFormatSymbols
*shared
182 = new SharedDateFormatSymbols(fLoc
, type
, status
);
183 if (shared
== NULL
) {
184 status
= U_MEMORY_ALLOCATION_ERROR
;
187 if (U_FAILURE(status
)) {
195 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols
)
197 #define kSUPPLEMENTAL "supplementalData"
200 * These are the tags we expect to see in normal resource bundle files associated
201 * with a locale and calendar
203 static const char gCalendarTag
[]="calendar";
204 static const char gGregorianTag
[]="gregorian";
205 static const char gErasTag
[]="eras";
206 static const char gCyclicNameSetsTag
[]="cyclicNameSets";
207 static const char gNameSetYearsTag
[]="years";
208 static const char gNameSetZodiacsTag
[]="zodiacs";
209 static const char gMonthNamesTag
[]="monthNames";
210 static const char gMonthPatternsTag
[]="monthPatterns";
211 static const char gDayNamesTag
[]="dayNames";
212 static const char gNamesWideTag
[]="wide";
213 static const char gNamesAbbrTag
[]="abbreviated";
214 static const char gNamesShortTag
[]="short";
215 static const char gNamesNarrowTag
[]="narrow";
216 static const char gNamesAllTag
[]="all";
217 static const char gNamesFormatTag
[]="format";
218 static const char gNamesStandaloneTag
[]="stand-alone";
219 static const char gNamesNumericTag
[]="numeric";
220 static const char gAmPmMarkersTag
[]="AmPmMarkers";
221 static const char gAmPmMarkersAbbrTag
[]="AmPmMarkersAbbr";
222 static const char gAmPmMarkersNarrowTag
[]="AmPmMarkersNarrow";
223 static const char gQuartersTag
[]="quarters";
224 static const char gNumberElementsTag
[]="NumberElements";
225 static const char gSymbolsTag
[]="symbols";
226 static const char gTimeSeparatorTag
[]="timeSeparator";
227 static const char gDayPeriodTag
[]="dayPeriod";
229 // static const char gZoneStringsTag[]="zoneStrings";
231 // static const char gLocalPatternCharsTag[]="localPatternChars";
233 static const char gContextTransformsTag
[]="contextTransforms";
235 static UMutex LOCK
= U_MUTEX_INITIALIZER
;
238 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
241 static inline UnicodeString
* newUnicodeStringArray(size_t count
) {
242 return new UnicodeString
[count
? count
: 1];
245 //------------------------------------------------------
247 DateFormatSymbols
* U_EXPORT2
248 DateFormatSymbols::createForLocale(
249 const Locale
& locale
, UErrorCode
&status
) {
250 const SharedDateFormatSymbols
*shared
= NULL
;
251 UnifiedCache::getByLocale(locale
, shared
, status
);
252 if (U_FAILURE(status
)) {
255 DateFormatSymbols
*result
= new DateFormatSymbols(shared
->get());
257 if (result
== NULL
) {
258 status
= U_MEMORY_ALLOCATION_ERROR
;
264 DateFormatSymbols::DateFormatSymbols(const Locale
& locale
,
268 initializeData(locale
, NULL
, status
);
271 DateFormatSymbols::DateFormatSymbols(UErrorCode
& status
)
274 initializeData(Locale::getDefault(), NULL
, status
, TRUE
);
278 DateFormatSymbols::DateFormatSymbols(const Locale
& locale
,
283 initializeData(locale
, type
, status
);
286 DateFormatSymbols::DateFormatSymbols(const char *type
, UErrorCode
& status
)
289 initializeData(Locale::getDefault(), type
, status
, TRUE
);
292 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols
& other
)
299 DateFormatSymbols::assignArray(UnicodeString
*& dstArray
,
301 const UnicodeString
* srcArray
,
304 // assignArray() is only called by copyData() and initializeData(), which in turn
305 // implements the copy constructor and the assignment operator.
306 // All strings in a DateFormatSymbols object are created in one of the following
307 // three ways that all allow to safely use UnicodeString::fastCopyFrom():
308 // - readonly-aliases from resource bundles
309 // - readonly-aliases or allocated strings from constants
310 // - safely cloned strings (with owned buffers) from setXYZ() functions
312 // Note that this is true for as long as DateFormatSymbols can be constructed
313 // only from a locale bundle or set via the cloning API,
314 // *and* for as long as all the strings are in *private* fields, preventing
315 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
317 dstArray
= newUnicodeStringArray(srcCount
);
318 if(dstArray
!= NULL
) {
320 for(i
=0; i
<srcCount
; ++i
) {
321 dstArray
[i
].fastCopyFrom(srcArray
[i
]);
327 * Create a copy, in fZoneStrings, of the given zone strings array. The
328 * member variables fZoneStringsRowCount and fZoneStringsColCount should
329 * be set already by the caller.
332 DateFormatSymbols::createZoneStrings(const UnicodeString
*const * otherStrings
)
335 UBool failed
= FALSE
;
337 fZoneStrings
= (UnicodeString
**)uprv_malloc(fZoneStringsRowCount
* sizeof(UnicodeString
*));
338 if (fZoneStrings
!= NULL
) {
339 for (row
=0; row
<fZoneStringsRowCount
; ++row
)
341 fZoneStrings
[row
] = newUnicodeStringArray(fZoneStringsColCount
);
342 if (fZoneStrings
[row
] == NULL
) {
346 for (col
=0; col
<fZoneStringsColCount
; ++col
) {
347 // fastCopyFrom() - see assignArray comments
348 fZoneStrings
[row
][col
].fastCopyFrom(otherStrings
[row
][col
]);
352 // If memory allocation failed, roll back and delete fZoneStrings
354 for (int i
= row
; i
>= 0; i
--) {
355 delete[] fZoneStrings
[i
];
357 uprv_free(fZoneStrings
);
363 * Copy all of the other's data to this.
366 DateFormatSymbols::copyData(const DateFormatSymbols
& other
) {
367 UErrorCode status
= U_ZERO_ERROR
;
368 U_LOCALE_BASED(locBased
, *this);
369 locBased
.setLocaleIDs(
370 other
.getLocale(ULOC_VALID_LOCALE
, status
),
371 other
.getLocale(ULOC_ACTUAL_LOCALE
, status
));
372 assignArray(fEras
, fErasCount
, other
.fEras
, other
.fErasCount
);
373 assignArray(fEraNames
, fEraNamesCount
, other
.fEraNames
, other
.fEraNamesCount
);
374 assignArray(fNarrowEras
, fNarrowErasCount
, other
.fNarrowEras
, other
.fNarrowErasCount
);
375 assignArray(fMonths
, fMonthsCount
, other
.fMonths
, other
.fMonthsCount
);
376 assignArray(fShortMonths
, fShortMonthsCount
, other
.fShortMonths
, other
.fShortMonthsCount
);
377 assignArray(fNarrowMonths
, fNarrowMonthsCount
, other
.fNarrowMonths
, other
.fNarrowMonthsCount
);
378 assignArray(fStandaloneMonths
, fStandaloneMonthsCount
, other
.fStandaloneMonths
, other
.fStandaloneMonthsCount
);
379 assignArray(fStandaloneShortMonths
, fStandaloneShortMonthsCount
, other
.fStandaloneShortMonths
, other
.fStandaloneShortMonthsCount
);
380 assignArray(fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
, other
.fStandaloneNarrowMonths
, other
.fStandaloneNarrowMonthsCount
);
381 assignArray(fWeekdays
, fWeekdaysCount
, other
.fWeekdays
, other
.fWeekdaysCount
);
382 assignArray(fShortWeekdays
, fShortWeekdaysCount
, other
.fShortWeekdays
, other
.fShortWeekdaysCount
);
383 assignArray(fShorterWeekdays
, fShorterWeekdaysCount
, other
.fShorterWeekdays
, other
.fShorterWeekdaysCount
);
384 assignArray(fNarrowWeekdays
, fNarrowWeekdaysCount
, other
.fNarrowWeekdays
, other
.fNarrowWeekdaysCount
);
385 assignArray(fStandaloneWeekdays
, fStandaloneWeekdaysCount
, other
.fStandaloneWeekdays
, other
.fStandaloneWeekdaysCount
);
386 assignArray(fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, other
.fStandaloneShortWeekdays
, other
.fStandaloneShortWeekdaysCount
);
387 assignArray(fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, other
.fStandaloneShorterWeekdays
, other
.fStandaloneShorterWeekdaysCount
);
388 assignArray(fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, other
.fStandaloneNarrowWeekdays
, other
.fStandaloneNarrowWeekdaysCount
);
389 assignArray(fAmPms
, fAmPmsCount
, other
.fAmPms
, other
.fAmPmsCount
);
390 assignArray(fNarrowAmPms
, fNarrowAmPmsCount
, other
.fNarrowAmPms
, other
.fNarrowAmPmsCount
);
391 fTimeSeparator
.fastCopyFrom(other
.fTimeSeparator
); // fastCopyFrom() - see assignArray comments
392 assignArray(fQuarters
, fQuartersCount
, other
.fQuarters
, other
.fQuartersCount
);
393 assignArray(fShortQuarters
, fShortQuartersCount
, other
.fShortQuarters
, other
.fShortQuartersCount
);
394 assignArray(fStandaloneQuarters
, fStandaloneQuartersCount
, other
.fStandaloneQuarters
, other
.fStandaloneQuartersCount
);
395 assignArray(fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, other
.fStandaloneShortQuarters
, other
.fStandaloneShortQuartersCount
);
396 assignArray(fWideDayPeriods
, fWideDayPeriodsCount
,
397 other
.fWideDayPeriods
, other
.fWideDayPeriodsCount
);
398 assignArray(fNarrowDayPeriods
, fNarrowDayPeriodsCount
,
399 other
.fNarrowDayPeriods
, other
.fNarrowDayPeriodsCount
);
400 assignArray(fAbbreviatedDayPeriods
, fAbbreviatedDayPeriodsCount
,
401 other
.fAbbreviatedDayPeriods
, other
.fAbbreviatedDayPeriodsCount
);
402 assignArray(fStandaloneWideDayPeriods
, fStandaloneWideDayPeriodsCount
,
403 other
.fStandaloneWideDayPeriods
, other
.fStandaloneWideDayPeriodsCount
);
404 assignArray(fStandaloneNarrowDayPeriods
, fStandaloneNarrowDayPeriodsCount
,
405 other
.fStandaloneNarrowDayPeriods
, other
.fStandaloneNarrowDayPeriodsCount
);
406 assignArray(fStandaloneAbbreviatedDayPeriods
, fStandaloneAbbreviatedDayPeriodsCount
,
407 other
.fStandaloneAbbreviatedDayPeriods
, other
.fStandaloneAbbreviatedDayPeriodsCount
);
408 if (other
.fLeapMonthPatterns
!= NULL
) {
409 assignArray(fLeapMonthPatterns
, fLeapMonthPatternsCount
, other
.fLeapMonthPatterns
, other
.fLeapMonthPatternsCount
);
411 fLeapMonthPatterns
= NULL
;
412 fLeapMonthPatternsCount
= 0;
414 if (other
.fShortYearNames
!= NULL
) {
415 assignArray(fShortYearNames
, fShortYearNamesCount
, other
.fShortYearNames
, other
.fShortYearNamesCount
);
417 fShortYearNames
= NULL
;
418 fShortYearNamesCount
= 0;
420 if (other
.fShortZodiacNames
!= NULL
) {
421 assignArray(fShortZodiacNames
, fShortZodiacNamesCount
, other
.fShortZodiacNames
, other
.fShortZodiacNamesCount
);
423 fShortZodiacNames
= NULL
;
424 fShortZodiacNamesCount
= 0;
427 if (other
.fZoneStrings
!= NULL
) {
428 fZoneStringsColCount
= other
.fZoneStringsColCount
;
429 fZoneStringsRowCount
= other
.fZoneStringsRowCount
;
430 createZoneStrings((const UnicodeString
**)other
.fZoneStrings
);
434 fZoneStringsColCount
= 0;
435 fZoneStringsRowCount
= 0;
437 fZSFLocale
= other
.fZSFLocale
;
438 // Other zone strings data is created on demand
439 fLocaleZoneStrings
= NULL
;
441 // fastCopyFrom() - see assignArray comments
442 fLocalPatternChars
.fastCopyFrom(other
.fLocalPatternChars
);
444 uprv_memcpy(fCapitalization
, other
.fCapitalization
, sizeof(fCapitalization
));
448 * Assignment operator.
450 DateFormatSymbols
& DateFormatSymbols::operator=(const DateFormatSymbols
& other
)
458 DateFormatSymbols::~DateFormatSymbols()
463 void DateFormatSymbols::dispose()
467 delete[] fNarrowEras
;
469 delete[] fShortMonths
;
470 delete[] fNarrowMonths
;
471 delete[] fStandaloneMonths
;
472 delete[] fStandaloneShortMonths
;
473 delete[] fStandaloneNarrowMonths
;
475 delete[] fShortWeekdays
;
476 delete[] fShorterWeekdays
;
477 delete[] fNarrowWeekdays
;
478 delete[] fStandaloneWeekdays
;
479 delete[] fStandaloneShortWeekdays
;
480 delete[] fStandaloneShorterWeekdays
;
481 delete[] fStandaloneNarrowWeekdays
;
483 delete[] fNarrowAmPms
;
485 delete[] fShortQuarters
;
486 delete[] fStandaloneQuarters
;
487 delete[] fStandaloneShortQuarters
;
488 delete[] fLeapMonthPatterns
;
489 delete[] fShortYearNames
;
490 delete[] fShortZodiacNames
;
491 delete[] fAbbreviatedDayPeriods
;
492 delete[] fWideDayPeriods
;
493 delete[] fNarrowDayPeriods
;
494 delete[] fStandaloneAbbreviatedDayPeriods
;
495 delete[] fStandaloneWideDayPeriods
;
496 delete[] fStandaloneNarrowDayPeriods
;
498 disposeZoneStrings();
501 void DateFormatSymbols::disposeZoneStrings()
504 for (int32_t row
= 0; row
< fZoneStringsRowCount
; ++row
) {
505 delete[] fZoneStrings
[row
];
507 uprv_free(fZoneStrings
);
509 if (fLocaleZoneStrings
) {
510 for (int32_t row
= 0; row
< fZoneStringsRowCount
; ++row
) {
511 delete[] fLocaleZoneStrings
[row
];
513 uprv_free(fLocaleZoneStrings
);
517 fLocaleZoneStrings
= NULL
;
518 fZoneStringsRowCount
= 0;
519 fZoneStringsColCount
= 0;
523 DateFormatSymbols::arrayCompare(const UnicodeString
* array1
,
524 const UnicodeString
* array2
,
527 if (array1
== array2
) return TRUE
;
531 if (array1
[count
] != array2
[count
]) return FALSE
;
537 DateFormatSymbols::operator==(const DateFormatSymbols
& other
) const
539 // First do cheap comparisons
540 if (this == &other
) {
543 if (fErasCount
== other
.fErasCount
&&
544 fEraNamesCount
== other
.fEraNamesCount
&&
545 fNarrowErasCount
== other
.fNarrowErasCount
&&
546 fMonthsCount
== other
.fMonthsCount
&&
547 fShortMonthsCount
== other
.fShortMonthsCount
&&
548 fNarrowMonthsCount
== other
.fNarrowMonthsCount
&&
549 fStandaloneMonthsCount
== other
.fStandaloneMonthsCount
&&
550 fStandaloneShortMonthsCount
== other
.fStandaloneShortMonthsCount
&&
551 fStandaloneNarrowMonthsCount
== other
.fStandaloneNarrowMonthsCount
&&
552 fWeekdaysCount
== other
.fWeekdaysCount
&&
553 fShortWeekdaysCount
== other
.fShortWeekdaysCount
&&
554 fShorterWeekdaysCount
== other
.fShorterWeekdaysCount
&&
555 fNarrowWeekdaysCount
== other
.fNarrowWeekdaysCount
&&
556 fStandaloneWeekdaysCount
== other
.fStandaloneWeekdaysCount
&&
557 fStandaloneShortWeekdaysCount
== other
.fStandaloneShortWeekdaysCount
&&
558 fStandaloneShorterWeekdaysCount
== other
.fStandaloneShorterWeekdaysCount
&&
559 fStandaloneNarrowWeekdaysCount
== other
.fStandaloneNarrowWeekdaysCount
&&
560 fAmPmsCount
== other
.fAmPmsCount
&&
561 fNarrowAmPmsCount
== other
.fNarrowAmPmsCount
&&
562 fQuartersCount
== other
.fQuartersCount
&&
563 fShortQuartersCount
== other
.fShortQuartersCount
&&
564 fStandaloneQuartersCount
== other
.fStandaloneQuartersCount
&&
565 fStandaloneShortQuartersCount
== other
.fStandaloneShortQuartersCount
&&
566 fLeapMonthPatternsCount
== other
.fLeapMonthPatternsCount
&&
567 fShortYearNamesCount
== other
.fShortYearNamesCount
&&
568 fShortZodiacNamesCount
== other
.fShortZodiacNamesCount
&&
569 fAbbreviatedDayPeriodsCount
== other
.fAbbreviatedDayPeriodsCount
&&
570 fWideDayPeriodsCount
== other
.fWideDayPeriodsCount
&&
571 fNarrowDayPeriodsCount
== other
.fNarrowDayPeriodsCount
&&
572 fStandaloneAbbreviatedDayPeriodsCount
== other
.fStandaloneAbbreviatedDayPeriodsCount
&&
573 fStandaloneWideDayPeriodsCount
== other
.fStandaloneWideDayPeriodsCount
&&
574 fStandaloneNarrowDayPeriodsCount
== other
.fStandaloneNarrowDayPeriodsCount
&&
575 (uprv_memcmp(fCapitalization
, other
.fCapitalization
, sizeof(fCapitalization
))==0))
577 // Now compare the arrays themselves
578 if (arrayCompare(fEras
, other
.fEras
, fErasCount
) &&
579 arrayCompare(fEraNames
, other
.fEraNames
, fEraNamesCount
) &&
580 arrayCompare(fNarrowEras
, other
.fNarrowEras
, fNarrowErasCount
) &&
581 arrayCompare(fMonths
, other
.fMonths
, fMonthsCount
) &&
582 arrayCompare(fShortMonths
, other
.fShortMonths
, fShortMonthsCount
) &&
583 arrayCompare(fNarrowMonths
, other
.fNarrowMonths
, fNarrowMonthsCount
) &&
584 arrayCompare(fStandaloneMonths
, other
.fStandaloneMonths
, fStandaloneMonthsCount
) &&
585 arrayCompare(fStandaloneShortMonths
, other
.fStandaloneShortMonths
, fStandaloneShortMonthsCount
) &&
586 arrayCompare(fStandaloneNarrowMonths
, other
.fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
) &&
587 arrayCompare(fWeekdays
, other
.fWeekdays
, fWeekdaysCount
) &&
588 arrayCompare(fShortWeekdays
, other
.fShortWeekdays
, fShortWeekdaysCount
) &&
589 arrayCompare(fShorterWeekdays
, other
.fShorterWeekdays
, fShorterWeekdaysCount
) &&
590 arrayCompare(fNarrowWeekdays
, other
.fNarrowWeekdays
, fNarrowWeekdaysCount
) &&
591 arrayCompare(fStandaloneWeekdays
, other
.fStandaloneWeekdays
, fStandaloneWeekdaysCount
) &&
592 arrayCompare(fStandaloneShortWeekdays
, other
.fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
) &&
593 arrayCompare(fStandaloneShorterWeekdays
, other
.fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
) &&
594 arrayCompare(fStandaloneNarrowWeekdays
, other
.fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
) &&
595 arrayCompare(fAmPms
, other
.fAmPms
, fAmPmsCount
) &&
596 arrayCompare(fNarrowAmPms
, other
.fNarrowAmPms
, fNarrowAmPmsCount
) &&
597 fTimeSeparator
== other
.fTimeSeparator
&&
598 arrayCompare(fQuarters
, other
.fQuarters
, fQuartersCount
) &&
599 arrayCompare(fShortQuarters
, other
.fShortQuarters
, fShortQuartersCount
) &&
600 arrayCompare(fStandaloneQuarters
, other
.fStandaloneQuarters
, fStandaloneQuartersCount
) &&
601 arrayCompare(fStandaloneShortQuarters
, other
.fStandaloneShortQuarters
, fStandaloneShortQuartersCount
) &&
602 arrayCompare(fLeapMonthPatterns
, other
.fLeapMonthPatterns
, fLeapMonthPatternsCount
) &&
603 arrayCompare(fShortYearNames
, other
.fShortYearNames
, fShortYearNamesCount
) &&
604 arrayCompare(fShortZodiacNames
, other
.fShortZodiacNames
, fShortZodiacNamesCount
) &&
605 arrayCompare(fAbbreviatedDayPeriods
, other
.fAbbreviatedDayPeriods
, fAbbreviatedDayPeriodsCount
) &&
606 arrayCompare(fWideDayPeriods
, other
.fWideDayPeriods
, fWideDayPeriodsCount
) &&
607 arrayCompare(fNarrowDayPeriods
, other
.fNarrowDayPeriods
, fNarrowDayPeriodsCount
) &&
608 arrayCompare(fStandaloneAbbreviatedDayPeriods
, other
.fStandaloneAbbreviatedDayPeriods
,
609 fStandaloneAbbreviatedDayPeriodsCount
) &&
610 arrayCompare(fStandaloneWideDayPeriods
, other
.fStandaloneWideDayPeriods
,
611 fStandaloneWideDayPeriodsCount
) &&
612 arrayCompare(fStandaloneNarrowDayPeriods
, other
.fStandaloneNarrowDayPeriods
,
613 fStandaloneWideDayPeriodsCount
))
615 // Compare the contents of fZoneStrings
616 if (fZoneStrings
== NULL
&& other
.fZoneStrings
== NULL
) {
617 if (fZSFLocale
== other
.fZSFLocale
) {
620 } else if (fZoneStrings
!= NULL
&& other
.fZoneStrings
!= NULL
) {
621 if (fZoneStringsRowCount
== other
.fZoneStringsRowCount
622 && fZoneStringsColCount
== other
.fZoneStringsColCount
) {
624 for (int32_t i
= 0; (i
< fZoneStringsRowCount
) && cmpres
; i
++) {
625 cmpres
= arrayCompare(fZoneStrings
[i
], other
.fZoneStrings
[i
], fZoneStringsColCount
);
636 //------------------------------------------------------
639 DateFormatSymbols::getEras(int32_t &count
) const
646 DateFormatSymbols::getEraNames(int32_t &count
) const
648 count
= fEraNamesCount
;
653 DateFormatSymbols::getNarrowEras(int32_t &count
) const
655 count
= fNarrowErasCount
;
660 DateFormatSymbols::getMonths(int32_t &count
) const
662 count
= fMonthsCount
;
667 DateFormatSymbols::getShortMonths(int32_t &count
) const
669 count
= fShortMonthsCount
;
674 DateFormatSymbols::getMonths(int32_t &count
, DtContextType context
, DtWidthType width
) const
676 UnicodeString
*returnValue
= NULL
;
682 count
= fMonthsCount
;
683 returnValue
= fMonths
;
686 case SHORT
: // no month data for this, defaults to ABBREVIATED
687 count
= fShortMonthsCount
;
688 returnValue
= fShortMonths
;
691 count
= fNarrowMonthsCount
;
692 returnValue
= fNarrowMonths
;
694 case DT_WIDTH_COUNT
:
701 count
= fStandaloneMonthsCount
;
702 returnValue
= fStandaloneMonths
;
705 case SHORT
: // no month data for this, defaults to ABBREVIATED
706 count
= fStandaloneShortMonthsCount
;
707 returnValue
= fStandaloneShortMonths
;
710 count
= fStandaloneNarrowMonthsCount
;
711 returnValue
= fStandaloneNarrowMonths
;
713 case DT_WIDTH_COUNT
:
717 case DT_CONTEXT_COUNT
:
724 DateFormatSymbols::getWeekdays(int32_t &count
) const
726 count
= fWeekdaysCount
;
731 DateFormatSymbols::getShortWeekdays(int32_t &count
) const
733 count
= fShortWeekdaysCount
;
734 return fShortWeekdays
;
738 DateFormatSymbols::getWeekdays(int32_t &count
, DtContextType context
, DtWidthType width
) const
740 UnicodeString
*returnValue
= NULL
;
745 count
= fWeekdaysCount
;
746 returnValue
= fWeekdays
;
749 count
= fShortWeekdaysCount
;
750 returnValue
= fShortWeekdays
;
753 count
= fShorterWeekdaysCount
;
754 returnValue
= fShorterWeekdays
;
757 count
= fNarrowWeekdaysCount
;
758 returnValue
= fNarrowWeekdays
;
760 case DT_WIDTH_COUNT
:
767 count
= fStandaloneWeekdaysCount
;
768 returnValue
= fStandaloneWeekdays
;
771 count
= fStandaloneShortWeekdaysCount
;
772 returnValue
= fStandaloneShortWeekdays
;
775 count
= fStandaloneShorterWeekdaysCount
;
776 returnValue
= fStandaloneShorterWeekdays
;
779 count
= fStandaloneNarrowWeekdaysCount
;
780 returnValue
= fStandaloneNarrowWeekdays
;
782 case DT_WIDTH_COUNT
:
786 case DT_CONTEXT_COUNT
:
793 DateFormatSymbols::getQuarters(int32_t &count
, DtContextType context
, DtWidthType width
) const
795 UnicodeString
*returnValue
= NULL
;
801 count
= fQuartersCount
;
802 returnValue
= fQuarters
;
805 case SHORT
: // no quarter data for this, defaults to ABBREVIATED
806 count
= fShortQuartersCount
;
807 returnValue
= fShortQuarters
;
813 case DT_WIDTH_COUNT
:
820 count
= fStandaloneQuartersCount
;
821 returnValue
= fStandaloneQuarters
;
824 case SHORT
: // no quarter data for this, defaults to ABBREVIATED
825 count
= fStandaloneShortQuartersCount
;
826 returnValue
= fStandaloneShortQuarters
;
832 case DT_WIDTH_COUNT
:
836 case DT_CONTEXT_COUNT
:
843 DateFormatSymbols::getTimeSeparatorString(UnicodeString
& result
) const
845 // fastCopyFrom() - see assignArray comments
846 return result
.fastCopyFrom(fTimeSeparator
);
850 DateFormatSymbols::getAmPmStrings(int32_t &count
) const
857 DateFormatSymbols::getLeapMonthPatterns(int32_t &count
) const
859 count
= fLeapMonthPatternsCount
;
860 return fLeapMonthPatterns
;
864 DateFormatSymbols::getYearNames(int32_t& count
,
865 DtContextType
/*ignored*/, DtWidthType
/*ignored*/) const
867 count
= fShortYearNamesCount
;
868 return fShortYearNames
;
872 DateFormatSymbols::setYearNames(const UnicodeString
* yearNames
, int32_t count
,
873 DtContextType context
, DtWidthType width
)
875 if (context
== FORMAT
&& width
== ABBREVIATED
) {
876 if (fShortYearNames
) {
877 delete[] fShortYearNames
;
879 fShortYearNames
= newUnicodeStringArray(count
);
880 uprv_arrayCopy(yearNames
, fShortYearNames
, count
);
881 fShortYearNamesCount
= count
;
886 DateFormatSymbols::getZodiacNames(int32_t& count
,
887 DtContextType
/*ignored*/, DtWidthType
/*ignored*/) const
889 count
= fShortZodiacNamesCount
;
890 return fShortZodiacNames
;
894 DateFormatSymbols::setZodiacNames(const UnicodeString
* zodiacNames
, int32_t count
,
895 DtContextType context
, DtWidthType width
)
897 if (context
== FORMAT
&& width
== ABBREVIATED
) {
898 if (fShortZodiacNames
) {
899 delete[] fShortZodiacNames
;
901 fShortZodiacNames
= newUnicodeStringArray(count
);
902 uprv_arrayCopy(zodiacNames
, fShortZodiacNames
, count
);
903 fShortZodiacNamesCount
= count
;
907 //------------------------------------------------------
910 DateFormatSymbols::setEras(const UnicodeString
* erasArray
, int32_t count
)
912 // delete the old list if we own it
916 // we always own the new list, which we create here (we duplicate rather
917 // than adopting the list passed in)
918 fEras
= newUnicodeStringArray(count
);
919 uprv_arrayCopy(erasArray
,fEras
, count
);
924 DateFormatSymbols::setEraNames(const UnicodeString
* eraNamesArray
, int32_t count
)
926 // delete the old list if we own it
930 // we always own the new list, which we create here (we duplicate rather
931 // than adopting the list passed in)
932 fEraNames
= newUnicodeStringArray(count
);
933 uprv_arrayCopy(eraNamesArray
,fEraNames
, count
);
934 fEraNamesCount
= count
;
938 DateFormatSymbols::setNarrowEras(const UnicodeString
* narrowErasArray
, int32_t count
)
940 // delete the old list if we own it
942 delete[] fNarrowEras
;
944 // we always own the new list, which we create here (we duplicate rather
945 // than adopting the list passed in)
946 fNarrowEras
= newUnicodeStringArray(count
);
947 uprv_arrayCopy(narrowErasArray
,fNarrowEras
, count
);
948 fNarrowErasCount
= count
;
952 DateFormatSymbols::setMonths(const UnicodeString
* monthsArray
, int32_t count
)
954 // delete the old list if we own it
958 // we always own the new list, which we create here (we duplicate rather
959 // than adopting the list passed in)
960 fMonths
= newUnicodeStringArray(count
);
961 uprv_arrayCopy( monthsArray
,fMonths
,count
);
962 fMonthsCount
= count
;
966 DateFormatSymbols::setShortMonths(const UnicodeString
* shortMonthsArray
, int32_t count
)
968 // delete the old list if we own it
970 delete[] fShortMonths
;
972 // we always own the new list, which we create here (we duplicate rather
973 // than adopting the list passed in)
974 fShortMonths
= newUnicodeStringArray(count
);
975 uprv_arrayCopy(shortMonthsArray
,fShortMonths
, count
);
976 fShortMonthsCount
= count
;
980 DateFormatSymbols::setMonths(const UnicodeString
* monthsArray
, int32_t count
, DtContextType context
, DtWidthType width
)
982 // delete the old list if we own it
983 // we always own the new list, which we create here (we duplicate rather
984 // than adopting the list passed in)
992 fMonths
= newUnicodeStringArray(count
);
993 uprv_arrayCopy( monthsArray
,fMonths
,count
);
994 fMonthsCount
= count
;
998 delete[] fShortMonths
;
999 fShortMonths
= newUnicodeStringArray(count
);
1000 uprv_arrayCopy( monthsArray
,fShortMonths
,count
);
1001 fShortMonthsCount
= count
;
1005 delete[] fNarrowMonths
;
1006 fNarrowMonths
= newUnicodeStringArray(count
);
1007 uprv_arrayCopy( monthsArray
,fNarrowMonths
,count
);
1008 fNarrowMonthsCount
= count
;
1017 if (fStandaloneMonths
)
1018 delete[] fStandaloneMonths
;
1019 fStandaloneMonths
= newUnicodeStringArray(count
);
1020 uprv_arrayCopy( monthsArray
,fStandaloneMonths
,count
);
1021 fStandaloneMonthsCount
= count
;
1024 if (fStandaloneShortMonths
)
1025 delete[] fStandaloneShortMonths
;
1026 fStandaloneShortMonths
= newUnicodeStringArray(count
);
1027 uprv_arrayCopy( monthsArray
,fStandaloneShortMonths
,count
);
1028 fStandaloneShortMonthsCount
= count
;
1031 if (fStandaloneNarrowMonths
)
1032 delete[] fStandaloneNarrowMonths
;
1033 fStandaloneNarrowMonths
= newUnicodeStringArray(count
);
1034 uprv_arrayCopy( monthsArray
,fStandaloneNarrowMonths
,count
);
1035 fStandaloneNarrowMonthsCount
= count
;
1041 case DT_CONTEXT_COUNT
:
1046 void DateFormatSymbols::setWeekdays(const UnicodeString
* weekdaysArray
, int32_t count
)
1048 // delete the old list if we own it
1052 // we always own the new list, which we create here (we duplicate rather
1053 // than adopting the list passed in)
1054 fWeekdays
= newUnicodeStringArray(count
);
1055 uprv_arrayCopy(weekdaysArray
,fWeekdays
,count
);
1056 fWeekdaysCount
= count
;
1060 DateFormatSymbols::setShortWeekdays(const UnicodeString
* shortWeekdaysArray
, int32_t count
)
1062 // delete the old list if we own it
1064 delete[] fShortWeekdays
;
1066 // we always own the new list, which we create here (we duplicate rather
1067 // than adopting the list passed in)
1068 fShortWeekdays
= newUnicodeStringArray(count
);
1069 uprv_arrayCopy(shortWeekdaysArray
, fShortWeekdays
, count
);
1070 fShortWeekdaysCount
= count
;
1074 DateFormatSymbols::setWeekdays(const UnicodeString
* weekdaysArray
, int32_t count
, DtContextType context
, DtWidthType width
)
1076 // delete the old list if we own it
1077 // we always own the new list, which we create here (we duplicate rather
1078 // than adopting the list passed in)
1086 fWeekdays
= newUnicodeStringArray(count
);
1087 uprv_arrayCopy(weekdaysArray
, fWeekdays
, count
);
1088 fWeekdaysCount
= count
;
1092 delete[] fShortWeekdays
;
1093 fShortWeekdays
= newUnicodeStringArray(count
);
1094 uprv_arrayCopy(weekdaysArray
, fShortWeekdays
, count
);
1095 fShortWeekdaysCount
= count
;
1098 if (fShorterWeekdays
)
1099 delete[] fShorterWeekdays
;
1100 fShorterWeekdays
= newUnicodeStringArray(count
);
1101 uprv_arrayCopy(weekdaysArray
, fShorterWeekdays
, count
);
1102 fShorterWeekdaysCount
= count
;
1105 if (fNarrowWeekdays
)
1106 delete[] fNarrowWeekdays
;
1107 fNarrowWeekdays
= newUnicodeStringArray(count
);
1108 uprv_arrayCopy(weekdaysArray
, fNarrowWeekdays
, count
);
1109 fNarrowWeekdaysCount
= count
;
1111 case DT_WIDTH_COUNT
:
1118 if (fStandaloneWeekdays
)
1119 delete[] fStandaloneWeekdays
;
1120 fStandaloneWeekdays
= newUnicodeStringArray(count
);
1121 uprv_arrayCopy(weekdaysArray
, fStandaloneWeekdays
, count
);
1122 fStandaloneWeekdaysCount
= count
;
1125 if (fStandaloneShortWeekdays
)
1126 delete[] fStandaloneShortWeekdays
;
1127 fStandaloneShortWeekdays
= newUnicodeStringArray(count
);
1128 uprv_arrayCopy(weekdaysArray
, fStandaloneShortWeekdays
, count
);
1129 fStandaloneShortWeekdaysCount
= count
;
1132 if (fStandaloneShorterWeekdays
)
1133 delete[] fStandaloneShorterWeekdays
;
1134 fStandaloneShorterWeekdays
= newUnicodeStringArray(count
);
1135 uprv_arrayCopy(weekdaysArray
, fStandaloneShorterWeekdays
, count
);
1136 fStandaloneShorterWeekdaysCount
= count
;
1139 if (fStandaloneNarrowWeekdays
)
1140 delete[] fStandaloneNarrowWeekdays
;
1141 fStandaloneNarrowWeekdays
= newUnicodeStringArray(count
);
1142 uprv_arrayCopy(weekdaysArray
, fStandaloneNarrowWeekdays
, count
);
1143 fStandaloneNarrowWeekdaysCount
= count
;
1145 case DT_WIDTH_COUNT
:
1149 case DT_CONTEXT_COUNT
:
1155 DateFormatSymbols::setQuarters(const UnicodeString
* quartersArray
, int32_t count
, DtContextType context
, DtWidthType width
)
1157 // delete the old list if we own it
1158 // we always own the new list, which we create here (we duplicate rather
1159 // than adopting the list passed in)
1167 fQuarters
= newUnicodeStringArray(count
);
1168 uprv_arrayCopy( quartersArray
,fQuarters
,count
);
1169 fQuartersCount
= count
;
1173 delete[] fShortQuarters
;
1174 fShortQuarters
= newUnicodeStringArray(count
);
1175 uprv_arrayCopy( quartersArray
,fShortQuarters
,count
);
1176 fShortQuartersCount
= count
;
1180 if (fNarrowQuarters)
1181 delete[] fNarrowQuarters;
1182 fNarrowQuarters = newUnicodeStringArray(count);
1183 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1184 fNarrowQuartersCount = count;
1194 if (fStandaloneQuarters
)
1195 delete[] fStandaloneQuarters
;
1196 fStandaloneQuarters
= newUnicodeStringArray(count
);
1197 uprv_arrayCopy( quartersArray
,fStandaloneQuarters
,count
);
1198 fStandaloneQuartersCount
= count
;
1201 if (fStandaloneShortQuarters
)
1202 delete[] fStandaloneShortQuarters
;
1203 fStandaloneShortQuarters
= newUnicodeStringArray(count
);
1204 uprv_arrayCopy( quartersArray
,fStandaloneShortQuarters
,count
);
1205 fStandaloneShortQuartersCount
= count
;
1209 if (fStandaloneNarrowQuarters)
1210 delete[] fStandaloneNarrowQuarters;
1211 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1212 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1213 fStandaloneNarrowQuartersCount = count;
1220 case DT_CONTEXT_COUNT
:
1226 DateFormatSymbols::setAmPmStrings(const UnicodeString
* amPmsArray
, int32_t count
)
1228 // delete the old list if we own it
1229 if (fAmPms
) delete[] fAmPms
;
1231 // we always own the new list, which we create here (we duplicate rather
1232 // than adopting the list passed in)
1233 fAmPms
= newUnicodeStringArray(count
);
1234 uprv_arrayCopy(amPmsArray
,fAmPms
,count
);
1235 fAmPmsCount
= count
;
1239 DateFormatSymbols::setTimeSeparatorString(const UnicodeString
& newTimeSeparator
)
1241 fTimeSeparator
= newTimeSeparator
;
1244 const UnicodeString
**
1245 DateFormatSymbols::getZoneStrings(int32_t& rowCount
, int32_t& columnCount
) const
1247 const UnicodeString
**result
= NULL
;
1250 if (fZoneStrings
== NULL
) {
1251 if (fLocaleZoneStrings
== NULL
) {
1252 ((DateFormatSymbols
*)this)->initZoneStringsArray();
1254 result
= (const UnicodeString
**)fLocaleZoneStrings
;
1256 result
= (const UnicodeString
**)fZoneStrings
;
1258 rowCount
= fZoneStringsRowCount
;
1259 columnCount
= fZoneStringsColCount
;
1265 // For now, we include all zones
1266 #define ZONE_SET UCAL_ZONE_TYPE_ANY
1268 // This code must be called within a synchronized block
1270 DateFormatSymbols::initZoneStringsArray(void) {
1271 if (fZoneStrings
!= NULL
|| fLocaleZoneStrings
!= NULL
) {
1275 UErrorCode status
= U_ZERO_ERROR
;
1277 StringEnumeration
*tzids
= NULL
;
1278 UnicodeString
** zarray
= NULL
;
1279 TimeZoneNames
*tzNames
= NULL
;
1282 static const UTimeZoneNameType TYPES
[] = {
1283 UTZNM_LONG_STANDARD
, UTZNM_SHORT_STANDARD
,
1284 UTZNM_LONG_DAYLIGHT
, UTZNM_SHORT_DAYLIGHT
1286 static const int32_t NUM_TYPES
= 4;
1288 do { // dummy do-while
1290 tzids
= TimeZone::createTimeZoneIDEnumeration(ZONE_SET
, NULL
, NULL
, status
);
1291 rows
= tzids
->count(status
);
1292 if (U_FAILURE(status
)) {
1297 int32_t size
= rows
* sizeof(UnicodeString
*);
1298 zarray
= (UnicodeString
**)uprv_malloc(size
);
1299 if (zarray
== NULL
) {
1300 status
= U_MEMORY_ALLOCATION_ERROR
;
1303 uprv_memset(zarray
, 0, size
);
1305 tzNames
= TimeZoneNames::createInstance(fZSFLocale
, status
);
1306 tzNames
->loadAllDisplayNames(status
);
1307 if (U_FAILURE(status
)) { break; }
1309 const UnicodeString
*tzid
;
1311 UDate now
= Calendar::getNow();
1312 UnicodeString tzDispName
;
1314 while ((tzid
= tzids
->snext(status
))) {
1315 if (U_FAILURE(status
)) {
1319 zarray
[i
] = new UnicodeString
[5];
1320 if (zarray
[i
] == NULL
) {
1321 status
= U_MEMORY_ALLOCATION_ERROR
;
1325 zarray
[i
][0].setTo(*tzid
);
1326 tzNames
->getDisplayNames(*tzid
, TYPES
, NUM_TYPES
, now
, zarray
[i
]+1, status
);
1332 if (U_FAILURE(status
)) {
1334 for (int32_t i
= 0; i
< rows
; i
++) {
1351 fLocaleZoneStrings
= zarray
;
1352 fZoneStringsRowCount
= rows
;
1353 fZoneStringsColCount
= 1 + NUM_TYPES
;
1357 DateFormatSymbols::setZoneStrings(const UnicodeString
* const *strings
, int32_t rowCount
, int32_t columnCount
)
1359 // since deleting a 2-d array is a pain in the butt, we offload that task to
1360 // a separate function
1361 disposeZoneStrings();
1362 // we always own the new list, which we create here (we duplicate rather
1363 // than adopting the list passed in)
1364 fZoneStringsRowCount
= rowCount
;
1365 fZoneStringsColCount
= columnCount
;
1366 createZoneStrings((const UnicodeString
**)strings
);
1369 //------------------------------------------------------
1371 const char16_t * U_EXPORT2
1372 DateFormatSymbols::getPatternUChars(void)
1374 return gPatternChars
;
1377 UDateFormatField U_EXPORT2
1378 DateFormatSymbols::getPatternCharIndex(UChar c
) {
1379 const UChar
*p
= u_strchr(gPatternChars
, c
);
1381 return UDAT_FIELD_COUNT
;
1383 return static_cast<UDateFormatField
>(p
- gPatternChars
);
1387 static const uint64_t kNumericFieldsAlways
=
1388 ((uint64_t)1 << UDAT_YEAR_FIELD
) | // y
1389 ((uint64_t)1 << UDAT_DATE_FIELD
) | // d
1390 ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD
) | // k
1391 ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD
) | // H
1392 ((uint64_t)1 << UDAT_MINUTE_FIELD
) | // m
1393 ((uint64_t)1 << UDAT_SECOND_FIELD
) | // s
1394 ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD
) | // S
1395 ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD
) | // D
1396 ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD
) | // F
1397 ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD
) | // w
1398 ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD
) | // W
1399 ((uint64_t)1 << UDAT_HOUR1_FIELD
) | // h
1400 ((uint64_t)1 << UDAT_HOUR0_FIELD
) | // K
1401 ((uint64_t)1 << UDAT_YEAR_WOY_FIELD
) | // Y
1402 ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD
) | // u
1403 ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD
) | // g
1404 ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD
) | // A
1405 ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD
); // r
1407 static const uint64_t kNumericFieldsForCount12
=
1408 ((uint64_t)1 << UDAT_MONTH_FIELD
) | // M or MM
1409 ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD
) | // e or ee
1410 ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD
) | // c or cc
1411 ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD
) | // L or LL
1412 ((uint64_t)1 << UDAT_QUARTER_FIELD
) | // Q or QQ
1413 ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD
); // q or qq
1416 DateFormatSymbols::isNumericField(UDateFormatField f
, int32_t count
) {
1417 if (f
== UDAT_FIELD_COUNT
) {
1420 uint64_t flag
= ((uint64_t)1 << f
);
1421 return ((kNumericFieldsAlways
& flag
) != 0 || ((kNumericFieldsForCount12
& flag
) != 0 && count
< 3));
1425 DateFormatSymbols::isNumericPatternChar(UChar c
, int32_t count
) {
1426 return isNumericField(getPatternCharIndex(c
), count
);
1429 //------------------------------------------------------
1432 DateFormatSymbols::getLocalPatternChars(UnicodeString
& result
) const
1434 // fastCopyFrom() - see assignArray comments
1435 return result
.fastCopyFrom(fLocalPatternChars
);
1438 //------------------------------------------------------
1441 DateFormatSymbols::setLocalPatternChars(const UnicodeString
& newLocalPatternChars
)
1443 fLocalPatternChars
= newLocalPatternChars
;
1446 //------------------------------------------------------
1450 // Constants declarations
1451 static const UChar kCalendarAliasPrefixUChar
[] = {
1452 SOLIDUS
, CAP_L
, CAP_O
, CAP_C
, CAP_A
, CAP_L
, CAP_E
, SOLIDUS
,
1453 LOW_C
, LOW_A
, LOW_L
, LOW_E
, LOW_N
, LOW_D
, LOW_A
, LOW_R
, SOLIDUS
1455 static const UChar kGregorianTagUChar
[] = {
1456 LOW_G
, LOW_R
, LOW_E
, LOW_G
, LOW_O
, LOW_R
, LOW_I
, LOW_A
, LOW_N
1458 static const UChar kVariantTagUChar
[] = {
1459 PERCENT
, LOW_V
, LOW_A
, LOW_R
, LOW_I
, LOW_A
, LOW_N
, LOW_T
1461 static const UChar kLeapTagUChar
[] = {
1462 LOW_L
, LOW_E
, LOW_A
, LOW_P
1464 static const UChar kCyclicNameSetsTagUChar
[] = {
1465 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
1467 static const UChar kYearsTagUChar
[] = {
1468 SOLIDUS
, LOW_Y
, LOW_E
, LOW_A
, LOW_R
, LOW_S
1470 static const UChar kZodiacsUChar
[] = {
1471 SOLIDUS
, LOW_Z
, LOW_O
, LOW_D
, LOW_I
, LOW_A
, LOW_C
, LOW_S
1473 static const UChar kDayPartsTagUChar
[] = {
1474 SOLIDUS
, LOW_D
, LOW_A
, LOW_Y
, CAP_P
, LOW_A
, LOW_R
, LOW_T
, LOW_S
1476 static const UChar kFormatTagUChar
[] = {
1477 SOLIDUS
, LOW_F
, LOW_O
, LOW_R
, LOW_M
, LOW_A
, LOW_T
1479 static const UChar kAbbrTagUChar
[] = {
1480 SOLIDUS
, LOW_A
, LOW_B
, LOW_B
, LOW_R
, LOW_E
, LOW_V
, LOW_I
, LOW_A
, LOW_T
, LOW_E
, LOW_D
1483 // ResourceSink to enumerate all calendar resources
1484 struct CalendarDataSink
: public ResourceSink
{
1486 // Enum which specifies the type of alias received, or no alias
1494 // Data structures to store resources from the current resource bundle
1496 Hashtable arraySizes
;
1499 * Whenever there are aliases, the same object will be added twice to 'map'.
1500 * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
1501 * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
1505 // Paths and the aliases they point to
1506 UVector aliasPathPairs
;
1508 // Current and next calendar resource table which should be loaded
1509 UnicodeString currentCalendarType
;
1510 UnicodeString nextCalendarType
;
1512 // Resources to visit when enumerating fallback calendars
1513 LocalPointer
<UVector
> resourcesToVisit
;
1515 // Alias' relative path populated whenever an alias is read
1516 UnicodeString aliasRelativePath
;
1518 // Initializes CalendarDataSink with default values
1519 CalendarDataSink(UErrorCode
& status
)
1520 : arrays(FALSE
, status
), arraySizes(FALSE
, status
), maps(FALSE
, status
),
1521 mapRefs(deleteHashtable
, NULL
, 10, status
),
1522 aliasPathPairs(uprv_deleteUObject
, uhash_compareUnicodeString
, status
),
1523 currentCalendarType(), nextCalendarType(),
1524 resourcesToVisit(NULL
), aliasRelativePath() {
1525 if (U_FAILURE(status
)) { return; }
1527 virtual ~CalendarDataSink();
1529 // Configure the CalendarSink to visit all the resources
1530 void visitAllResources() {
1531 resourcesToVisit
.adoptInstead(NULL
);
1534 // Actions to be done before enumerating
1535 void preEnumerate(const UnicodeString
&calendarType
) {
1536 currentCalendarType
= calendarType
;
1537 nextCalendarType
.setToBogus();
1538 aliasPathPairs
.removeAllElements();
1541 virtual void put(const char *key
, ResourceValue
&value
, UBool
, UErrorCode
&errorCode
) {
1542 if (U_FAILURE(errorCode
)) { return; }
1543 U_ASSERT(!currentCalendarType
.isEmpty());
1545 // Stores the resources to visit on the next calendar.
1546 LocalPointer
<UVector
> resourcesToVisitNext(NULL
);
1547 ResourceTable calendarData
= value
.getTable(errorCode
);
1548 if (U_FAILURE(errorCode
)) { return; }
1550 // Enumerate all resources for this calendar
1551 for (int i
= 0; calendarData
.getKeyAndValue(i
, key
, value
); i
++) {
1552 UnicodeString
keyUString(key
, -1, US_INV
);
1554 // == Handle aliases ==
1555 AliasType aliasType
= processAliasFromValue(keyUString
, value
, errorCode
);
1556 if (U_FAILURE(errorCode
)) { return; }
1557 if (aliasType
== GREGORIAN
) {
1558 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
1561 } else if (aliasType
== DIFFERENT_CALENDAR
) {
1562 // Whenever an alias to the next calendar (except gregorian) is encountered, register the
1563 // calendar type it's pointing to
1564 if (resourcesToVisitNext
.isNull()) {
1565 resourcesToVisitNext
1566 .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject
, uhash_compareUnicodeString
, errorCode
),
1568 if (U_FAILURE(errorCode
)) { return; }
1570 LocalPointer
<UnicodeString
> aliasRelativePathCopy(new UnicodeString(aliasRelativePath
), errorCode
);
1571 resourcesToVisitNext
->addElement(aliasRelativePathCopy
.getAlias(), errorCode
);
1572 if (U_FAILURE(errorCode
)) { return; }
1573 // Only release ownership after resourcesToVisitNext takes it (no error happened):
1574 aliasRelativePathCopy
.orphan();
1577 } else if (aliasType
== SAME_CALENDAR
) {
1578 // Register same-calendar alias
1579 if (arrays
.get(aliasRelativePath
) == NULL
&& maps
.get(aliasRelativePath
) == NULL
) {
1580 LocalPointer
<UnicodeString
> aliasRelativePathCopy(new UnicodeString(aliasRelativePath
), errorCode
);
1581 aliasPathPairs
.addElement(aliasRelativePathCopy
.getAlias(), errorCode
);
1582 if (U_FAILURE(errorCode
)) { return; }
1583 // Only release ownership after aliasPathPairs takes it (no error happened):
1584 aliasRelativePathCopy
.orphan();
1585 LocalPointer
<UnicodeString
> keyUStringCopy(new UnicodeString(keyUString
), errorCode
);
1586 aliasPathPairs
.addElement(keyUStringCopy
.getAlias(), errorCode
);
1587 if (U_FAILURE(errorCode
)) { return; }
1588 // Only release ownership after aliasPathPairs takes it (no error happened):
1589 keyUStringCopy
.orphan();
1594 // Only visit the resources that were referenced by an alias on the previous calendar
1595 // (AmPmMarkersAbbr is an exception).
1596 if (!resourcesToVisit
.isNull() && !resourcesToVisit
->isEmpty() && !resourcesToVisit
->contains(&keyUString
)
1597 && uprv_strcmp(key
, gAmPmMarkersAbbrTag
) != 0) { continue; }
1599 // == Handle data ==
1600 if (uprv_strcmp(key
, gAmPmMarkersTag
) == 0
1601 || uprv_strcmp(key
, gAmPmMarkersAbbrTag
) == 0
1602 || uprv_strcmp(key
, gAmPmMarkersNarrowTag
) == 0) {
1603 if (arrays
.get(keyUString
) == NULL
) {
1604 ResourceArray resourceArray
= value
.getArray(errorCode
);
1605 int32_t arraySize
= resourceArray
.getSize();
1606 LocalArray
<UnicodeString
> stringArray(new UnicodeString
[arraySize
], errorCode
);
1607 value
.getStringArray(stringArray
.getAlias(), arraySize
, errorCode
);
1608 arrays
.put(keyUString
, stringArray
.orphan(), errorCode
);
1609 arraySizes
.puti(keyUString
, arraySize
, errorCode
);
1610 if (U_FAILURE(errorCode
)) { return; }
1612 } else if (uprv_strcmp(key
, gErasTag
) == 0
1613 || uprv_strcmp(key
, gDayNamesTag
) == 0
1614 || uprv_strcmp(key
, gMonthNamesTag
) == 0
1615 || uprv_strcmp(key
, gQuartersTag
) == 0
1616 || uprv_strcmp(key
, gDayPeriodTag
) == 0
1617 || uprv_strcmp(key
, gMonthPatternsTag
) == 0
1618 || uprv_strcmp(key
, gCyclicNameSetsTag
) == 0) {
1619 processResource(keyUString
, key
, value
, errorCode
);
1623 // Apply same-calendar aliases
1627 for (int32_t i
= 0; i
< aliasPathPairs
.size();) {
1629 UnicodeString
*alias
= (UnicodeString
*)aliasPathPairs
[i
];
1630 UnicodeString
*aliasArray
;
1631 Hashtable
*aliasMap
;
1632 if ((aliasArray
= (UnicodeString
*)arrays
.get(*alias
)) != NULL
) {
1633 UnicodeString
*path
= (UnicodeString
*)aliasPathPairs
[i
+ 1];
1634 if (arrays
.get(*path
) == NULL
) {
1636 int32_t aliasArraySize
= arraySizes
.geti(*alias
);
1637 LocalArray
<UnicodeString
> aliasArrayCopy(new UnicodeString
[aliasArraySize
], errorCode
);
1638 if (U_FAILURE(errorCode
)) { return; }
1639 uprv_arrayCopy(aliasArray
, aliasArrayCopy
.getAlias(), aliasArraySize
);
1640 // Put the array on the 'arrays' map
1641 arrays
.put(*path
, aliasArrayCopy
.orphan(), errorCode
);
1642 arraySizes
.puti(*path
, aliasArraySize
, errorCode
);
1644 if (U_FAILURE(errorCode
)) { return; }
1646 } else if ((aliasMap
= (Hashtable
*)maps
.get(*alias
)) != NULL
) {
1647 UnicodeString
*path
= (UnicodeString
*)aliasPathPairs
[i
+ 1];
1648 if (maps
.get(*path
) == NULL
) {
1649 maps
.put(*path
, aliasMap
, errorCode
);
1651 if (U_FAILURE(errorCode
)) { return; }
1655 aliasPathPairs
.removeElementAt(i
+ 1);
1656 aliasPathPairs
.removeElementAt(i
);
1662 } while (modified
&& !aliasPathPairs
.isEmpty());
1664 // Set the resources to visit on the next calendar
1665 if (!resourcesToVisitNext
.isNull()) {
1666 resourcesToVisit
.moveFrom(resourcesToVisitNext
);
1670 // Process the nested resource bundle tables
1671 void processResource(UnicodeString
&path
, const char *key
, ResourceValue
&value
, UErrorCode
&errorCode
) {
1672 if (U_FAILURE(errorCode
)) return;
1674 ResourceTable table
= value
.getTable(errorCode
);
1675 if (U_FAILURE(errorCode
)) return;
1676 Hashtable
* stringMap
= NULL
;
1678 // Iterate over all the elements of the table and add them to the map
1679 for (int i
= 0; table
.getKeyAndValue(i
, key
, value
); i
++) {
1680 UnicodeString
keyUString(key
, -1, US_INV
);
1682 // Ignore '%variant' keys
1683 if (keyUString
.endsWith(kVariantTagUChar
, UPRV_LENGTHOF(kVariantTagUChar
))) {
1687 // == Handle String elements ==
1688 if (value
.getType() == URES_STRING
) {
1689 // We are on a leaf, store the map elements into the stringMap
1691 LocalPointer
<Hashtable
> stringMapPtr(new Hashtable(FALSE
, errorCode
), errorCode
);
1692 stringMap
= stringMapPtr
.getAlias();
1693 maps
.put(path
, stringMap
, errorCode
);
1694 // mapRefs will take ownership of 'stringMap':
1695 mapRefs
.addElement(stringMap
, errorCode
);
1696 if (U_FAILURE(errorCode
)) { return; }
1697 // Only release ownership after mapRefs takes it (no error happened):
1698 stringMapPtr
.orphan();
1699 stringMap
->setValueDeleter(uprv_deleteUObject
);
1701 U_ASSERT(stringMap
!= NULL
);
1702 int32_t valueStringSize
;
1703 const UChar
*valueString
= value
.getString(valueStringSize
, errorCode
);
1704 if (U_FAILURE(errorCode
)) { return; }
1705 LocalPointer
<UnicodeString
> valueUString(new UnicodeString(TRUE
, valueString
, valueStringSize
), errorCode
);
1706 stringMap
->put(keyUString
, valueUString
.orphan(), errorCode
);
1707 if (U_FAILURE(errorCode
)) { return; }
1710 U_ASSERT(stringMap
== NULL
);
1712 // Store the current path's length and append the current key to the path.
1713 int32_t pathLength
= path
.length();
1714 path
.append(SOLIDUS
).append(keyUString
);
1716 // In cyclicNameSets ignore everything but years/format/abbreviated
1717 // and zodiacs/format/abbreviated
1718 if (path
.startsWith(kCyclicNameSetsTagUChar
, UPRV_LENGTHOF(kCyclicNameSetsTagUChar
))) {
1720 int32_t startIndex
= UPRV_LENGTHOF(kCyclicNameSetsTagUChar
);
1722 if (startIndex
== path
.length()
1723 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kZodiacsUChar
)), kZodiacsUChar
, 0, UPRV_LENGTHOF(kZodiacsUChar
)) == 0
1724 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kYearsTagUChar
)), kYearsTagUChar
, 0, UPRV_LENGTHOF(kYearsTagUChar
)) == 0
1725 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kDayPartsTagUChar
)), kDayPartsTagUChar
, 0, UPRV_LENGTHOF(kDayPartsTagUChar
)) == 0) {
1726 startIndex
+= length
;
1728 if (startIndex
== path
.length()
1729 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kFormatTagUChar
)), kFormatTagUChar
, 0, UPRV_LENGTHOF(kFormatTagUChar
)) == 0) {
1730 startIndex
+= length
;
1732 if (startIndex
== path
.length()
1733 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kAbbrTagUChar
)), kAbbrTagUChar
, 0, UPRV_LENGTHOF(kAbbrTagUChar
)) == 0) {
1739 // Drop the latest key on the path and continue
1740 path
.retainBetween(0, pathLength
);
1745 // == Handle aliases ==
1746 if (arrays
.get(path
) != NULL
|| maps
.get(path
) != NULL
) {
1747 // Drop the latest key on the path and continue
1748 path
.retainBetween(0, pathLength
);
1752 AliasType aliasType
= processAliasFromValue(path
, value
, errorCode
);
1753 if (U_FAILURE(errorCode
)) { return; }
1754 if (aliasType
== SAME_CALENDAR
) {
1755 // Store the alias path and the current path on aliasPathPairs
1756 LocalPointer
<UnicodeString
> aliasRelativePathCopy(new UnicodeString(aliasRelativePath
), errorCode
);
1757 aliasPathPairs
.addElement(aliasRelativePathCopy
.getAlias(), errorCode
);
1758 if (U_FAILURE(errorCode
)) { return; }
1759 // Only release ownership after aliasPathPairs takes it (no error happened):
1760 aliasRelativePathCopy
.orphan();
1761 LocalPointer
<UnicodeString
> pathCopy(new UnicodeString(path
), errorCode
);
1762 aliasPathPairs
.addElement(pathCopy
.getAlias(), errorCode
);
1763 if (U_FAILURE(errorCode
)) { return; }
1764 // Only release ownership after aliasPathPairs takes it (no error happened):
1767 // Drop the latest key on the path and continue
1768 path
.retainBetween(0, pathLength
);
1771 U_ASSERT(aliasType
== NONE
);
1773 // == Handle data ==
1774 if (value
.getType() == URES_ARRAY
) {
1775 // We are on a leaf, store the array
1776 ResourceArray rDataArray
= value
.getArray(errorCode
);
1777 int32_t dataArraySize
= rDataArray
.getSize();
1778 LocalArray
<UnicodeString
> dataArray(new UnicodeString
[dataArraySize
], errorCode
);
1779 value
.getStringArray(dataArray
.getAlias(), dataArraySize
, errorCode
);
1780 arrays
.put(path
, dataArray
.orphan(), errorCode
);
1781 arraySizes
.puti(path
, dataArraySize
, errorCode
);
1782 if (U_FAILURE(errorCode
)) { return; }
1783 } else if (value
.getType() == URES_TABLE
) {
1784 // We are not on a leaf, recursively process the subtable.
1785 processResource(path
, key
, value
, errorCode
);
1786 if (U_FAILURE(errorCode
)) { return; }
1789 // Drop the latest key on the path
1790 path
.retainBetween(0, pathLength
);
1794 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
1795 AliasType
processAliasFromValue(UnicodeString
¤tRelativePath
, ResourceValue
&value
,
1796 UErrorCode
&errorCode
) {
1797 if (U_FAILURE(errorCode
)) { return NONE
; }
1799 if (value
.getType() == URES_ALIAS
) {
1800 int32_t aliasPathSize
;
1801 const UChar
* aliasPathUChar
= value
.getAliasString(aliasPathSize
, errorCode
);
1802 if (U_FAILURE(errorCode
)) { return NONE
; }
1803 UnicodeString
aliasPath(aliasPathUChar
, aliasPathSize
);
1804 const int32_t aliasPrefixLength
= UPRV_LENGTHOF(kCalendarAliasPrefixUChar
);
1805 if (aliasPath
.startsWith(kCalendarAliasPrefixUChar
, aliasPrefixLength
)
1806 && aliasPath
.length() > aliasPrefixLength
) {
1807 int32_t typeLimit
= aliasPath
.indexOf(SOLIDUS
, aliasPrefixLength
);
1808 if (typeLimit
> aliasPrefixLength
) {
1809 const UnicodeString aliasCalendarType
=
1810 aliasPath
.tempSubStringBetween(aliasPrefixLength
, typeLimit
);
1811 aliasRelativePath
.setTo(aliasPath
, typeLimit
+ 1, aliasPath
.length());
1813 if (currentCalendarType
== aliasCalendarType
1814 && currentRelativePath
!= aliasRelativePath
) {
1815 // If we have an alias to the same calendar, the path to the resource must be different
1816 return SAME_CALENDAR
;
1818 } else if (currentCalendarType
!= aliasCalendarType
1819 && currentRelativePath
== aliasRelativePath
) {
1820 // If we have an alias to a different calendar, the path to the resource must be the same
1821 if (aliasCalendarType
.compare(kGregorianTagUChar
, UPRV_LENGTHOF(kGregorianTagUChar
)) == 0) {
1823 } else if (nextCalendarType
.isBogus()) {
1824 nextCalendarType
= aliasCalendarType
;
1825 return DIFFERENT_CALENDAR
;
1826 } else if (nextCalendarType
== aliasCalendarType
) {
1827 return DIFFERENT_CALENDAR
;
1832 errorCode
= U_INTERNAL_PROGRAM_ERROR
;
1838 // Deleter function to be used by 'arrays'
1839 static void U_CALLCONV
deleteUnicodeStringArray(void *uArray
) {
1840 delete[] static_cast<UnicodeString
*>(uArray
);
1843 // Deleter function to be used by 'maps'
1844 static void U_CALLCONV
deleteHashtable(void *table
) {
1845 delete static_cast<Hashtable
*>(table
);
1848 // Virtual destructors have to be defined out of line
1849 CalendarDataSink::~CalendarDataSink() {
1850 arrays
.setValueDeleter(deleteUnicodeStringArray
);
1854 //------------------------------------------------------
1857 initField(UnicodeString
**field
, int32_t& length
, const UChar
*data
, LastResortSize numStr
, LastResortSize strLen
, UErrorCode
&status
) {
1858 if (U_SUCCESS(status
)) {
1860 *field
= newUnicodeStringArray((size_t)numStr
);
1862 for(int32_t i
= 0; i
<length
; i
++) {
1863 // readonly aliases - all "data" strings are constant
1864 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1865 (*(field
)+i
)->setTo(TRUE
, data
+(i
*((int32_t)strLen
)), -1);
1870 status
= U_MEMORY_ALLOCATION_ERROR
;
1876 initField(UnicodeString
**field
, int32_t& length
, CalendarDataSink
&sink
, CharString
&key
, UErrorCode
&status
) {
1877 if (U_SUCCESS(status
)) {
1878 UnicodeString
keyUString(key
.data(), -1, US_INV
);
1879 UnicodeString
* array
= static_cast<UnicodeString
*>(sink
.arrays
.get(keyUString
));
1881 if (array
!= NULL
) {
1882 length
= sink
.arraySizes
.geti(keyUString
);
1884 // DateFormatSymbols takes ownership of the array:
1885 sink
.arrays
.remove(keyUString
);
1888 status
= U_MISSING_RESOURCE_ERROR
;
1894 initField(UnicodeString
**field
, int32_t& length
, CalendarDataSink
&sink
, CharString
&key
, int32_t arrayOffset
, UErrorCode
&status
) {
1895 if (U_SUCCESS(status
)) {
1896 UnicodeString
keyUString(key
.data(), -1, US_INV
);
1897 UnicodeString
* array
= static_cast<UnicodeString
*>(sink
.arrays
.get(keyUString
));
1899 if (array
!= NULL
) {
1900 int32_t arrayLength
= sink
.arraySizes
.geti(keyUString
);
1901 length
= arrayLength
+ arrayOffset
;
1902 *field
= new UnicodeString
[length
];
1903 if (*field
== NULL
) {
1904 status
= U_MEMORY_ALLOCATION_ERROR
;
1907 uprv_arrayCopy(array
, 0, *field
, arrayOffset
, arrayLength
);
1910 status
= U_MISSING_RESOURCE_ERROR
;
1916 initLeapMonthPattern(UnicodeString
*field
, int32_t index
, CalendarDataSink
&sink
, CharString
&path
, UErrorCode
&status
) {
1917 field
[index
].remove();
1918 if (U_SUCCESS(status
)) {
1919 UnicodeString
pathUString(path
.data(), -1, US_INV
);
1920 Hashtable
*leapMonthTable
= static_cast<Hashtable
*>(sink
.maps
.get(pathUString
));
1921 if (leapMonthTable
!= NULL
) {
1922 UnicodeString
leapLabel(FALSE
, kLeapTagUChar
, UPRV_LENGTHOF(kLeapTagUChar
));
1923 UnicodeString
*leapMonthPattern
= static_cast<UnicodeString
*>(leapMonthTable
->get(leapLabel
));
1924 if (leapMonthPattern
!= NULL
) {
1925 field
[index
].fastCopyFrom(*leapMonthPattern
);
1927 field
[index
].setToBogus();
1931 status
= U_MISSING_RESOURCE_ERROR
;
1936 &buildResourcePath(CharString
&path
, const char* segment1
, UErrorCode
&errorCode
) {
1937 return path
.clear().append(segment1
, -1, errorCode
);
1941 &buildResourcePath(CharString
&path
, const char* segment1
, const char* segment2
,
1942 UErrorCode
&errorCode
) {
1943 return buildResourcePath(path
, segment1
, errorCode
).append('/', errorCode
)
1944 .append(segment2
, -1, errorCode
);
1948 &buildResourcePath(CharString
&path
, const char* segment1
, const char* segment2
,
1949 const char* segment3
, UErrorCode
&errorCode
) {
1950 return buildResourcePath(path
, segment1
, segment2
, errorCode
).append('/', errorCode
)
1951 .append(segment3
, -1, errorCode
);
1955 &buildResourcePath(CharString
&path
, const char* segment1
, const char* segment2
,
1956 const char* segment3
, const char* segment4
, UErrorCode
&errorCode
) {
1957 return buildResourcePath(path
, segment1
, segment2
, segment3
, errorCode
).append('/', errorCode
)
1958 .append(segment4
, -1, errorCode
);
1962 const char * usageTypeName
;
1963 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue
;
1964 } ContextUsageTypeNameToEnumValue
;
1966 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap
[] = {
1967 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1968 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat
},
1969 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow
},
1970 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone
},
1971 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev
},
1972 { "era-name", DateFormatSymbols::kCapContextUsageEraWide
},
1973 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow
},
1974 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong
},
1975 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort
},
1976 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat
},
1977 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow
},
1978 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone
},
1979 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong
},
1980 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort
},
1981 { NULL
, (DateFormatSymbols::ECapitalizationContextUsageType
)0 },
1984 // Resource keys to look up localized strings for day periods.
1985 // The first one must be midnight and the second must be noon, so that their indices coincide
1986 // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1987 static const char *dayPeriodKeys
[] = {"midnight", "noon",
1988 "morning1", "afternoon1", "evening1", "night1",
1989 "morning2", "afternoon2", "evening2", "night2"};
1991 UnicodeString
* loadDayPeriodStrings(CalendarDataSink
&sink
, CharString
&path
,
1992 int32_t &stringCount
, UErrorCode
&status
) {
1993 if (U_FAILURE(status
)) { return NULL
; }
1995 UnicodeString
pathUString(path
.data(), -1, US_INV
);
1996 Hashtable
* map
= static_cast<Hashtable
*>(sink
.maps
.get(pathUString
));
1998 stringCount
= UPRV_LENGTHOF(dayPeriodKeys
);
1999 UnicodeString
*strings
= new UnicodeString
[stringCount
];
2000 if (strings
== NULL
) {
2001 status
= U_MEMORY_ALLOCATION_ERROR
;
2006 for (int32_t i
= 0; i
< stringCount
; ++i
) {
2007 UnicodeString
dayPeriodKey(dayPeriodKeys
[i
], -1, US_INV
);
2008 UnicodeString
*dayPeriod
= static_cast<UnicodeString
*>(map
->get(dayPeriodKey
));
2009 if (dayPeriod
!= NULL
) {
2010 strings
[i
].fastCopyFrom(*dayPeriod
);
2012 strings
[i
].setToBogus();
2016 for (int32_t i
= 0; i
< stringCount
; i
++) {
2017 strings
[i
].setToBogus();
2025 DateFormatSymbols::initializeData(const Locale
& locale
, const char *type
, UErrorCode
& status
, UBool useLastResortData
)
2028 /* In case something goes wrong, initialize all of the data to NULL. */
2034 fNarrowErasCount
= 0;
2037 fShortMonths
= NULL
;
2038 fShortMonthsCount
=0;
2039 fNarrowMonths
= NULL
;
2040 fNarrowMonthsCount
=0;
2041 fStandaloneMonths
= NULL
;
2042 fStandaloneMonthsCount
=0;
2043 fStandaloneShortMonths
= NULL
;
2044 fStandaloneShortMonthsCount
=0;
2045 fStandaloneNarrowMonths
= NULL
;
2046 fStandaloneNarrowMonthsCount
=0;
2049 fShortWeekdays
= NULL
;
2050 fShortWeekdaysCount
=0;
2051 fShorterWeekdays
= NULL
;
2052 fShorterWeekdaysCount
=0;
2053 fNarrowWeekdays
= NULL
;
2054 fNarrowWeekdaysCount
=0;
2055 fStandaloneWeekdays
= NULL
;
2056 fStandaloneWeekdaysCount
=0;
2057 fStandaloneShortWeekdays
= NULL
;
2058 fStandaloneShortWeekdaysCount
=0;
2059 fStandaloneShorterWeekdays
= NULL
;
2060 fStandaloneShorterWeekdaysCount
=0;
2061 fStandaloneNarrowWeekdays
= NULL
;
2062 fStandaloneNarrowWeekdaysCount
=0;
2065 fNarrowAmPms
= NULL
;
2066 fNarrowAmPmsCount
=0;
2067 fTimeSeparator
.setToBogus();
2070 fShortQuarters
= NULL
;
2071 fShortQuartersCount
= 0;
2072 fStandaloneQuarters
= NULL
;
2073 fStandaloneQuartersCount
= 0;
2074 fStandaloneShortQuarters
= NULL
;
2075 fStandaloneShortQuartersCount
= 0;
2076 fLeapMonthPatterns
= NULL
;
2077 fLeapMonthPatternsCount
= 0;
2078 fShortYearNames
= NULL
;
2079 fShortYearNamesCount
= 0;
2080 fShortZodiacNames
= NULL
;
2081 fShortZodiacNamesCount
= 0;
2082 fZoneStringsRowCount
= 0;
2083 fZoneStringsColCount
= 0;
2084 fZoneStrings
= NULL
;
2085 fLocaleZoneStrings
= NULL
;
2086 fAbbreviatedDayPeriods
= NULL
;
2087 fAbbreviatedDayPeriodsCount
= 0;
2088 fWideDayPeriods
= NULL
;
2089 fWideDayPeriodsCount
= 0;
2090 fNarrowDayPeriods
= NULL
;
2091 fNarrowDayPeriodsCount
= 0;
2092 fStandaloneAbbreviatedDayPeriods
= NULL
;
2093 fStandaloneAbbreviatedDayPeriodsCount
= 0;
2094 fStandaloneWideDayPeriods
= NULL
;
2095 fStandaloneWideDayPeriodsCount
= 0;
2096 fStandaloneNarrowDayPeriods
= NULL
;
2097 fStandaloneNarrowDayPeriodsCount
= 0;
2098 uprv_memset(fCapitalization
, 0, sizeof(fCapitalization
));
2100 // We need to preserve the requested locale for
2101 // lazy ZoneStringFormat instantiation. ZoneStringFormat
2102 // is region sensitive, thus, bundle locale bundle's locale
2103 // is not sufficient.
2104 fZSFLocale
= locale
;
2106 if (U_FAILURE(status
)) return;
2108 // Create a CalendarDataSink to process this data and the resouce bundles
2109 CalendarDataSink
calendarSink(status
);
2110 UResourceBundle
*rb
= ures_open(NULL
, locale
.getBaseName(), &status
);
2111 UResourceBundle
*cb
= ures_getByKey(rb
, gCalendarTag
, NULL
, &status
);
2113 if (U_FAILURE(status
)) return;
2115 // Iterate over the resource bundle data following the fallbacks through different calendar types
2116 UnicodeString
calendarType((type
!= NULL
&& *type
!= '\0')? type
: gGregorianTag
, -1, US_INV
);
2117 while (!calendarType
.isBogus()) {
2118 CharString calendarTypeBuffer
;
2119 calendarTypeBuffer
.appendInvariantChars(calendarType
, status
);
2120 if (U_FAILURE(status
)) { return; }
2121 const char *calendarTypeCArray
= calendarTypeBuffer
.data();
2123 // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2124 UErrorCode oldStatus
= status
;
2125 UResourceBundle
*ctb
= ures_getByKeyWithFallback(cb
, calendarTypeCArray
, NULL
, &status
);
2126 if (status
== U_MISSING_RESOURCE_ERROR
) {
2128 if (uprv_strcmp(calendarTypeCArray
, gGregorianTag
) != 0) {
2129 calendarType
.setTo(FALSE
, kGregorianTagUChar
, UPRV_LENGTHOF(kGregorianTagUChar
));
2130 calendarSink
.visitAllResources();
2137 calendarSink
.preEnumerate(calendarType
);
2138 ures_getAllItemsWithFallback(ctb
, "", calendarSink
, status
);
2140 if (U_FAILURE(status
)) break;
2142 // Stop loading when gregorian was loaded
2143 if (uprv_strcmp(calendarTypeCArray
, gGregorianTag
) == 0) {
2147 // Get the next calendar type to process from the sink
2148 calendarType
= calendarSink
.nextCalendarType
;
2150 // Gregorian is always the last fallback
2151 if (calendarType
.isBogus()) {
2152 calendarType
.setTo(FALSE
, kGregorianTagUChar
, UPRV_LENGTHOF(kGregorianTagUChar
));
2153 calendarSink
.visitAllResources();
2157 // CharString object to build paths
2160 // Load Leap Month Patterns
2161 UErrorCode tempStatus
= status
;
2162 fLeapMonthPatterns
= newUnicodeStringArray(kMonthPatternsCount
);
2163 if (fLeapMonthPatterns
) {
2164 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternFormatWide
, calendarSink
,
2165 buildResourcePath(path
, gMonthPatternsTag
, gNamesFormatTag
, gNamesWideTag
, tempStatus
), tempStatus
);
2166 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternFormatAbbrev
, calendarSink
,
2167 buildResourcePath(path
, gMonthPatternsTag
, gNamesFormatTag
, gNamesAbbrTag
, tempStatus
), tempStatus
);
2168 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternFormatNarrow
, calendarSink
,
2169 buildResourcePath(path
, gMonthPatternsTag
, gNamesFormatTag
, gNamesNarrowTag
, tempStatus
), tempStatus
);
2170 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternStandaloneWide
, calendarSink
,
2171 buildResourcePath(path
, gMonthPatternsTag
, gNamesStandaloneTag
, gNamesWideTag
, tempStatus
), tempStatus
);
2172 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternStandaloneAbbrev
, calendarSink
,
2173 buildResourcePath(path
, gMonthPatternsTag
, gNamesStandaloneTag
, gNamesAbbrTag
, tempStatus
), tempStatus
);
2174 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternStandaloneNarrow
, calendarSink
,
2175 buildResourcePath(path
, gMonthPatternsTag
, gNamesStandaloneTag
, gNamesNarrowTag
, tempStatus
), tempStatus
);
2176 initLeapMonthPattern(fLeapMonthPatterns
, kLeapMonthPatternNumeric
, calendarSink
,
2177 buildResourcePath(path
, gMonthPatternsTag
, gNamesNumericTag
, gNamesAllTag
, tempStatus
), tempStatus
);
2178 if (U_SUCCESS(tempStatus
)) {
2179 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2180 // The ordering of the following statements is important.
2181 if (fLeapMonthPatterns
[kLeapMonthPatternFormatAbbrev
].isEmpty()) {
2182 fLeapMonthPatterns
[kLeapMonthPatternFormatAbbrev
].setTo(fLeapMonthPatterns
[kLeapMonthPatternFormatWide
]);
2184 if (fLeapMonthPatterns
[kLeapMonthPatternFormatNarrow
].isEmpty()) {
2185 fLeapMonthPatterns
[kLeapMonthPatternFormatNarrow
].setTo(fLeapMonthPatterns
[kLeapMonthPatternStandaloneNarrow
]);
2187 if (fLeapMonthPatterns
[kLeapMonthPatternStandaloneWide
].isEmpty()) {
2188 fLeapMonthPatterns
[kLeapMonthPatternStandaloneWide
].setTo(fLeapMonthPatterns
[kLeapMonthPatternFormatWide
]);
2190 if (fLeapMonthPatterns
[kLeapMonthPatternStandaloneAbbrev
].isEmpty()) {
2191 fLeapMonthPatterns
[kLeapMonthPatternStandaloneAbbrev
].setTo(fLeapMonthPatterns
[kLeapMonthPatternFormatAbbrev
]);
2194 fLeapMonthPatternsCount
= kMonthPatternsCount
;
2196 delete[] fLeapMonthPatterns
;
2197 fLeapMonthPatterns
= NULL
;
2201 // Load cyclic names sets
2202 tempStatus
= status
;
2203 initField(&fShortYearNames
, fShortYearNamesCount
, calendarSink
,
2204 buildResourcePath(path
, gCyclicNameSetsTag
, gNameSetYearsTag
, gNamesFormatTag
, gNamesAbbrTag
, tempStatus
), tempStatus
);
2205 initField(&fShortZodiacNames
, fShortZodiacNamesCount
, calendarSink
,
2206 buildResourcePath(path
, gCyclicNameSetsTag
, gNameSetZodiacsTag
, gNamesFormatTag
, gNamesAbbrTag
, tempStatus
), tempStatus
);
2208 // Load context transforms and capitalization
2209 tempStatus
= U_ZERO_ERROR
;
2210 UResourceBundle
*localeBundle
= ures_open(NULL
, locale
.getName(), &tempStatus
);
2211 if (U_SUCCESS(tempStatus
)) {
2212 UResourceBundle
*contextTransforms
= ures_getByKeyWithFallback(localeBundle
, gContextTransformsTag
, NULL
, &tempStatus
);
2213 if (U_SUCCESS(tempStatus
)) {
2214 UResourceBundle
*contextTransformUsage
;
2215 while ( (contextTransformUsage
= ures_getNextResource(contextTransforms
, NULL
, &tempStatus
)) != NULL
) {
2216 const int32_t * intVector
= ures_getIntVector(contextTransformUsage
, &len
, &status
);
2217 if (U_SUCCESS(tempStatus
) && intVector
!= NULL
&& len
>= 2) {
2218 const char* usageType
= ures_getKey(contextTransformUsage
);
2219 if (usageType
!= NULL
) {
2220 const ContextUsageTypeNameToEnumValue
* typeMapPtr
= contextUsageTypeMap
;
2221 int32_t compResult
= 0;
2222 // linear search; list is short and we cannot be sure that bsearch is available
2223 while ( typeMapPtr
->usageTypeName
!= NULL
&& (compResult
= uprv_strcmp(usageType
, typeMapPtr
->usageTypeName
)) > 0 ) {
2226 if (typeMapPtr
->usageTypeName
!= NULL
&& compResult
== 0) {
2227 fCapitalization
[typeMapPtr
->usageTypeEnumValue
][0] = intVector
[0];
2228 fCapitalization
[typeMapPtr
->usageTypeEnumValue
][1] = intVector
[1];
2232 tempStatus
= U_ZERO_ERROR
;
2233 ures_close(contextTransformUsage
);
2235 ures_close(contextTransforms
);
2238 tempStatus
= U_ZERO_ERROR
;
2239 const LocalPointer
<NumberingSystem
> numberingSystem(
2240 NumberingSystem::createInstance(locale
, tempStatus
), tempStatus
);
2241 if (U_SUCCESS(tempStatus
)) {
2242 // These functions all fail gracefully if passed NULL pointers and
2243 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2244 // to check for errors once after all calls are made.
2245 const LocalUResourceBundlePointer
numberElementsData(ures_getByKeyWithFallback(
2246 localeBundle
, gNumberElementsTag
, NULL
, &tempStatus
));
2247 const LocalUResourceBundlePointer
nsNameData(ures_getByKeyWithFallback(
2248 numberElementsData
.getAlias(), numberingSystem
->getName(), NULL
, &tempStatus
));
2249 const LocalUResourceBundlePointer
symbolsData(ures_getByKeyWithFallback(
2250 nsNameData
.getAlias(), gSymbolsTag
, NULL
, &tempStatus
));
2251 fTimeSeparator
= ures_getUnicodeStringByKey(
2252 symbolsData
.getAlias(), gTimeSeparatorTag
, &tempStatus
);
2253 if (U_FAILURE(tempStatus
)) {
2254 fTimeSeparator
.setToBogus();
2258 ures_close(localeBundle
);
2261 if (fTimeSeparator
.isBogus()) {
2262 fTimeSeparator
.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR
);
2266 fWideDayPeriods
= loadDayPeriodStrings(calendarSink
,
2267 buildResourcePath(path
, gDayPeriodTag
, gNamesFormatTag
, gNamesWideTag
, status
),
2268 fWideDayPeriodsCount
, status
);
2269 fNarrowDayPeriods
= loadDayPeriodStrings(calendarSink
,
2270 buildResourcePath(path
, gDayPeriodTag
, gNamesFormatTag
, gNamesNarrowTag
, status
),
2271 fNarrowDayPeriodsCount
, status
);
2272 fAbbreviatedDayPeriods
= loadDayPeriodStrings(calendarSink
,
2273 buildResourcePath(path
, gDayPeriodTag
, gNamesFormatTag
, gNamesAbbrTag
, status
),
2274 fAbbreviatedDayPeriodsCount
, status
);
2275 fStandaloneWideDayPeriods
= loadDayPeriodStrings(calendarSink
,
2276 buildResourcePath(path
, gDayPeriodTag
, gNamesStandaloneTag
, gNamesWideTag
, status
),
2277 fStandaloneWideDayPeriodsCount
, status
);
2278 fStandaloneNarrowDayPeriods
= loadDayPeriodStrings(calendarSink
,
2279 buildResourcePath(path
, gDayPeriodTag
, gNamesStandaloneTag
, gNamesNarrowTag
, status
),
2280 fStandaloneNarrowDayPeriodsCount
, status
);
2281 fStandaloneAbbreviatedDayPeriods
= loadDayPeriodStrings(calendarSink
,
2282 buildResourcePath(path
, gDayPeriodTag
, gNamesStandaloneTag
, gNamesAbbrTag
, status
),
2283 fStandaloneAbbreviatedDayPeriodsCount
, status
);
2285 U_LOCALE_BASED(locBased
, *this);
2286 // if we make it to here, the resource data is cool, and we can get everything out
2287 // of it that we need except for the time-zone and localized-pattern data, which
2288 // are stored in a separate file
2289 locBased
.setLocaleIDs(ures_getLocaleByType(cb
, ULOC_VALID_LOCALE
, &status
),
2290 ures_getLocaleByType(cb
, ULOC_ACTUAL_LOCALE
, &status
));
2293 initField(&fEras
, fErasCount
, calendarSink
, buildResourcePath(path
, gErasTag
, gNamesAbbrTag
, status
), status
);
2294 UErrorCode oldStatus
= status
;
2295 initField(&fEraNames
, fEraNamesCount
, calendarSink
, buildResourcePath(path
, gErasTag
, gNamesWideTag
, status
), status
);
2296 if (status
== U_MISSING_RESOURCE_ERROR
) { // Workaround because eras/wide was omitted from CLDR 1.3
2298 assignArray(fEraNames
, fEraNamesCount
, fEras
, fErasCount
);
2300 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2302 initField(&fNarrowEras
, fNarrowErasCount
, calendarSink
, buildResourcePath(path
, gErasTag
, gNamesNarrowTag
, status
), status
);
2303 if (status
== U_MISSING_RESOURCE_ERROR
) { // Workaround because eras/wide was omitted from CLDR 1.3
2305 assignArray(fNarrowEras
, fNarrowErasCount
, fEras
, fErasCount
);
2309 initField(&fMonths
, fMonthsCount
, calendarSink
,
2310 buildResourcePath(path
, gMonthNamesTag
, gNamesFormatTag
, gNamesWideTag
, status
), status
);
2311 initField(&fShortMonths
, fShortMonthsCount
, calendarSink
,
2312 buildResourcePath(path
, gMonthNamesTag
, gNamesFormatTag
, gNamesAbbrTag
, status
), status
);
2313 initField(&fStandaloneMonths
, fStandaloneMonthsCount
, calendarSink
,
2314 buildResourcePath(path
, gMonthNamesTag
, gNamesStandaloneTag
, gNamesWideTag
, status
), status
);
2315 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/wide not available, use format/wide */
2316 status
= U_ZERO_ERROR
;
2317 assignArray(fStandaloneMonths
, fStandaloneMonthsCount
, fMonths
, fMonthsCount
);
2319 initField(&fStandaloneShortMonths
, fStandaloneShortMonthsCount
, calendarSink
,
2320 buildResourcePath(path
, gMonthNamesTag
, gNamesStandaloneTag
, gNamesAbbrTag
, status
), status
);
2321 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/abbreviated not available, use format/abbreviated */
2322 status
= U_ZERO_ERROR
;
2323 assignArray(fStandaloneShortMonths
, fStandaloneShortMonthsCount
, fShortMonths
, fShortMonthsCount
);
2326 UErrorCode narrowMonthsEC
= status
;
2327 UErrorCode standaloneNarrowMonthsEC
= status
;
2328 initField(&fNarrowMonths
, fNarrowMonthsCount
, calendarSink
,
2329 buildResourcePath(path
, gMonthNamesTag
, gNamesFormatTag
, gNamesNarrowTag
, narrowMonthsEC
), narrowMonthsEC
);
2330 initField(&fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
, calendarSink
,
2331 buildResourcePath(path
, gMonthNamesTag
, gNamesStandaloneTag
, gNamesNarrowTag
, narrowMonthsEC
), standaloneNarrowMonthsEC
);
2332 if (narrowMonthsEC
== U_MISSING_RESOURCE_ERROR
&& standaloneNarrowMonthsEC
!= U_MISSING_RESOURCE_ERROR
) {
2333 // If format/narrow not available, use standalone/narrow
2334 assignArray(fNarrowMonths
, fNarrowMonthsCount
, fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
);
2335 } else if (narrowMonthsEC
!= U_MISSING_RESOURCE_ERROR
&& standaloneNarrowMonthsEC
== U_MISSING_RESOURCE_ERROR
) {
2336 // If standalone/narrow not availabe, use format/narrow
2337 assignArray(fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
, fNarrowMonths
, fNarrowMonthsCount
);
2338 } else if (narrowMonthsEC
== U_MISSING_RESOURCE_ERROR
&& standaloneNarrowMonthsEC
== U_MISSING_RESOURCE_ERROR
) {
2339 // If neither is available, use format/abbreviated
2340 assignArray(fNarrowMonths
, fNarrowMonthsCount
, fShortMonths
, fShortMonthsCount
);
2341 assignArray(fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
, fShortMonths
, fShortMonthsCount
);
2344 // Load AM/PM markers
2345 initField(&fAmPms
, fAmPmsCount
, calendarSink
,
2346 buildResourcePath(path
, gAmPmMarkersTag
, status
), status
);
2347 initField(&fNarrowAmPms
, fNarrowAmPmsCount
, calendarSink
,
2348 buildResourcePath(path
, gAmPmMarkersNarrowTag
, status
), status
);
2351 initField(&fQuarters
, fQuartersCount
, calendarSink
,
2352 buildResourcePath(path
, gQuartersTag
, gNamesFormatTag
, gNamesWideTag
, status
), status
);
2353 initField(&fShortQuarters
, fShortQuartersCount
, calendarSink
,
2354 buildResourcePath(path
, gQuartersTag
, gNamesFormatTag
, gNamesAbbrTag
, status
), status
);
2356 initField(&fStandaloneQuarters
, fStandaloneQuartersCount
, calendarSink
,
2357 buildResourcePath(path
, gQuartersTag
, gNamesStandaloneTag
, gNamesWideTag
, status
), status
);
2358 if(status
== U_MISSING_RESOURCE_ERROR
) {
2359 status
= U_ZERO_ERROR
;
2360 assignArray(fStandaloneQuarters
, fStandaloneQuartersCount
, fQuarters
, fQuartersCount
);
2362 initField(&fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, calendarSink
,
2363 buildResourcePath(path
, gQuartersTag
, gNamesStandaloneTag
, gNamesAbbrTag
, status
), status
);
2364 if(status
== U_MISSING_RESOURCE_ERROR
) {
2365 status
= U_ZERO_ERROR
;
2366 assignArray(fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, fShortQuarters
, fShortQuartersCount
);
2369 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2371 // fastCopyFrom()/setTo() - see assignArray comments
2372 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2373 fLocalPatternChars.setTo(TRUE, resStr, len);
2374 // If the locale data does not include new pattern chars, use the defaults
2375 // TODO: Consider making this an error, since this may add conflicting characters.
2376 if (len < PATTERN_CHARS_LEN) {
2377 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2380 fLocalPatternChars
.setTo(TRUE
, gPatternChars
, PATTERN_CHARS_LEN
);
2382 // Format wide weekdays -> fWeekdays
2383 // {sfb} fixed to handle 1-based weekdays
2384 initField(&fWeekdays
, fWeekdaysCount
, calendarSink
,
2385 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesWideTag
, status
), 1, status
);
2387 // Format abbreviated weekdays -> fShortWeekdays
2388 initField(&fShortWeekdays
, fShortWeekdaysCount
, calendarSink
,
2389 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesAbbrTag
, status
), 1, status
);
2391 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2392 initField(&fShorterWeekdays
, fShorterWeekdaysCount
, calendarSink
,
2393 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesShortTag
, status
), 1, status
);
2394 if (status
== U_MISSING_RESOURCE_ERROR
) {
2395 status
= U_ZERO_ERROR
;
2396 assignArray(fShorterWeekdays
, fShorterWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2399 // Stand-alone wide weekdays -> fStandaloneWeekdays
2400 initField(&fStandaloneWeekdays
, fStandaloneWeekdaysCount
, calendarSink
,
2401 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesWideTag
, status
), 1, status
);
2402 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/wide is not available, use format/wide */
2403 status
= U_ZERO_ERROR
;
2404 assignArray(fStandaloneWeekdays
, fStandaloneWeekdaysCount
, fWeekdays
, fWeekdaysCount
);
2407 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2408 initField(&fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, calendarSink
,
2409 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesAbbrTag
, status
), 1, status
);
2410 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/abbreviated is not available, use format/abbreviated */
2411 status
= U_ZERO_ERROR
;
2412 assignArray(fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2415 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2416 initField(&fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, calendarSink
,
2417 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesShortTag
, status
), 1, status
);
2418 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/short is not available, use format/short */
2419 status
= U_ZERO_ERROR
;
2420 assignArray(fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, fShorterWeekdays
, fShorterWeekdaysCount
);
2423 // Format narrow weekdays -> fNarrowWeekdays
2424 UErrorCode narrowWeeksEC
= status
;
2425 initField(&fNarrowWeekdays
, fNarrowWeekdaysCount
, calendarSink
,
2426 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesNarrowTag
, status
), 1, narrowWeeksEC
);
2427 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2428 UErrorCode standaloneNarrowWeeksEC
= status
;
2429 initField(&fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, calendarSink
,
2430 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesNarrowTag
, status
), 1, standaloneNarrowWeeksEC
);
2432 if (narrowWeeksEC
== U_MISSING_RESOURCE_ERROR
&& standaloneNarrowWeeksEC
!= U_MISSING_RESOURCE_ERROR
) {
2433 // If format/narrow not available, use standalone/narrow
2434 assignArray(fNarrowWeekdays
, fNarrowWeekdaysCount
, fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
);
2435 } else if (narrowWeeksEC
!= U_MISSING_RESOURCE_ERROR
&& standaloneNarrowWeeksEC
== U_MISSING_RESOURCE_ERROR
) {
2436 // If standalone/narrow not available, use format/narrow
2437 assignArray(fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, fNarrowWeekdays
, fNarrowWeekdaysCount
);
2438 } else if (narrowWeeksEC
== U_MISSING_RESOURCE_ERROR
&& standaloneNarrowWeeksEC
== U_MISSING_RESOURCE_ERROR
) {
2439 // If neither is available, use format/abbreviated
2440 assignArray(fNarrowWeekdays
, fNarrowWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2441 assignArray(fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2444 // Last resort fallback in case previous data wasn't loaded
2445 if (U_FAILURE(status
))
2447 if (useLastResortData
)
2449 // Handle the case in which there is no resource data present.
2450 // We don't have to generate usable patterns in this situation;
2451 // we just need to produce something that will be semi-intelligible
2454 status
= U_USING_FALLBACK_WARNING
;
2455 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2456 initField(&fEras
, fErasCount
, (const UChar
*)gLastResortEras
, kEraNum
, kEraLen
, status
);
2457 initField(&fEraNames
, fEraNamesCount
, (const UChar
*)gLastResortEras
, kEraNum
, kEraLen
, status
);
2458 initField(&fNarrowEras
, fNarrowErasCount
, (const UChar
*)gLastResortEras
, kEraNum
, kEraLen
, status
);
2459 initField(&fMonths
, fMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2460 initField(&fShortMonths
, fShortMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2461 initField(&fNarrowMonths
, fNarrowMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2462 initField(&fStandaloneMonths
, fStandaloneMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2463 initField(&fStandaloneShortMonths
, fStandaloneShortMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2464 initField(&fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2465 initField(&fWeekdays
, fWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2466 initField(&fShortWeekdays
, fShortWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2467 initField(&fShorterWeekdays
, fShorterWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2468 initField(&fNarrowWeekdays
, fNarrowWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2469 initField(&fStandaloneWeekdays
, fStandaloneWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2470 initField(&fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2471 initField(&fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2472 initField(&fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2473 initField(&fAmPms
, fAmPmsCount
, (const UChar
*)gLastResortAmPmMarkers
, kAmPmNum
, kAmPmLen
, status
);
2474 initField(&fNarrowAmPms
, fNarrowAmPmsCount
, (const UChar
*)gLastResortAmPmMarkers
, kAmPmNum
, kAmPmLen
, status
);
2475 initField(&fQuarters
, fQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2476 initField(&fShortQuarters
, fShortQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2477 initField(&fStandaloneQuarters
, fStandaloneQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2478 initField(&fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2479 fLocalPatternChars
.setTo(TRUE
, gPatternChars
, PATTERN_CHARS_LEN
);
2489 DateFormatSymbols::getLocale(ULocDataLocaleType type
, UErrorCode
& status
) const {
2490 U_LOCALE_BASED(locBased
, *this);
2491 return locBased
.getLocale(type
, status
);
2496 #endif /* #if !UCONFIG_NO_FORMATTING */