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 *******************************************************************************
27 #include "unicode/utypes.h"
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"
50 #include "shareddateformatsymbols.h"
51 #include "unicode/calendar.h"
52 #include "unifiedcache.h"
54 // *****************************************************************************
55 // class DateFormatSymbols
56 // *****************************************************************************
59 * These are static arrays we use only in the case where we have no
63 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
64 #define PATTERN_CHARS_LEN 38
66 #define PATTERN_CHARS_LEN 37
70 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
71 * locales use the same these unlocalized pattern characters.
73 static const UChar gPatternChars
[] = {
74 // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
75 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
77 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
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
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.
93 // These are the month names and abbreviations of last resort.
94 static const UChar gLastResortMonthNames
[13][3] =
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" */
111 // These are the weekday names and abbreviations of last resort.
112 static const UChar gLastResortDayNames
[8][2] =
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" */
124 // These are the quarter names and abbreviations of last resort.
125 static const UChar gLastResortQuarters
[4][2] =
127 {0x0031, 0x0000}, /* "1" */
128 {0x0032, 0x0000}, /* "2" */
129 {0x0033, 0x0000}, /* "3" */
130 {0x0034, 0x0000}, /* "4" */
133 // These are the am/pm and BC/AD markers of last resort.
134 static const UChar gLastResortAmPmMarkers
[2][3] =
136 {0x0041, 0x004D, 0x0000}, /* "AM" */
137 {0x0050, 0x004D, 0x0000} /* "PM" */
140 static const UChar gLastResortEras
[2][3] =
142 {0x0042, 0x0043, 0x0000}, /* "BC" */
143 {0x0041, 0x0044, 0x0000} /* "AD" */
146 /* Sizes for the last resort string arrays */
147 typedef enum LastResortSize
{
172 SharedDateFormatSymbols::~SharedDateFormatSymbols() {
175 template<> U_I18N_API
176 const SharedDateFormatSymbols
*
177 LocaleCacheKey
<SharedDateFormatSymbols
>::createObject(
178 const void * /*unusedContext*/, UErrorCode
&status
) const {
180 Calendar::getCalendarTypeFromLocale(fLoc
, type
, UPRV_LENGTHOF(type
), status
);
181 if (U_FAILURE(status
)) {
184 SharedDateFormatSymbols
*shared
185 = new SharedDateFormatSymbols(fLoc
, type
, status
);
186 if (shared
== NULL
) {
187 status
= U_MEMORY_ALLOCATION_ERROR
;
190 if (U_FAILURE(status
)) {
198 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols
)
200 #define kSUPPLEMENTAL "supplementalData"
203 * These are the tags we expect to see in normal resource bundle files associated
204 * with a locale and calendar
206 static const char gCalendarTag
[]="calendar";
207 static const char gGregorianTag
[]="gregorian";
208 static const char gErasTag
[]="eras";
209 static const char gCyclicNameSetsTag
[]="cyclicNameSets";
210 static const char gNameSetYearsTag
[]="years";
211 static const char gNameSetZodiacsTag
[]="zodiacs";
212 static const char gMonthNamesTag
[]="monthNames";
213 static const char gMonthPatternsTag
[]="monthPatterns";
214 static const char gDayNamesTag
[]="dayNames";
215 static const char gNamesWideTag
[]="wide";
216 static const char gNamesAbbrTag
[]="abbreviated";
217 static const char gNamesShortTag
[]="short";
218 static const char gNamesNarrowTag
[]="narrow";
219 static const char gNamesAllTag
[]="all";
220 static const char gNamesFormatTag
[]="format";
221 static const char gNamesStandaloneTag
[]="stand-alone";
222 static const char gNamesNumericTag
[]="numeric";
223 static const char gAmPmMarkersTag
[]="AmPmMarkers";
224 static const char gAmPmMarkersAbbrTag
[]="AmPmMarkersAbbr";
225 static const char gAmPmMarkersNarrowTag
[]="AmPmMarkersNarrow";
226 static const char gQuartersTag
[]="quarters";
227 static const char gNumberElementsTag
[]="NumberElements";
228 static const char gSymbolsTag
[]="symbols";
229 static const char gTimeSeparatorTag
[]="timeSeparator";
230 static const char gDayPeriodTag
[]="dayPeriod";
232 // static const char gZoneStringsTag[]="zoneStrings";
234 // static const char gLocalPatternCharsTag[]="localPatternChars";
236 static const char gContextTransformsTag
[]="contextTransforms";
239 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
242 static inline UnicodeString
* newUnicodeStringArray(size_t count
) {
243 return new UnicodeString
[count
? count
: 1];
246 //------------------------------------------------------
248 DateFormatSymbols
* U_EXPORT2
249 DateFormatSymbols::createForLocale(
250 const Locale
& locale
, UErrorCode
&status
) {
251 const SharedDateFormatSymbols
*shared
= NULL
;
252 UnifiedCache::getByLocale(locale
, shared
, status
);
253 if (U_FAILURE(status
)) {
256 DateFormatSymbols
*result
= new DateFormatSymbols(shared
->get());
258 if (result
== NULL
) {
259 status
= U_MEMORY_ALLOCATION_ERROR
;
265 DateFormatSymbols::DateFormatSymbols(const Locale
& locale
,
269 initializeData(locale
, NULL
, status
);
272 DateFormatSymbols::DateFormatSymbols(UErrorCode
& status
)
275 initializeData(Locale::getDefault(), NULL
, status
, TRUE
);
279 DateFormatSymbols::DateFormatSymbols(const Locale
& locale
,
284 initializeData(locale
, type
, status
);
287 DateFormatSymbols::DateFormatSymbols(const char *type
, UErrorCode
& status
)
290 initializeData(Locale::getDefault(), type
, status
, TRUE
);
293 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols
& other
)
300 DateFormatSymbols::assignArray(UnicodeString
*& dstArray
,
302 const UnicodeString
* srcArray
,
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
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()).
318 dstArray
= newUnicodeStringArray(srcCount
);
319 if(dstArray
!= NULL
) {
321 for(i
=0; i
<srcCount
; ++i
) {
322 dstArray
[i
].fastCopyFrom(srcArray
[i
]);
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.
333 DateFormatSymbols::createZoneStrings(const UnicodeString
*const * otherStrings
)
336 UBool failed
= FALSE
;
338 fZoneStrings
= (UnicodeString
**)uprv_malloc(fZoneStringsRowCount
* sizeof(UnicodeString
*));
339 if (fZoneStrings
!= NULL
) {
340 for (row
=0; row
<fZoneStringsRowCount
; ++row
)
342 fZoneStrings
[row
] = newUnicodeStringArray(fZoneStringsColCount
);
343 if (fZoneStrings
[row
] == NULL
) {
347 for (col
=0; col
<fZoneStringsColCount
; ++col
) {
348 // fastCopyFrom() - see assignArray comments
349 fZoneStrings
[row
][col
].fastCopyFrom(otherStrings
[row
][col
]);
353 // If memory allocation failed, roll back and delete fZoneStrings
355 for (int i
= row
; i
>= 0; i
--) {
356 delete[] fZoneStrings
[i
];
358 uprv_free(fZoneStrings
);
364 * Copy all of the other's data to this.
367 DateFormatSymbols::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
);
412 fLeapMonthPatterns
= NULL
;
413 fLeapMonthPatternsCount
= 0;
415 if (other
.fShortYearNames
!= NULL
) {
416 assignArray(fShortYearNames
, fShortYearNamesCount
, other
.fShortYearNames
, other
.fShortYearNamesCount
);
418 fShortYearNames
= NULL
;
419 fShortYearNamesCount
= 0;
421 if (other
.fShortZodiacNames
!= NULL
) {
422 assignArray(fShortZodiacNames
, fShortZodiacNamesCount
, other
.fShortZodiacNames
, other
.fShortZodiacNamesCount
);
424 fShortZodiacNames
= NULL
;
425 fShortZodiacNamesCount
= 0;
428 if (other
.fZoneStrings
!= NULL
) {
429 fZoneStringsColCount
= other
.fZoneStringsColCount
;
430 fZoneStringsRowCount
= other
.fZoneStringsRowCount
;
431 createZoneStrings((const UnicodeString
**)other
.fZoneStrings
);
435 fZoneStringsColCount
= 0;
436 fZoneStringsRowCount
= 0;
438 fZSFLocale
= other
.fZSFLocale
;
439 // Other zone strings data is created on demand
440 fLocaleZoneStrings
= NULL
;
442 // fastCopyFrom() - see assignArray comments
443 fLocalPatternChars
.fastCopyFrom(other
.fLocalPatternChars
);
445 uprv_memcpy(fCapitalization
, other
.fCapitalization
, sizeof(fCapitalization
));
449 * Assignment operator.
451 DateFormatSymbols
& DateFormatSymbols::operator=(const DateFormatSymbols
& other
)
459 DateFormatSymbols::~DateFormatSymbols()
464 void DateFormatSymbols::dispose()
468 delete[] fNarrowEras
;
470 delete[] fShortMonths
;
471 delete[] fNarrowMonths
;
472 delete[] fStandaloneMonths
;
473 delete[] fStandaloneShortMonths
;
474 delete[] fStandaloneNarrowMonths
;
476 delete[] fShortWeekdays
;
477 delete[] fShorterWeekdays
;
478 delete[] fNarrowWeekdays
;
479 delete[] fStandaloneWeekdays
;
480 delete[] fStandaloneShortWeekdays
;
481 delete[] fStandaloneShorterWeekdays
;
482 delete[] fStandaloneNarrowWeekdays
;
484 delete[] fNarrowAmPms
;
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
;
499 disposeZoneStrings();
502 void DateFormatSymbols::disposeZoneStrings()
505 for (int32_t row
= 0; row
< fZoneStringsRowCount
; ++row
) {
506 delete[] fZoneStrings
[row
];
508 uprv_free(fZoneStrings
);
510 if (fLocaleZoneStrings
) {
511 for (int32_t row
= 0; row
< fZoneStringsRowCount
; ++row
) {
512 delete[] fLocaleZoneStrings
[row
];
514 uprv_free(fLocaleZoneStrings
);
518 fLocaleZoneStrings
= NULL
;
519 fZoneStringsRowCount
= 0;
520 fZoneStringsColCount
= 0;
524 DateFormatSymbols::arrayCompare(const UnicodeString
* array1
,
525 const UnicodeString
* array2
,
528 if (array1
== array2
) return TRUE
;
532 if (array1
[count
] != array2
[count
]) return FALSE
;
538 DateFormatSymbols::operator==(const DateFormatSymbols
& other
) const
540 // First do cheap comparisons
541 if (this == &other
) {
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))
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
))
616 // Compare the contents of fZoneStrings
617 if (fZoneStrings
== NULL
&& other
.fZoneStrings
== NULL
) {
618 if (fZSFLocale
== other
.fZSFLocale
) {
621 } else if (fZoneStrings
!= NULL
&& other
.fZoneStrings
!= NULL
) {
622 if (fZoneStringsRowCount
== other
.fZoneStringsRowCount
623 && fZoneStringsColCount
== other
.fZoneStringsColCount
) {
625 for (int32_t i
= 0; (i
< fZoneStringsRowCount
) && cmpres
; i
++) {
626 cmpres
= arrayCompare(fZoneStrings
[i
], other
.fZoneStrings
[i
], fZoneStringsColCount
);
637 //------------------------------------------------------
640 DateFormatSymbols::getEras(int32_t &count
) const
647 DateFormatSymbols::getEraNames(int32_t &count
) const
649 count
= fEraNamesCount
;
654 DateFormatSymbols::getNarrowEras(int32_t &count
) const
656 count
= fNarrowErasCount
;
661 DateFormatSymbols::getMonths(int32_t &count
) const
663 count
= fMonthsCount
;
668 DateFormatSymbols::getShortMonths(int32_t &count
) const
670 count
= fShortMonthsCount
;
675 DateFormatSymbols::getMonths(int32_t &count
, DtContextType context
, DtWidthType width
) const
677 UnicodeString
*returnValue
= NULL
;
683 count
= fMonthsCount
;
684 returnValue
= fMonths
;
687 case SHORT
: // no month data for this, defaults to ABBREVIATED
688 count
= fShortMonthsCount
;
689 returnValue
= fShortMonths
;
692 count
= fNarrowMonthsCount
;
693 returnValue
= fNarrowMonths
;
695 case DT_WIDTH_COUNT
:
702 count
= fStandaloneMonthsCount
;
703 returnValue
= fStandaloneMonths
;
706 case SHORT
: // no month data for this, defaults to ABBREVIATED
707 count
= fStandaloneShortMonthsCount
;
708 returnValue
= fStandaloneShortMonths
;
711 count
= fStandaloneNarrowMonthsCount
;
712 returnValue
= fStandaloneNarrowMonths
;
714 case DT_WIDTH_COUNT
:
718 case DT_CONTEXT_COUNT
:
725 DateFormatSymbols::getWeekdays(int32_t &count
) const
727 count
= fWeekdaysCount
;
732 DateFormatSymbols::getShortWeekdays(int32_t &count
) const
734 count
= fShortWeekdaysCount
;
735 return fShortWeekdays
;
739 DateFormatSymbols::getWeekdays(int32_t &count
, DtContextType context
, DtWidthType width
) const
741 UnicodeString
*returnValue
= NULL
;
746 count
= fWeekdaysCount
;
747 returnValue
= fWeekdays
;
750 count
= fShortWeekdaysCount
;
751 returnValue
= fShortWeekdays
;
754 count
= fShorterWeekdaysCount
;
755 returnValue
= fShorterWeekdays
;
758 count
= fNarrowWeekdaysCount
;
759 returnValue
= fNarrowWeekdays
;
761 case DT_WIDTH_COUNT
:
768 count
= fStandaloneWeekdaysCount
;
769 returnValue
= fStandaloneWeekdays
;
772 count
= fStandaloneShortWeekdaysCount
;
773 returnValue
= fStandaloneShortWeekdays
;
776 count
= fStandaloneShorterWeekdaysCount
;
777 returnValue
= fStandaloneShorterWeekdays
;
780 count
= fStandaloneNarrowWeekdaysCount
;
781 returnValue
= fStandaloneNarrowWeekdays
;
783 case DT_WIDTH_COUNT
:
787 case DT_CONTEXT_COUNT
:
794 DateFormatSymbols::getQuarters(int32_t &count
, DtContextType context
, DtWidthType width
) const
796 UnicodeString
*returnValue
= NULL
;
802 count
= fQuartersCount
;
803 returnValue
= fQuarters
;
806 case SHORT
: // no quarter data for this, defaults to ABBREVIATED
807 count
= fShortQuartersCount
;
808 returnValue
= fShortQuarters
;
814 case DT_WIDTH_COUNT
:
821 count
= fStandaloneQuartersCount
;
822 returnValue
= fStandaloneQuarters
;
825 case SHORT
: // no quarter data for this, defaults to ABBREVIATED
826 count
= fStandaloneShortQuartersCount
;
827 returnValue
= fStandaloneShortQuarters
;
833 case DT_WIDTH_COUNT
:
837 case DT_CONTEXT_COUNT
:
844 DateFormatSymbols::getTimeSeparatorString(UnicodeString
& result
) const
846 // fastCopyFrom() - see assignArray comments
847 return result
.fastCopyFrom(fTimeSeparator
);
851 DateFormatSymbols::getAmPmStrings(int32_t &count
) const
858 DateFormatSymbols::getLeapMonthPatterns(int32_t &count
) const
860 count
= fLeapMonthPatternsCount
;
861 return fLeapMonthPatterns
;
865 DateFormatSymbols::getYearNames(int32_t& count
,
866 DtContextType
/*ignored*/, DtWidthType
/*ignored*/) const
868 count
= fShortYearNamesCount
;
869 return fShortYearNames
;
873 DateFormatSymbols::setYearNames(const UnicodeString
* yearNames
, int32_t count
,
874 DtContextType context
, DtWidthType width
)
876 if (context
== FORMAT
&& width
== ABBREVIATED
) {
877 if (fShortYearNames
) {
878 delete[] fShortYearNames
;
880 fShortYearNames
= newUnicodeStringArray(count
);
881 uprv_arrayCopy(yearNames
, fShortYearNames
, count
);
882 fShortYearNamesCount
= count
;
887 DateFormatSymbols::getZodiacNames(int32_t& count
,
888 DtContextType
/*ignored*/, DtWidthType
/*ignored*/) const
890 count
= fShortZodiacNamesCount
;
891 return fShortZodiacNames
;
895 DateFormatSymbols::setZodiacNames(const UnicodeString
* zodiacNames
, int32_t count
,
896 DtContextType context
, DtWidthType width
)
898 if (context
== FORMAT
&& width
== ABBREVIATED
) {
899 if (fShortZodiacNames
) {
900 delete[] fShortZodiacNames
;
902 fShortZodiacNames
= newUnicodeStringArray(count
);
903 uprv_arrayCopy(zodiacNames
, fShortZodiacNames
, count
);
904 fShortZodiacNamesCount
= count
;
908 //------------------------------------------------------
911 DateFormatSymbols::setEras(const UnicodeString
* erasArray
, int32_t count
)
913 // delete the old list if we own it
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
);
925 DateFormatSymbols::setEraNames(const UnicodeString
* eraNamesArray
, int32_t count
)
927 // delete the old list if we own it
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
;
939 DateFormatSymbols::setNarrowEras(const UnicodeString
* narrowErasArray
, int32_t count
)
941 // delete the old list if we own it
943 delete[] fNarrowEras
;
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
;
953 DateFormatSymbols::setMonths(const UnicodeString
* monthsArray
, int32_t count
)
955 // delete the old list if we own it
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
;
967 DateFormatSymbols::setShortMonths(const UnicodeString
* shortMonthsArray
, int32_t count
)
969 // delete the old list if we own it
971 delete[] fShortMonths
;
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
;
981 DateFormatSymbols::setMonths(const UnicodeString
* monthsArray
, int32_t count
, DtContextType context
, DtWidthType width
)
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)
993 fMonths
= newUnicodeStringArray(count
);
994 uprv_arrayCopy( monthsArray
,fMonths
,count
);
995 fMonthsCount
= count
;
999 delete[] fShortMonths
;
1000 fShortMonths
= newUnicodeStringArray(count
);
1001 uprv_arrayCopy( monthsArray
,fShortMonths
,count
);
1002 fShortMonthsCount
= count
;
1006 delete[] fNarrowMonths
;
1007 fNarrowMonths
= newUnicodeStringArray(count
);
1008 uprv_arrayCopy( monthsArray
,fNarrowMonths
,count
);
1009 fNarrowMonthsCount
= count
;
1018 if (fStandaloneMonths
)
1019 delete[] fStandaloneMonths
;
1020 fStandaloneMonths
= newUnicodeStringArray(count
);
1021 uprv_arrayCopy( monthsArray
,fStandaloneMonths
,count
);
1022 fStandaloneMonthsCount
= count
;
1025 if (fStandaloneShortMonths
)
1026 delete[] fStandaloneShortMonths
;
1027 fStandaloneShortMonths
= newUnicodeStringArray(count
);
1028 uprv_arrayCopy( monthsArray
,fStandaloneShortMonths
,count
);
1029 fStandaloneShortMonthsCount
= count
;
1032 if (fStandaloneNarrowMonths
)
1033 delete[] fStandaloneNarrowMonths
;
1034 fStandaloneNarrowMonths
= newUnicodeStringArray(count
);
1035 uprv_arrayCopy( monthsArray
,fStandaloneNarrowMonths
,count
);
1036 fStandaloneNarrowMonthsCount
= count
;
1042 case DT_CONTEXT_COUNT
:
1047 void DateFormatSymbols::setWeekdays(const UnicodeString
* weekdaysArray
, int32_t count
)
1049 // delete the old list if we own it
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
;
1061 DateFormatSymbols::setShortWeekdays(const UnicodeString
* shortWeekdaysArray
, int32_t count
)
1063 // delete the old list if we own it
1065 delete[] fShortWeekdays
;
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
;
1075 DateFormatSymbols::setWeekdays(const UnicodeString
* weekdaysArray
, int32_t count
, DtContextType context
, DtWidthType width
)
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)
1087 fWeekdays
= newUnicodeStringArray(count
);
1088 uprv_arrayCopy(weekdaysArray
, fWeekdays
, count
);
1089 fWeekdaysCount
= count
;
1093 delete[] fShortWeekdays
;
1094 fShortWeekdays
= newUnicodeStringArray(count
);
1095 uprv_arrayCopy(weekdaysArray
, fShortWeekdays
, count
);
1096 fShortWeekdaysCount
= count
;
1099 if (fShorterWeekdays
)
1100 delete[] fShorterWeekdays
;
1101 fShorterWeekdays
= newUnicodeStringArray(count
);
1102 uprv_arrayCopy(weekdaysArray
, fShorterWeekdays
, count
);
1103 fShorterWeekdaysCount
= count
;
1106 if (fNarrowWeekdays
)
1107 delete[] fNarrowWeekdays
;
1108 fNarrowWeekdays
= newUnicodeStringArray(count
);
1109 uprv_arrayCopy(weekdaysArray
, fNarrowWeekdays
, count
);
1110 fNarrowWeekdaysCount
= count
;
1112 case DT_WIDTH_COUNT
:
1119 if (fStandaloneWeekdays
)
1120 delete[] fStandaloneWeekdays
;
1121 fStandaloneWeekdays
= newUnicodeStringArray(count
);
1122 uprv_arrayCopy(weekdaysArray
, fStandaloneWeekdays
, count
);
1123 fStandaloneWeekdaysCount
= count
;
1126 if (fStandaloneShortWeekdays
)
1127 delete[] fStandaloneShortWeekdays
;
1128 fStandaloneShortWeekdays
= newUnicodeStringArray(count
);
1129 uprv_arrayCopy(weekdaysArray
, fStandaloneShortWeekdays
, count
);
1130 fStandaloneShortWeekdaysCount
= count
;
1133 if (fStandaloneShorterWeekdays
)
1134 delete[] fStandaloneShorterWeekdays
;
1135 fStandaloneShorterWeekdays
= newUnicodeStringArray(count
);
1136 uprv_arrayCopy(weekdaysArray
, fStandaloneShorterWeekdays
, count
);
1137 fStandaloneShorterWeekdaysCount
= count
;
1140 if (fStandaloneNarrowWeekdays
)
1141 delete[] fStandaloneNarrowWeekdays
;
1142 fStandaloneNarrowWeekdays
= newUnicodeStringArray(count
);
1143 uprv_arrayCopy(weekdaysArray
, fStandaloneNarrowWeekdays
, count
);
1144 fStandaloneNarrowWeekdaysCount
= count
;
1146 case DT_WIDTH_COUNT
:
1150 case DT_CONTEXT_COUNT
:
1156 DateFormatSymbols::setQuarters(const UnicodeString
* quartersArray
, int32_t count
, DtContextType context
, DtWidthType width
)
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)
1168 fQuarters
= newUnicodeStringArray(count
);
1169 uprv_arrayCopy( quartersArray
,fQuarters
,count
);
1170 fQuartersCount
= count
;
1174 delete[] fShortQuarters
;
1175 fShortQuarters
= newUnicodeStringArray(count
);
1176 uprv_arrayCopy( quartersArray
,fShortQuarters
,count
);
1177 fShortQuartersCount
= count
;
1181 if (fNarrowQuarters)
1182 delete[] fNarrowQuarters;
1183 fNarrowQuarters = newUnicodeStringArray(count);
1184 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1185 fNarrowQuartersCount = count;
1195 if (fStandaloneQuarters
)
1196 delete[] fStandaloneQuarters
;
1197 fStandaloneQuarters
= newUnicodeStringArray(count
);
1198 uprv_arrayCopy( quartersArray
,fStandaloneQuarters
,count
);
1199 fStandaloneQuartersCount
= count
;
1202 if (fStandaloneShortQuarters
)
1203 delete[] fStandaloneShortQuarters
;
1204 fStandaloneShortQuarters
= newUnicodeStringArray(count
);
1205 uprv_arrayCopy( quartersArray
,fStandaloneShortQuarters
,count
);
1206 fStandaloneShortQuartersCount
= count
;
1210 if (fStandaloneNarrowQuarters)
1211 delete[] fStandaloneNarrowQuarters;
1212 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1213 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1214 fStandaloneNarrowQuartersCount = count;
1221 case DT_CONTEXT_COUNT
:
1227 DateFormatSymbols::setAmPmStrings(const UnicodeString
* amPmsArray
, int32_t count
)
1229 // delete the old list if we own it
1230 if (fAmPms
) delete[] fAmPms
;
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
;
1240 DateFormatSymbols::setTimeSeparatorString(const UnicodeString
& newTimeSeparator
)
1242 fTimeSeparator
= newTimeSeparator
;
1245 const UnicodeString
**
1246 DateFormatSymbols::getZoneStrings(int32_t& rowCount
, int32_t& columnCount
) const
1248 const UnicodeString
**result
= NULL
;
1249 static UMutex
*LOCK
= STATIC_NEW(UMutex
);
1252 if (fZoneStrings
== NULL
) {
1253 if (fLocaleZoneStrings
== NULL
) {
1254 ((DateFormatSymbols
*)this)->initZoneStringsArray();
1256 result
= (const UnicodeString
**)fLocaleZoneStrings
;
1258 result
= (const UnicodeString
**)fZoneStrings
;
1260 rowCount
= fZoneStringsRowCount
;
1261 columnCount
= fZoneStringsColCount
;
1267 // For now, we include all zones
1268 #define ZONE_SET UCAL_ZONE_TYPE_ANY
1270 // This code must be called within a synchronized block
1272 DateFormatSymbols::initZoneStringsArray(void) {
1273 if (fZoneStrings
!= NULL
|| fLocaleZoneStrings
!= NULL
) {
1277 UErrorCode status
= U_ZERO_ERROR
;
1279 StringEnumeration
*tzids
= NULL
;
1280 UnicodeString
** zarray
= NULL
;
1281 TimeZoneNames
*tzNames
= NULL
;
1284 static const UTimeZoneNameType TYPES
[] = {
1285 UTZNM_LONG_STANDARD
, UTZNM_SHORT_STANDARD
,
1286 UTZNM_LONG_DAYLIGHT
, UTZNM_SHORT_DAYLIGHT
1288 static const int32_t NUM_TYPES
= 4;
1290 do { // dummy do-while
1292 tzids
= TimeZone::createTimeZoneIDEnumeration(ZONE_SET
, NULL
, NULL
, status
);
1293 rows
= tzids
->count(status
);
1294 if (U_FAILURE(status
)) {
1299 int32_t size
= rows
* sizeof(UnicodeString
*);
1300 zarray
= (UnicodeString
**)uprv_malloc(size
);
1301 if (zarray
== NULL
) {
1302 status
= U_MEMORY_ALLOCATION_ERROR
;
1305 uprv_memset(zarray
, 0, size
);
1307 tzNames
= TimeZoneNames::createInstance(fZSFLocale
, status
);
1308 tzNames
->loadAllDisplayNames(status
);
1309 if (U_FAILURE(status
)) { break; }
1311 const UnicodeString
*tzid
;
1313 UDate now
= Calendar::getNow();
1314 UnicodeString tzDispName
;
1316 while ((tzid
= tzids
->snext(status
)) != 0) {
1317 if (U_FAILURE(status
)) {
1321 zarray
[i
] = new UnicodeString
[5];
1322 if (zarray
[i
] == NULL
) {
1323 status
= U_MEMORY_ALLOCATION_ERROR
;
1327 zarray
[i
][0].setTo(*tzid
);
1328 tzNames
->getDisplayNames(*tzid
, TYPES
, NUM_TYPES
, now
, zarray
[i
]+1, status
);
1334 if (U_FAILURE(status
)) {
1336 for (int32_t i
= 0; i
< rows
; i
++) {
1353 fLocaleZoneStrings
= zarray
;
1354 fZoneStringsRowCount
= rows
;
1355 fZoneStringsColCount
= 1 + NUM_TYPES
;
1359 DateFormatSymbols::setZoneStrings(const UnicodeString
* const *strings
, int32_t rowCount
, int32_t columnCount
)
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
);
1371 //------------------------------------------------------
1373 const char16_t * U_EXPORT2
1374 DateFormatSymbols::getPatternUChars(void)
1376 return gPatternChars
;
1379 UDateFormatField U_EXPORT2
1380 DateFormatSymbols::getPatternCharIndex(UChar c
) {
1381 const UChar
*p
= u_strchr(gPatternChars
, c
);
1383 return UDAT_FIELD_COUNT
;
1385 return static_cast<UDateFormatField
>(p
- gPatternChars
);
1389 static 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
1409 static 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
1418 DateFormatSymbols::isNumericField(UDateFormatField f
, int32_t count
) {
1419 if (f
== UDAT_FIELD_COUNT
) {
1422 uint64_t flag
= ((uint64_t)1 << f
);
1423 return ((kNumericFieldsAlways
& flag
) != 0 || ((kNumericFieldsForCount12
& flag
) != 0 && count
< 3));
1427 DateFormatSymbols::isNumericPatternChar(UChar c
, int32_t count
) {
1428 return isNumericField(getPatternCharIndex(c
), count
);
1431 //------------------------------------------------------
1434 DateFormatSymbols::getLocalPatternChars(UnicodeString
& result
) const
1436 // fastCopyFrom() - see assignArray comments
1437 return result
.fastCopyFrom(fLocalPatternChars
);
1440 //------------------------------------------------------
1443 DateFormatSymbols::setLocalPatternChars(const UnicodeString
& newLocalPatternChars
)
1445 fLocalPatternChars
= newLocalPatternChars
;
1448 //------------------------------------------------------
1452 // Constants declarations
1453 static 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
1457 static const UChar kGregorianTagUChar
[] = {
1458 LOW_G
, LOW_R
, LOW_E
, LOW_G
, LOW_O
, LOW_R
, LOW_I
, LOW_A
, LOW_N
1460 static const UChar kVariantTagUChar
[] = {
1461 PERCENT
, LOW_V
, LOW_A
, LOW_R
, LOW_I
, LOW_A
, LOW_N
, LOW_T
1463 static const UChar kLeapTagUChar
[] = {
1464 LOW_L
, LOW_E
, LOW_A
, LOW_P
1466 static 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
1469 static const UChar kYearsTagUChar
[] = {
1470 SOLIDUS
, LOW_Y
, LOW_E
, LOW_A
, LOW_R
, LOW_S
1472 static const UChar kZodiacsUChar
[] = {
1473 SOLIDUS
, LOW_Z
, LOW_O
, LOW_D
, LOW_I
, LOW_A
, LOW_C
, LOW_S
1475 static const UChar kDayPartsTagUChar
[] = {
1476 SOLIDUS
, LOW_D
, LOW_A
, LOW_Y
, CAP_P
, LOW_A
, LOW_R
, LOW_T
, LOW_S
1478 static const UChar kFormatTagUChar
[] = {
1479 SOLIDUS
, LOW_F
, LOW_O
, LOW_R
, LOW_M
, LOW_A
, LOW_T
1481 static 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
1485 // ResourceSink to enumerate all calendar resources
1486 struct CalendarDataSink
: public ResourceSink
{
1488 // Enum which specifies the type of alias received, or no alias
1496 // Data structures to store resources from the current resource bundle
1498 Hashtable arraySizes
;
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.
1505 MemoryPool
<Hashtable
> mapRefs
;
1507 // Paths and the aliases they point to
1508 UVector aliasPathPairs
;
1510 // Current and next calendar resource table which should be loaded
1511 UnicodeString currentCalendarType
;
1512 UnicodeString nextCalendarType
;
1514 // Resources to visit when enumerating fallback calendars
1515 LocalPointer
<UVector
> resourcesToVisit
;
1517 // Alias' relative path populated whenever an alias is read
1518 UnicodeString aliasRelativePath
;
1520 // Initializes CalendarDataSink with default values
1521 CalendarDataSink(UErrorCode
& status
)
1522 : arrays(FALSE
, status
), arraySizes(FALSE
, status
), maps(FALSE
, status
),
1524 aliasPathPairs(uprv_deleteUObject
, uhash_compareUnicodeString
, status
),
1525 currentCalendarType(), nextCalendarType(),
1526 resourcesToVisit(NULL
), aliasRelativePath() {
1527 if (U_FAILURE(status
)) { return; }
1529 virtual ~CalendarDataSink();
1531 // Configure the CalendarSink to visit all the resources
1532 void visitAllResources() {
1533 resourcesToVisit
.adoptInstead(NULL
);
1536 // Actions to be done before enumerating
1537 void preEnumerate(const UnicodeString
&calendarType
) {
1538 currentCalendarType
= calendarType
;
1539 nextCalendarType
.setToBogus();
1540 aliasPathPairs
.removeAllElements();
1543 virtual void put(const char *key
, ResourceValue
&value
, UBool
, UErrorCode
&errorCode
) {
1544 if (U_FAILURE(errorCode
)) { return; }
1545 U_ASSERT(!currentCalendarType
.isEmpty());
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; }
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
);
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.
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
),
1570 if (U_FAILURE(errorCode
)) { return; }
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();
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();
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; }
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; }
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
);
1625 // Apply same-calendar aliases
1629 for (int32_t i
= 0; i
< aliasPathPairs
.size();) {
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
) {
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
);
1646 if (U_FAILURE(errorCode
)) { return; }
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
);
1653 if (U_FAILURE(errorCode
)) { return; }
1657 aliasPathPairs
.removeElementAt(i
+ 1);
1658 aliasPathPairs
.removeElementAt(i
);
1664 } while (modified
&& !aliasPathPairs
.isEmpty());
1666 // Set the resources to visit on the next calendar
1667 if (!resourcesToVisitNext
.isNull()) {
1668 resourcesToVisit
= std::move(resourcesToVisitNext
);
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;
1676 ResourceTable table
= value
.getTable(errorCode
);
1677 if (U_FAILURE(errorCode
)) return;
1678 Hashtable
* stringMap
= NULL
;
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
);
1684 // Ignore '%variant' keys
1685 if (keyUString
.endsWith(kVariantTagUChar
, UPRV_LENGTHOF(kVariantTagUChar
))) {
1689 // == Handle String elements ==
1690 if (value
.getType() == URES_STRING
) {
1691 // We are on a leaf, store the map elements into the stringMap
1693 // mapRefs will keep ownership of 'stringMap':
1694 stringMap
= mapRefs
.create(FALSE
, errorCode
);
1695 if (stringMap
== NULL
) {
1696 errorCode
= U_MEMORY_ALLOCATION_ERROR
;
1699 maps
.put(path
, stringMap
, errorCode
);
1700 if (U_FAILURE(errorCode
)) { return; }
1701 stringMap
->setValueDeleter(uprv_deleteUObject
);
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; }
1712 U_ASSERT(stringMap
== NULL
);
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
);
1718 // In cyclicNameSets ignore everything but years/format/abbreviated
1719 // and zodiacs/format/abbreviated
1720 if (path
.startsWith(kCyclicNameSetsTagUChar
, UPRV_LENGTHOF(kCyclicNameSetsTagUChar
))) {
1722 int32_t startIndex
= UPRV_LENGTHOF(kCyclicNameSetsTagUChar
);
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
;
1730 if (startIndex
== path
.length()
1731 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kFormatTagUChar
)), kFormatTagUChar
, 0, UPRV_LENGTHOF(kFormatTagUChar
)) == 0) {
1732 startIndex
+= length
;
1734 if (startIndex
== path
.length()
1735 || path
.compare(startIndex
, (length
= UPRV_LENGTHOF(kAbbrTagUChar
)), kAbbrTagUChar
, 0, UPRV_LENGTHOF(kAbbrTagUChar
)) == 0) {
1741 // Drop the latest key on the path and continue
1742 path
.retainBetween(0, pathLength
);
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
);
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):
1769 // Drop the latest key on the path and continue
1770 path
.retainBetween(0, pathLength
);
1773 U_ASSERT(aliasType
== NONE
);
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; }
1791 // Drop the latest key on the path
1792 path
.retainBetween(0, pathLength
);
1796 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
1797 AliasType
processAliasFromValue(UnicodeString
¤tRelativePath
, ResourceValue
&value
,
1798 UErrorCode
&errorCode
) {
1799 if (U_FAILURE(errorCode
)) { return NONE
; }
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());
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
;
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) {
1825 } else if (nextCalendarType
.isBogus()) {
1826 nextCalendarType
= aliasCalendarType
;
1827 return DIFFERENT_CALENDAR
;
1828 } else if (nextCalendarType
== aliasCalendarType
) {
1829 return DIFFERENT_CALENDAR
;
1834 errorCode
= U_INTERNAL_PROGRAM_ERROR
;
1840 // Deleter function to be used by 'arrays'
1841 static void U_CALLCONV
deleteUnicodeStringArray(void *uArray
) {
1842 delete[] static_cast<UnicodeString
*>(uArray
);
1845 // Virtual destructors have to be defined out of line
1846 CalendarDataSink::~CalendarDataSink() {
1847 arrays
.setValueDeleter(deleteUnicodeStringArray
);
1851 //------------------------------------------------------
1854 initField(UnicodeString
**field
, int32_t& length
, const UChar
*data
, LastResortSize numStr
, LastResortSize strLen
, UErrorCode
&status
) {
1855 if (U_SUCCESS(status
)) {
1857 *field
= newUnicodeStringArray((size_t)numStr
);
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);
1867 status
= U_MEMORY_ALLOCATION_ERROR
;
1873 initField(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
));
1878 if (array
!= NULL
) {
1879 length
= sink
.arraySizes
.geti(keyUString
);
1881 // DateFormatSymbols takes ownership of the array:
1882 sink
.arrays
.remove(keyUString
);
1885 status
= U_MISSING_RESOURCE_ERROR
;
1891 initField(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
));
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
;
1904 uprv_arrayCopy(array
, 0, *field
, arrayOffset
, arrayLength
);
1907 status
= U_MISSING_RESOURCE_ERROR
;
1913 initLeapMonthPattern(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
);
1924 field
[index
].setToBogus();
1928 status
= U_MISSING_RESOURCE_ERROR
;
1933 &buildResourcePath(CharString
&path
, const char* segment1
, UErrorCode
&errorCode
) {
1934 return path
.clear().append(segment1
, -1, errorCode
);
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
);
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
);
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
);
1959 const char * usageTypeName
;
1960 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue
;
1961 } ContextUsageTypeNameToEnumValue
;
1963 static 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 },
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.
1984 static const char *dayPeriodKeys
[] = {"midnight", "noon",
1985 "morning1", "afternoon1", "evening1", "night1",
1986 "morning2", "afternoon2", "evening2", "night2"};
1988 UnicodeString
* loadDayPeriodStrings(CalendarDataSink
&sink
, CharString
&path
,
1989 int32_t &stringCount
, UErrorCode
&status
) {
1990 if (U_FAILURE(status
)) { return NULL
; }
1992 UnicodeString
pathUString(path
.data(), -1, US_INV
);
1993 Hashtable
* map
= static_cast<Hashtable
*>(sink
.maps
.get(pathUString
));
1995 stringCount
= UPRV_LENGTHOF(dayPeriodKeys
);
1996 UnicodeString
*strings
= new UnicodeString
[stringCount
];
1997 if (strings
== NULL
) {
1998 status
= U_MEMORY_ALLOCATION_ERROR
;
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
);
2009 strings
[i
].setToBogus();
2013 for (int32_t i
= 0; i
< stringCount
; i
++) {
2014 strings
[i
].setToBogus();
2022 DateFormatSymbols::initializeData(const Locale
& locale
, const char *type
, UErrorCode
& status
, UBool useLastResortData
)
2025 /* In case something goes wrong, initialize all of the data to NULL. */
2031 fNarrowErasCount
= 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;
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;
2062 fNarrowAmPms
= NULL
;
2063 fNarrowAmPmsCount
=0;
2064 fTimeSeparator
.setToBogus();
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
));
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
;
2103 if (U_FAILURE(status
)) return;
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
);
2110 if (U_FAILURE(status
)) return;
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();
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
) {
2125 if (uprv_strcmp(calendarTypeCArray
, gGregorianTag
) != 0) {
2126 calendarType
.setTo(FALSE
, kGregorianTagUChar
, UPRV_LENGTHOF(kGregorianTagUChar
));
2127 calendarSink
.visitAllResources();
2134 calendarSink
.preEnumerate(calendarType
);
2135 ures_getAllItemsWithFallback(ctb
, "", calendarSink
, status
);
2137 if (U_FAILURE(status
)) break;
2139 // Stop loading when gregorian was loaded
2140 if (uprv_strcmp(calendarTypeCArray
, gGregorianTag
) == 0) {
2144 // Get the next calendar type to process from the sink
2145 calendarType
= calendarSink
.nextCalendarType
;
2147 // Gregorian is always the last fallback
2148 if (calendarType
.isBogus()) {
2149 calendarType
.setTo(FALSE
, kGregorianTagUChar
, UPRV_LENGTHOF(kGregorianTagUChar
));
2150 calendarSink
.visitAllResources();
2154 // CharString object to build paths
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
]);
2181 if (fLeapMonthPatterns
[kLeapMonthPatternFormatNarrow
].isEmpty()) {
2182 fLeapMonthPatterns
[kLeapMonthPatternFormatNarrow
].setTo(fLeapMonthPatterns
[kLeapMonthPatternStandaloneNarrow
]);
2184 if (fLeapMonthPatterns
[kLeapMonthPatternStandaloneWide
].isEmpty()) {
2185 fLeapMonthPatterns
[kLeapMonthPatternStandaloneWide
].setTo(fLeapMonthPatterns
[kLeapMonthPatternFormatWide
]);
2187 if (fLeapMonthPatterns
[kLeapMonthPatternStandaloneAbbrev
].isEmpty()) {
2188 fLeapMonthPatterns
[kLeapMonthPatternStandaloneAbbrev
].setTo(fLeapMonthPatterns
[kLeapMonthPatternFormatAbbrev
]);
2191 fLeapMonthPatternsCount
= kMonthPatternsCount
;
2193 delete[] fLeapMonthPatterns
;
2194 fLeapMonthPatterns
= NULL
;
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
);
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 ) {
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]);
2229 tempStatus
= U_ZERO_ERROR
;
2230 ures_close(contextTransformUsage
);
2232 ures_close(contextTransforms
);
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();
2255 ures_close(localeBundle
);
2258 if (fTimeSeparator
.isBogus()) {
2259 fTimeSeparator
.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR
);
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
);
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
));
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
2295 assignArray(fEraNames
, fEraNamesCount
, fEras
, fErasCount
);
2297 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
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
2302 assignArray(fNarrowEras
, fNarrowErasCount
, fEras
, fErasCount
);
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
);
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
);
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
);
2341 // Load AM/PM markers
2342 initField(&fAmPms
, fAmPmsCount
, calendarSink
,
2343 buildResourcePath(path
, gAmPmMarkersTag
, status
), status
);
2344 initField(&fNarrowAmPms
, fNarrowAmPmsCount
, calendarSink
,
2345 buildResourcePath(path
, gAmPmMarkersNarrowTag
, status
), status
);
2348 initField(&fQuarters
, fQuartersCount
, calendarSink
,
2349 buildResourcePath(path
, gQuartersTag
, gNamesFormatTag
, gNamesWideTag
, status
), status
);
2350 initField(&fShortQuarters
, fShortQuartersCount
, calendarSink
,
2351 buildResourcePath(path
, gQuartersTag
, gNamesFormatTag
, gNamesAbbrTag
, status
), status
);
2353 initField(&fStandaloneQuarters
, fStandaloneQuartersCount
, calendarSink
,
2354 buildResourcePath(path
, gQuartersTag
, gNamesStandaloneTag
, gNamesWideTag
, status
), status
);
2355 if(status
== U_MISSING_RESOURCE_ERROR
) {
2356 status
= U_ZERO_ERROR
;
2357 assignArray(fStandaloneQuarters
, fStandaloneQuartersCount
, fQuarters
, fQuartersCount
);
2359 initField(&fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, calendarSink
,
2360 buildResourcePath(path
, gQuartersTag
, gNamesStandaloneTag
, gNamesAbbrTag
, status
), status
);
2361 if(status
== U_MISSING_RESOURCE_ERROR
) {
2362 status
= U_ZERO_ERROR
;
2363 assignArray(fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, fShortQuarters
, fShortQuartersCount
);
2366 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2368 // fastCopyFrom()/setTo() - see assignArray comments
2369 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2370 fLocalPatternChars.setTo(TRUE, resStr, len);
2371 // If the locale data does not include new pattern chars, use the defaults
2372 // TODO: Consider making this an error, since this may add conflicting characters.
2373 if (len < PATTERN_CHARS_LEN) {
2374 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2377 fLocalPatternChars
.setTo(TRUE
, gPatternChars
, PATTERN_CHARS_LEN
);
2379 // Format wide weekdays -> fWeekdays
2380 // {sfb} fixed to handle 1-based weekdays
2381 initField(&fWeekdays
, fWeekdaysCount
, calendarSink
,
2382 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesWideTag
, status
), 1, status
);
2384 // Format abbreviated weekdays -> fShortWeekdays
2385 initField(&fShortWeekdays
, fShortWeekdaysCount
, calendarSink
,
2386 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesAbbrTag
, status
), 1, status
);
2388 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2389 initField(&fShorterWeekdays
, fShorterWeekdaysCount
, calendarSink
,
2390 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesShortTag
, status
), 1, status
);
2391 if (status
== U_MISSING_RESOURCE_ERROR
) {
2392 status
= U_ZERO_ERROR
;
2393 assignArray(fShorterWeekdays
, fShorterWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2396 // Stand-alone wide weekdays -> fStandaloneWeekdays
2397 initField(&fStandaloneWeekdays
, fStandaloneWeekdaysCount
, calendarSink
,
2398 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesWideTag
, status
), 1, status
);
2399 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/wide is not available, use format/wide */
2400 status
= U_ZERO_ERROR
;
2401 assignArray(fStandaloneWeekdays
, fStandaloneWeekdaysCount
, fWeekdays
, fWeekdaysCount
);
2404 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2405 initField(&fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, calendarSink
,
2406 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesAbbrTag
, status
), 1, status
);
2407 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/abbreviated is not available, use format/abbreviated */
2408 status
= U_ZERO_ERROR
;
2409 assignArray(fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2412 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2413 initField(&fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, calendarSink
,
2414 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesShortTag
, status
), 1, status
);
2415 if (status
== U_MISSING_RESOURCE_ERROR
) { /* If standalone/short is not available, use format/short */
2416 status
= U_ZERO_ERROR
;
2417 assignArray(fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, fShorterWeekdays
, fShorterWeekdaysCount
);
2420 // Format narrow weekdays -> fNarrowWeekdays
2421 UErrorCode narrowWeeksEC
= status
;
2422 initField(&fNarrowWeekdays
, fNarrowWeekdaysCount
, calendarSink
,
2423 buildResourcePath(path
, gDayNamesTag
, gNamesFormatTag
, gNamesNarrowTag
, status
), 1, narrowWeeksEC
);
2424 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2425 UErrorCode standaloneNarrowWeeksEC
= status
;
2426 initField(&fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, calendarSink
,
2427 buildResourcePath(path
, gDayNamesTag
, gNamesStandaloneTag
, gNamesNarrowTag
, status
), 1, standaloneNarrowWeeksEC
);
2429 if (narrowWeeksEC
== U_MISSING_RESOURCE_ERROR
&& standaloneNarrowWeeksEC
!= U_MISSING_RESOURCE_ERROR
) {
2430 // If format/narrow not available, use standalone/narrow
2431 assignArray(fNarrowWeekdays
, fNarrowWeekdaysCount
, fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
);
2432 } else if (narrowWeeksEC
!= U_MISSING_RESOURCE_ERROR
&& standaloneNarrowWeeksEC
== U_MISSING_RESOURCE_ERROR
) {
2433 // If standalone/narrow not available, use format/narrow
2434 assignArray(fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, fNarrowWeekdays
, fNarrowWeekdaysCount
);
2435 } else if (narrowWeeksEC
== U_MISSING_RESOURCE_ERROR
&& standaloneNarrowWeeksEC
== U_MISSING_RESOURCE_ERROR
) {
2436 // If neither is available, use format/abbreviated
2437 assignArray(fNarrowWeekdays
, fNarrowWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2438 assignArray(fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, fShortWeekdays
, fShortWeekdaysCount
);
2441 // Last resort fallback in case previous data wasn't loaded
2442 if (U_FAILURE(status
))
2444 if (useLastResortData
)
2446 // Handle the case in which there is no resource data present.
2447 // We don't have to generate usable patterns in this situation;
2448 // we just need to produce something that will be semi-intelligible
2451 status
= U_USING_FALLBACK_WARNING
;
2452 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2453 initField(&fEras
, fErasCount
, (const UChar
*)gLastResortEras
, kEraNum
, kEraLen
, status
);
2454 initField(&fEraNames
, fEraNamesCount
, (const UChar
*)gLastResortEras
, kEraNum
, kEraLen
, status
);
2455 initField(&fNarrowEras
, fNarrowErasCount
, (const UChar
*)gLastResortEras
, kEraNum
, kEraLen
, status
);
2456 initField(&fMonths
, fMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2457 initField(&fShortMonths
, fShortMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2458 initField(&fNarrowMonths
, fNarrowMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2459 initField(&fStandaloneMonths
, fStandaloneMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2460 initField(&fStandaloneShortMonths
, fStandaloneShortMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2461 initField(&fStandaloneNarrowMonths
, fStandaloneNarrowMonthsCount
, (const UChar
*)gLastResortMonthNames
, kMonthNum
, kMonthLen
, status
);
2462 initField(&fWeekdays
, fWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2463 initField(&fShortWeekdays
, fShortWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2464 initField(&fShorterWeekdays
, fShorterWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2465 initField(&fNarrowWeekdays
, fNarrowWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2466 initField(&fStandaloneWeekdays
, fStandaloneWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2467 initField(&fStandaloneShortWeekdays
, fStandaloneShortWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2468 initField(&fStandaloneShorterWeekdays
, fStandaloneShorterWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2469 initField(&fStandaloneNarrowWeekdays
, fStandaloneNarrowWeekdaysCount
, (const UChar
*)gLastResortDayNames
, kDayNum
, kDayLen
, status
);
2470 initField(&fAmPms
, fAmPmsCount
, (const UChar
*)gLastResortAmPmMarkers
, kAmPmNum
, kAmPmLen
, status
);
2471 initField(&fNarrowAmPms
, fNarrowAmPmsCount
, (const UChar
*)gLastResortAmPmMarkers
, kAmPmNum
, kAmPmLen
, status
);
2472 initField(&fQuarters
, fQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2473 initField(&fShortQuarters
, fShortQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2474 initField(&fStandaloneQuarters
, fStandaloneQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2475 initField(&fStandaloneShortQuarters
, fStandaloneShortQuartersCount
, (const UChar
*)gLastResortQuarters
, kQuarterNum
, kQuarterLen
, status
);
2476 fLocalPatternChars
.setTo(TRUE
, gPatternChars
, PATTERN_CHARS_LEN
);
2486 DateFormatSymbols::getLocale(ULocDataLocaleType type
, UErrorCode
& status
) const {
2487 U_LOCALE_BASED(locBased
, *this);
2488 return locBased
.getLocale(type
, status
);
2493 #endif /* #if !UCONFIG_NO_FORMATTING */