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