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