• 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__anon5578a7220111::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__anon5578a7220111::CalendarDataSink1537     void visitAllResources() {
1538         resourcesToVisit.adoptInstead(NULL);
1539     }
1540 
1541     // Actions to be done before enumerating
preEnumerate__anon5578a7220111::CalendarDataSink1542     void preEnumerate(const UnicodeString &calendarType) {
1543         currentCalendarType = calendarType;
1544         nextCalendarType.setToBogus();
1545         aliasPathPairs.removeAllElements();
1546     }
1547 
put__anon5578a7220111::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(new UnicodeString(aliasRelativePath), errorCode);
1578                 resourcesToVisitNext->addElementX(aliasRelativePathCopy.getAlias(), errorCode);
1579                 if (U_FAILURE(errorCode)) { return; }
1580                 // Only release ownership after resourcesToVisitNext takes it (no error happened):
1581                 aliasRelativePathCopy.orphan();
1582                 continue;
1583 
1584             } else if (aliasType == SAME_CALENDAR) {
1585                 // Register same-calendar alias
1586                 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
1587                     LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1588                     aliasPathPairs.addElementX(aliasRelativePathCopy.getAlias(), errorCode);
1589                     if (U_FAILURE(errorCode)) { return; }
1590                     // Only release ownership after aliasPathPairs takes it (no error happened):
1591                     aliasRelativePathCopy.orphan();
1592                     LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode);
1593                     aliasPathPairs.addElementX(keyUStringCopy.getAlias(), errorCode);
1594                     if (U_FAILURE(errorCode)) { return; }
1595                     // Only release ownership after aliasPathPairs takes it (no error happened):
1596                     keyUStringCopy.orphan();
1597                 }
1598                 continue;
1599             }
1600 
1601             // Only visit the resources that were referenced by an alias on the previous calendar
1602             // (AmPmMarkersAbbr is an exception).
1603             if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1604                 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1605 
1606             // == Handle data ==
1607             if (uprv_strcmp(key, gAmPmMarkersTag) == 0
1608                 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
1609                 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1610                 if (arrays.get(keyUString) == NULL) {
1611                     ResourceArray resourceArray = value.getArray(errorCode);
1612                     int32_t arraySize = resourceArray.getSize();
1613                     LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1614                     value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1615                     arrays.put(keyUString, stringArray.orphan(), errorCode);
1616                     arraySizes.puti(keyUString, arraySize, errorCode);
1617                     if (U_FAILURE(errorCode)) { return; }
1618                 }
1619             } else if (uprv_strcmp(key, gErasTag) == 0
1620                        || uprv_strcmp(key, gDayNamesTag) == 0
1621                        || uprv_strcmp(key, gMonthNamesTag) == 0
1622                        || uprv_strcmp(key, gQuartersTag) == 0
1623                        || uprv_strcmp(key, gDayPeriodTag) == 0
1624                        || uprv_strcmp(key, gMonthPatternsTag) == 0
1625                        || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
1626                 processResource(keyUString, key, value, errorCode);
1627             }
1628         }
1629 
1630         // Apply same-calendar aliases
1631         UBool modified;
1632         do {
1633             modified = false;
1634             for (int32_t i = 0; i < aliasPathPairs.size();) {
1635                 UBool mod = false;
1636                 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
1637                 UnicodeString *aliasArray;
1638                 Hashtable *aliasMap;
1639                 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
1640                     UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1641                     if (arrays.get(*path) == NULL) {
1642                         // Clone the array
1643                         int32_t aliasArraySize = arraySizes.geti(*alias);
1644                         LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1645                         if (U_FAILURE(errorCode)) { return; }
1646                         uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1647                         // Put the array on the 'arrays' map
1648                         arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1649                         arraySizes.puti(*path, aliasArraySize, errorCode);
1650                     }
1651                     if (U_FAILURE(errorCode)) { return; }
1652                     mod = true;
1653                 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
1654                     UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1655                     if (maps.get(*path) == NULL) {
1656                         maps.put(*path, aliasMap, errorCode);
1657                     }
1658                     if (U_FAILURE(errorCode)) { return; }
1659                     mod = true;
1660                 }
1661                 if (mod) {
1662                     aliasPathPairs.removeElementAt(i + 1);
1663                     aliasPathPairs.removeElementAt(i);
1664                     modified = true;
1665                 } else {
1666                     i += 2;
1667                 }
1668             }
1669         } while (modified && !aliasPathPairs.isEmpty());
1670 
1671         // Set the resources to visit on the next calendar
1672         if (!resourcesToVisitNext.isNull()) {
1673             resourcesToVisit = std::move(resourcesToVisitNext);
1674         }
1675     }
1676 
1677     // Process the nested resource bundle tables
processResource__anon5578a7220111::CalendarDataSink1678     void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1679         if (U_FAILURE(errorCode)) return;
1680 
1681         ResourceTable table = value.getTable(errorCode);
1682         if (U_FAILURE(errorCode)) return;
1683         Hashtable* stringMap = NULL;
1684 
1685         // Iterate over all the elements of the table and add them to the map
1686         for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1687             UnicodeString keyUString(key, -1, US_INV);
1688 
1689             // Ignore '%variant' keys
1690             if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
1691                 continue;
1692             }
1693 
1694             // == Handle String elements ==
1695             if (value.getType() == URES_STRING) {
1696                 // We are on a leaf, store the map elements into the stringMap
1697                 if (i == 0) {
1698                     // mapRefs will keep ownership of 'stringMap':
1699                     stringMap = mapRefs.create(FALSE, errorCode);
1700                     if (stringMap == NULL) {
1701                         errorCode = U_MEMORY_ALLOCATION_ERROR;
1702                         return;
1703                     }
1704                     maps.put(path, stringMap, errorCode);
1705                     if (U_FAILURE(errorCode)) { return; }
1706                     stringMap->setValueDeleter(uprv_deleteUObject);
1707                 }
1708                 U_ASSERT(stringMap != NULL);
1709                 int32_t valueStringSize;
1710                 const UChar *valueString = value.getString(valueStringSize, errorCode);
1711                 if (U_FAILURE(errorCode)) { return; }
1712                 LocalPointer<UnicodeString> valueUString(new UnicodeString(TRUE, valueString, valueStringSize), errorCode);
1713                 stringMap->put(keyUString, valueUString.orphan(), errorCode);
1714                 if (U_FAILURE(errorCode)) { return; }
1715                 continue;
1716             }
1717             U_ASSERT(stringMap == NULL);
1718 
1719             // Store the current path's length and append the current key to the path.
1720             int32_t pathLength = path.length();
1721             path.append(SOLIDUS).append(keyUString);
1722 
1723             // In cyclicNameSets ignore everything but years/format/abbreviated
1724             // and zodiacs/format/abbreviated
1725             if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
1726                 UBool skip = TRUE;
1727                 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
1728                 int32_t length = 0;
1729                 if (startIndex == path.length()
1730                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
1731                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
1732                     || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
1733                     startIndex += length;
1734                     length = 0;
1735                     if (startIndex == path.length()
1736                         || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
1737                         startIndex += length;
1738                         length = 0;
1739                         if (startIndex == path.length()
1740                             || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
1741                             skip = FALSE;
1742                         }
1743                     }
1744                 }
1745                 if (skip) {
1746                     // Drop the latest key on the path and continue
1747                     path.retainBetween(0, pathLength);
1748                     continue;
1749                 }
1750             }
1751 
1752             // == Handle aliases ==
1753             if (arrays.get(path) != NULL || maps.get(path) != NULL) {
1754                 // Drop the latest key on the path and continue
1755                 path.retainBetween(0, pathLength);
1756                 continue;
1757             }
1758 
1759             AliasType aliasType = processAliasFromValue(path, value, errorCode);
1760             if (U_FAILURE(errorCode)) { return; }
1761             if (aliasType == SAME_CALENDAR) {
1762                 // Store the alias path and the current path on aliasPathPairs
1763                 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1764                 aliasPathPairs.addElementX(aliasRelativePathCopy.getAlias(), errorCode);
1765                 if (U_FAILURE(errorCode)) { return; }
1766                 // Only release ownership after aliasPathPairs takes it (no error happened):
1767                 aliasRelativePathCopy.orphan();
1768                 LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode);
1769                 aliasPathPairs.addElementX(pathCopy.getAlias(), errorCode);
1770                 if (U_FAILURE(errorCode)) { return; }
1771                 // Only release ownership after aliasPathPairs takes it (no error happened):
1772                 pathCopy.orphan();
1773 
1774                 // Drop the latest key on the path and continue
1775                 path.retainBetween(0, pathLength);
1776                 continue;
1777             }
1778             U_ASSERT(aliasType == NONE);
1779 
1780             // == Handle data ==
1781             if (value.getType() == URES_ARRAY) {
1782                 // We are on a leaf, store the array
1783                 ResourceArray rDataArray = value.getArray(errorCode);
1784                 int32_t dataArraySize = rDataArray.getSize();
1785                 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1786                 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1787                 arrays.put(path, dataArray.orphan(), errorCode);
1788                 arraySizes.puti(path, dataArraySize, errorCode);
1789                 if (U_FAILURE(errorCode)) { return; }
1790             } else if (value.getType() == URES_TABLE) {
1791                 // We are not on a leaf, recursively process the subtable.
1792                 processResource(path, key, value, errorCode);
1793                 if (U_FAILURE(errorCode)) { return; }
1794             }
1795 
1796             // Drop the latest key on the path
1797             path.retainBetween(0, pathLength);
1798         }
1799     }
1800 
1801     // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
processAliasFromValue__anon5578a7220111::CalendarDataSink1802     AliasType processAliasFromValue(UnicodeString &currentRelativePath, ResourceValue &value,
1803                                     UErrorCode &errorCode) {
1804         if (U_FAILURE(errorCode)) { return NONE; }
1805 
1806         if (value.getType() == URES_ALIAS) {
1807             int32_t aliasPathSize;
1808             const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1809             if (U_FAILURE(errorCode)) { return NONE; }
1810             UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1811             const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
1812             if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1813                 && aliasPath.length() > aliasPrefixLength) {
1814                 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
1815                 if (typeLimit > aliasPrefixLength) {
1816                     const UnicodeString aliasCalendarType =
1817                         aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1818                     aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1819 
1820                     if (currentCalendarType == aliasCalendarType
1821                         && currentRelativePath != aliasRelativePath) {
1822                         // If we have an alias to the same calendar, the path to the resource must be different
1823                         return SAME_CALENDAR;
1824 
1825                     } else if (currentCalendarType != aliasCalendarType
1826                                && currentRelativePath == aliasRelativePath) {
1827                         // If we have an alias to a different calendar, the path to the resource must be the same
1828                         if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
1829                             return GREGORIAN;
1830                         } else if (nextCalendarType.isBogus()) {
1831                             nextCalendarType = aliasCalendarType;
1832                             return DIFFERENT_CALENDAR;
1833                         } else if (nextCalendarType == aliasCalendarType) {
1834                             return DIFFERENT_CALENDAR;
1835                         }
1836                     }
1837                 }
1838             }
1839             errorCode = U_INTERNAL_PROGRAM_ERROR;
1840             return NONE;
1841         }
1842         return NONE;
1843     }
1844 
1845     // Deleter function to be used by 'arrays'
deleteUnicodeStringArray__anon5578a7220111::CalendarDataSink1846     static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1847         delete[] static_cast<UnicodeString *>(uArray);
1848     }
1849 };
1850 // Virtual destructors have to be defined out of line
~CalendarDataSink()1851 CalendarDataSink::~CalendarDataSink() {
1852     arrays.setValueDeleter(deleteUnicodeStringArray);
1853 }
1854 }
1855 
1856 //------------------------------------------------------
1857 
1858 static void
initField(UnicodeString ** field,int32_t & length,const UChar * data,LastResortSize numStr,LastResortSize strLen,UErrorCode & status)1859 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1860     if (U_SUCCESS(status)) {
1861         length = numStr;
1862         *field = newUnicodeStringArray((size_t)numStr);
1863         if (*field) {
1864             for(int32_t i = 0; i<length; i++) {
1865                 // readonly aliases - all "data" strings are constant
1866                 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1867                 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1868             }
1869         }
1870         else {
1871             length = 0;
1872             status = U_MEMORY_ALLOCATION_ERROR;
1873         }
1874     }
1875 }
1876 
1877 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,UErrorCode & status)1878 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1879     if (U_SUCCESS(status)) {
1880         UnicodeString keyUString(key.data(), -1, US_INV);
1881         UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1882 
1883         if (array != NULL) {
1884             length = sink.arraySizes.geti(keyUString);
1885             *field = array;
1886             // DateFormatSymbols takes ownership of the array:
1887             sink.arrays.remove(keyUString);
1888         } else {
1889             length = 0;
1890             status = U_MISSING_RESOURCE_ERROR;
1891         }
1892     }
1893 }
1894 
1895 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,int32_t arrayOffset,UErrorCode & status)1896 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1897     if (U_SUCCESS(status)) {
1898         UnicodeString keyUString(key.data(), -1, US_INV);
1899         UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1900 
1901         if (array != NULL) {
1902             int32_t arrayLength = sink.arraySizes.geti(keyUString);
1903             length = arrayLength + arrayOffset;
1904             *field = new UnicodeString[length];
1905             if (*field == NULL) {
1906                 status = U_MEMORY_ALLOCATION_ERROR;
1907                 return;
1908             }
1909             uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1910         } else {
1911             length = 0;
1912             status = U_MISSING_RESOURCE_ERROR;
1913         }
1914     }
1915 }
1916 
1917 static void
initLeapMonthPattern(UnicodeString * field,int32_t index,CalendarDataSink & sink,CharString & path,UErrorCode & status)1918 initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
1919     field[index].remove();
1920     if (U_SUCCESS(status)) {
1921         UnicodeString pathUString(path.data(), -1, US_INV);
1922         Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
1923         if (leapMonthTable != NULL) {
1924             UnicodeString leapLabel(FALSE, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
1925             UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
1926             if (leapMonthPattern != NULL) {
1927                 field[index].fastCopyFrom(*leapMonthPattern);
1928             } else {
1929                 field[index].setToBogus();
1930             }
1931             return;
1932         }
1933         status = U_MISSING_RESOURCE_ERROR;
1934     }
1935 }
1936 
1937 static CharString
buildResourcePath(CharString & path,const char * segment1,UErrorCode & errorCode)1938 &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
1939     return path.clear().append(segment1, -1, errorCode);
1940 }
1941 
1942 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,UErrorCode & errorCode)1943 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1944                    UErrorCode &errorCode) {
1945     return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
1946                                                        .append(segment2, -1, errorCode);
1947 }
1948 
1949 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,UErrorCode & errorCode)1950 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1951                    const char* segment3, UErrorCode &errorCode) {
1952     return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
1953                                                                  .append(segment3, -1, errorCode);
1954 }
1955 
1956 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,const char * segment4,UErrorCode & errorCode)1957 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1958                    const char* segment3, const char* segment4, UErrorCode &errorCode) {
1959     return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
1960                                                                            .append(segment4, -1, errorCode);
1961 }
1962 
1963 typedef struct {
1964     const char * usageTypeName;
1965     DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1966 } ContextUsageTypeNameToEnumValue;
1967 
1968 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1969    // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1970     { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1971     { "day-narrow",     DateFormatSymbols::kCapContextUsageDayNarrow },
1972     { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1973     { "era-abbr",       DateFormatSymbols::kCapContextUsageEraAbbrev },
1974     { "era-name",       DateFormatSymbols::kCapContextUsageEraWide },
1975     { "era-narrow",     DateFormatSymbols::kCapContextUsageEraNarrow },
1976     { "metazone-long",  DateFormatSymbols::kCapContextUsageMetazoneLong },
1977     { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1978     { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1979     { "month-narrow",   DateFormatSymbols::kCapContextUsageMonthNarrow },
1980     { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1981     { "zone-long",      DateFormatSymbols::kCapContextUsageZoneLong },
1982     { "zone-short",     DateFormatSymbols::kCapContextUsageZoneShort },
1983     { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1984 };
1985 
1986 // Resource keys to look up localized strings for day periods.
1987 // The first one must be midnight and the second must be noon, so that their indices coincide
1988 // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1989 static const char *dayPeriodKeys[] = {"midnight", "noon",
1990                          "morning1", "afternoon1", "evening1", "night1",
1991                          "morning2", "afternoon2", "evening2", "night2"};
1992 
loadDayPeriodStrings(CalendarDataSink & sink,CharString & path,int32_t & stringCount,UErrorCode & status)1993 UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
1994                                     int32_t &stringCount,  UErrorCode &status) {
1995     if (U_FAILURE(status)) { return NULL; }
1996 
1997     UnicodeString pathUString(path.data(), -1, US_INV);
1998     Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
1999 
2000     stringCount = UPRV_LENGTHOF(dayPeriodKeys);
2001     UnicodeString *strings = new UnicodeString[stringCount];
2002     if (strings == NULL) {
2003         status = U_MEMORY_ALLOCATION_ERROR;
2004         return NULL;
2005     }
2006 
2007     if (map != NULL) {
2008         for (int32_t i = 0; i < stringCount; ++i) {
2009             UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
2010             UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2011             if (dayPeriod != NULL) {
2012                 strings[i].fastCopyFrom(*dayPeriod);
2013             } else {
2014                 strings[i].setToBogus();
2015             }
2016         }
2017     } else {
2018         for (int32_t i = 0; i < stringCount; i++) {
2019             strings[i].setToBogus();
2020         }
2021     }
2022     return strings;
2023 }
2024 
2025 
2026 void
initializeData(const Locale & locale,const char * type,UErrorCode & status,UBool useLastResortData)2027 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2028 {
2029     int32_t len = 0;
2030     /* In case something goes wrong, initialize all of the data to NULL. */
2031     fEras = NULL;
2032     fErasCount = 0;
2033     fEraNames = NULL;
2034     fEraNamesCount = 0;
2035     fNarrowEras = NULL;
2036     fNarrowErasCount = 0;
2037     fMonths = NULL;
2038     fMonthsCount=0;
2039     fShortMonths = NULL;
2040     fShortMonthsCount=0;
2041     fNarrowMonths = NULL;
2042     fNarrowMonthsCount=0;
2043     fStandaloneMonths = NULL;
2044     fStandaloneMonthsCount=0;
2045     fStandaloneShortMonths = NULL;
2046     fStandaloneShortMonthsCount=0;
2047     fStandaloneNarrowMonths = NULL;
2048     fStandaloneNarrowMonthsCount=0;
2049     fWeekdays = NULL;
2050     fWeekdaysCount=0;
2051     fShortWeekdays = NULL;
2052     fShortWeekdaysCount=0;
2053     fShorterWeekdays = NULL;
2054     fShorterWeekdaysCount=0;
2055     fNarrowWeekdays = NULL;
2056     fNarrowWeekdaysCount=0;
2057     fStandaloneWeekdays = NULL;
2058     fStandaloneWeekdaysCount=0;
2059     fStandaloneShortWeekdays = NULL;
2060     fStandaloneShortWeekdaysCount=0;
2061     fStandaloneShorterWeekdays = NULL;
2062     fStandaloneShorterWeekdaysCount=0;
2063     fStandaloneNarrowWeekdays = NULL;
2064     fStandaloneNarrowWeekdaysCount=0;
2065     fAmPms = NULL;
2066     fAmPmsCount=0;
2067     fNarrowAmPms = NULL;
2068     fNarrowAmPmsCount=0;
2069     fTimeSeparator.setToBogus();
2070     fQuarters = NULL;
2071     fQuartersCount = 0;
2072     fShortQuarters = NULL;
2073     fShortQuartersCount = 0;
2074     fNarrowQuarters = NULL;
2075     fNarrowQuartersCount = 0;
2076     fStandaloneQuarters = NULL;
2077     fStandaloneQuartersCount = 0;
2078     fStandaloneShortQuarters = NULL;
2079     fStandaloneShortQuartersCount = 0;
2080     fStandaloneNarrowQuarters = NULL;
2081     fStandaloneNarrowQuartersCount = 0;
2082     fLeapMonthPatterns = NULL;
2083     fLeapMonthPatternsCount = 0;
2084     fShortYearNames = NULL;
2085     fShortYearNamesCount = 0;
2086     fShortZodiacNames = NULL;
2087     fShortZodiacNamesCount = 0;
2088     fZoneStringsRowCount = 0;
2089     fZoneStringsColCount = 0;
2090     fZoneStrings = NULL;
2091     fLocaleZoneStrings = NULL;
2092     fAbbreviatedDayPeriods = NULL;
2093     fAbbreviatedDayPeriodsCount = 0;
2094     fWideDayPeriods = NULL;
2095     fWideDayPeriodsCount = 0;
2096     fNarrowDayPeriods = NULL;
2097     fNarrowDayPeriodsCount = 0;
2098     fStandaloneAbbreviatedDayPeriods = NULL;
2099     fStandaloneAbbreviatedDayPeriodsCount = 0;
2100     fStandaloneWideDayPeriods = NULL;
2101     fStandaloneWideDayPeriodsCount = 0;
2102     fStandaloneNarrowDayPeriods = NULL;
2103     fStandaloneNarrowDayPeriodsCount = 0;
2104     uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
2105 
2106     // We need to preserve the requested locale for
2107     // lazy ZoneStringFormat instantiation.  ZoneStringFormat
2108     // is region sensitive, thus, bundle locale bundle's locale
2109     // is not sufficient.
2110     fZSFLocale = locale;
2111 
2112     if (U_FAILURE(status)) return;
2113 
2114     // Create a CalendarDataSink to process this data and the resource bundles
2115     CalendarDataSink calendarSink(status);
2116     UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
2117     UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
2118 
2119     if (U_FAILURE(status)) return;
2120 
2121     // Iterate over the resource bundle data following the fallbacks through different calendar types
2122     UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
2123     while (!calendarType.isBogus()) {
2124         CharString calendarTypeBuffer;
2125         calendarTypeBuffer.appendInvariantChars(calendarType, status);
2126         if (U_FAILURE(status)) { return; }
2127         const char *calendarTypeCArray = calendarTypeBuffer.data();
2128 
2129         // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2130         UErrorCode oldStatus = status;
2131         UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
2132         if (status == U_MISSING_RESOURCE_ERROR) {
2133             ures_close(ctb);
2134             if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
2135                 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2136                 calendarSink.visitAllResources();
2137                 status = oldStatus;
2138                 continue;
2139             }
2140             return;
2141         }
2142 
2143         calendarSink.preEnumerate(calendarType);
2144         ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
2145         ures_close(ctb);
2146         if (U_FAILURE(status)) break;
2147 
2148         // Stop loading when gregorian was loaded
2149         if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2150             break;
2151         }
2152 
2153         // Get the next calendar type to process from the sink
2154         calendarType = calendarSink.nextCalendarType;
2155 
2156         // Gregorian is always the last fallback
2157         if (calendarType.isBogus()) {
2158             calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2159             calendarSink.visitAllResources();
2160         }
2161     }
2162 
2163     // CharString object to build paths
2164     CharString path;
2165 
2166     // Load Leap Month Patterns
2167     UErrorCode tempStatus = status;
2168     fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2169     if (fLeapMonthPatterns) {
2170         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2171                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2172         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2173                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2174         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2175                              buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2176         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2177                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2178         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2179                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2180         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2181                              buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2182         initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2183                              buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2184         if (U_SUCCESS(tempStatus)) {
2185             // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2186             // The ordering of the following statements is important.
2187             if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
2188                 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2189             }
2190             if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
2191                 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
2192             }
2193             if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
2194                 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2195             }
2196             if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
2197                 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
2198             }
2199             // end of hack
2200             fLeapMonthPatternsCount = kMonthPatternsCount;
2201         } else {
2202             delete[] fLeapMonthPatterns;
2203             fLeapMonthPatterns = NULL;
2204         }
2205     }
2206 
2207     // Load cyclic names sets
2208     tempStatus = status;
2209     initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2210               buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2211     initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2212               buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2213 
2214     // Load context transforms and capitalization
2215     tempStatus = U_ZERO_ERROR;
2216     UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
2217     if (U_SUCCESS(tempStatus)) {
2218         UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
2219         if (U_SUCCESS(tempStatus)) {
2220             UResourceBundle *contextTransformUsage;
2221             while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
2222                 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
2223                 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
2224                     const char* usageType = ures_getKey(contextTransformUsage);
2225                     if (usageType != NULL) {
2226                         const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2227                         int32_t compResult = 0;
2228                         // linear search; list is short and we cannot be sure that bsearch is available
2229                         while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2230                             ++typeMapPtr;
2231                         }
2232                         if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
2233                             fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2234                             fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2235                         }
2236                     }
2237                 }
2238                 tempStatus = U_ZERO_ERROR;
2239                 ures_close(contextTransformUsage);
2240             }
2241             ures_close(contextTransforms);
2242         }
2243 
2244         tempStatus = U_ZERO_ERROR;
2245         const LocalPointer<NumberingSystem> numberingSystem(
2246                 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2247         if (U_SUCCESS(tempStatus)) {
2248             // These functions all fail gracefully if passed NULL pointers and
2249             // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2250             // to check for errors once after all calls are made.
2251             const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
2252                     localeBundle, gNumberElementsTag, NULL, &tempStatus));
2253             const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
2254                     numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
2255             const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
2256                     nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
2257             fTimeSeparator = ures_getUnicodeStringByKey(
2258                     symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2259             if (U_FAILURE(tempStatus)) {
2260                 fTimeSeparator.setToBogus();
2261             }
2262         }
2263 
2264         ures_close(localeBundle);
2265     }
2266 
2267     if (fTimeSeparator.isBogus()) {
2268         fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2269     }
2270 
2271     // Load day periods
2272     fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2273                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2274                             fWideDayPeriodsCount, status);
2275     fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2276                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2277                             fNarrowDayPeriodsCount, status);
2278     fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2279                             buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2280                             fAbbreviatedDayPeriodsCount, status);
2281     fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2282                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2283                             fStandaloneWideDayPeriodsCount, status);
2284     fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2285                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2286                             fStandaloneNarrowDayPeriodsCount, status);
2287     fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2288                             buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2289                             fStandaloneAbbreviatedDayPeriodsCount, status);
2290 
2291     U_LOCALE_BASED(locBased, *this);
2292     // if we make it to here, the resource data is cool, and we can get everything out
2293     // of it that we need except for the time-zone and localized-pattern data, which
2294     // are stored in a separate file
2295     locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
2296                           ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
2297 
2298     // Load eras
2299     initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
2300     UErrorCode oldStatus = status;
2301     initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
2302     if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2303         status = oldStatus;
2304         assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
2305     }
2306     // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2307     oldStatus = status;
2308     initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
2309     if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2310         status = oldStatus;
2311         assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
2312     }
2313 
2314     // Load month names
2315     initField(&fMonths, fMonthsCount, calendarSink,
2316               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2317     initField(&fShortMonths, fShortMonthsCount, calendarSink,
2318               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2319     initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2320               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2321     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
2322         status = U_ZERO_ERROR;
2323         assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
2324     }
2325     initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2326               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2327     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
2328         status = U_ZERO_ERROR;
2329         assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
2330     }
2331 
2332     UErrorCode narrowMonthsEC = status;
2333     UErrorCode standaloneNarrowMonthsEC = status;
2334     initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2335               buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2336     initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2337               buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2338     if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
2339         // If format/narrow not available, use standalone/narrow
2340         assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
2341     } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2342         // If standalone/narrow not available, use format/narrow
2343         assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
2344     } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2345         // If neither is available, use format/abbreviated
2346         assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2347         assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2348     }
2349 
2350     // Load AM/PM markers; if wide or narrow not available, use short
2351     UErrorCode ampmStatus = U_ZERO_ERROR;
2352     initField(&fAmPms, fAmPmsCount, calendarSink,
2353               buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2354     if (U_FAILURE(ampmStatus)) {
2355         initField(&fAmPms, fAmPmsCount, calendarSink,
2356                   buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2357     }
2358     ampmStatus = U_ZERO_ERROR;
2359     initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2360               buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2361     if (U_FAILURE(ampmStatus)) {
2362         initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2363                   buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2364     }
2365 
2366     // Load quarters
2367     initField(&fQuarters, fQuartersCount, calendarSink,
2368               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2369     initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2370               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2371 
2372     initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2373               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2374     if(status == U_MISSING_RESOURCE_ERROR) {
2375         status = U_ZERO_ERROR;
2376         assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2377     }
2378     initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2379               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2380     if(status == U_MISSING_RESOURCE_ERROR) {
2381         status = U_ZERO_ERROR;
2382         assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
2383     }
2384 
2385     // unlike the fields above, narrow format quarters fall back on narrow standalone quarters
2386     initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, calendarSink,
2387               buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
2388     initField(&fNarrowQuarters, fNarrowQuartersCount, calendarSink,
2389               buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesNarrowTag, status), status);
2390     if(status == U_MISSING_RESOURCE_ERROR) {
2391         status = U_ZERO_ERROR;
2392         assignArray(fNarrowQuarters, fNarrowQuartersCount, fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount);
2393     }
2394 
2395     // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2396     /*
2397     // fastCopyFrom()/setTo() - see assignArray comments
2398     resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2399     fLocalPatternChars.setTo(TRUE, resStr, len);
2400     // If the locale data does not include new pattern chars, use the defaults
2401     // TODO: Consider making this an error, since this may add conflicting characters.
2402     if (len < PATTERN_CHARS_LEN) {
2403         fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2404     }
2405     */
2406     fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2407 
2408     // Format wide weekdays -> fWeekdays
2409     // {sfb} fixed to handle 1-based weekdays
2410     initField(&fWeekdays, fWeekdaysCount, calendarSink,
2411               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2412 
2413     // Format abbreviated weekdays -> fShortWeekdays
2414     initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2415               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2416 
2417     // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2418     initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2419               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2420     if (status == U_MISSING_RESOURCE_ERROR) {
2421         status = U_ZERO_ERROR;
2422         assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2423     }
2424 
2425     // Stand-alone wide weekdays -> fStandaloneWeekdays
2426     initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2427               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2428     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
2429         status = U_ZERO_ERROR;
2430         assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
2431     }
2432 
2433     // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2434     initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2435               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2436     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
2437         status = U_ZERO_ERROR;
2438         assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2439     }
2440 
2441     // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2442     initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2443               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2444     if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
2445         status = U_ZERO_ERROR;
2446         assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
2447     }
2448 
2449     // Format narrow weekdays -> fNarrowWeekdays
2450     UErrorCode narrowWeeksEC = status;
2451     initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2452               buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2453     // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2454     UErrorCode standaloneNarrowWeeksEC = status;
2455     initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2456               buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2457 
2458     if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
2459         // If format/narrow not available, use standalone/narrow
2460         assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
2461     } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
2462         // If standalone/narrow not available, use format/narrow
2463         assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
2464     } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
2465         // If neither is available, use format/abbreviated
2466         assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2467         assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2468     }
2469 
2470     // Last resort fallback in case previous data wasn't loaded
2471     if (U_FAILURE(status))
2472     {
2473         if (useLastResortData)
2474         {
2475             // Handle the case in which there is no resource data present.
2476             // We don't have to generate usable patterns in this situation;
2477             // we just need to produce something that will be semi-intelligible
2478             // in most locales.
2479 
2480             status = U_USING_FALLBACK_WARNING;
2481             //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2482             initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2483             initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2484             initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2485             initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
2486             initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2487             initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2488             initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
2489             initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2490             initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2491             initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2492             initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2493             initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2494             initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2495             initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2496             initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2497             initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2498             initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2499             initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2500             initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2501             initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2502             initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2503             initField(&fNarrowQuarters, fNarrowQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2504             initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2505             initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2506             initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2507             fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2508         }
2509     }
2510 
2511     // Close resources
2512     ures_close(cb);
2513     ures_close(rb);
2514 }
2515 
2516 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const2517 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
2518     U_LOCALE_BASED(locBased, *this);
2519     return locBased.getLocale(type, status);
2520 }
2521 
2522 U_NAMESPACE_END
2523 
2524 #endif /* #if !UCONFIG_NO_FORMATTING */
2525 
2526 //eof
2527