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