1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2015, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 *
7 * File DTFMTSYM.CPP
8 *
9 * Modification History:
10 *
11 *   Date        Name        Description
12 *   02/19/97    aliu        Converted from java.
13 *   07/21/98    stephen     Added getZoneIndex
14 *                            Changed weekdays/short weekdays to be one-based
15 *   06/14/99    stephen     Removed SimpleDateFormat::fgTimeZoneDataSuffix
16 *   11/16/99    weiv        Added 'Y' and 'e' to fgPatternChars
17 *   03/27/00    weiv        Keeping resource bundle around!
18 *   06/30/05    emmons      Added eraNames, narrow month/day, standalone context
19 *   10/12/05    emmons      Added setters for eraNames, month/day by width/context
20 *******************************************************************************
21 */
22 #include "unicode/utypes.h"
23 
24 #if !UCONFIG_NO_FORMATTING
25 #include "unicode/ustring.h"
26 #include "unicode/localpointer.h"
27 #include "unicode/dtfmtsym.h"
28 #include "unicode/smpdtfmt.h"
29 #include "unicode/msgfmt.h"
30 #include "unicode/numsys.h"
31 #include "unicode/tznames.h"
32 #include "cpputils.h"
33 #include "umutex.h"
34 #include "cmemory.h"
35 #include "cstring.h"
36 #include "locbased.h"
37 #include "gregoimp.h"
38 #include "hash.h"
39 #include "uresimp.h"
40 #include "ureslocs.h"
41 #include "shareddateformatsymbols.h"
42 #include "unicode/calendar.h"
43 #include "unifiedcache.h"
44 
45 // *****************************************************************************
46 // class DateFormatSymbols
47 // *****************************************************************************
48 
49 /**
50  * These are static arrays we use only in the case where we have no
51  * resource data.
52  */
53 
54 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
55 #define PATTERN_CHARS_LEN 36
56 #else
57 #define PATTERN_CHARS_LEN 35
58 #endif
59 
60 /**
61  * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
62  * locales use the same these unlocalized pattern characters.
63  */
64 static const UChar gPatternChars[] = {
65 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
66     // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr:
67 #else
68     // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxr
69 #endif
70     0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
71     0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
72     0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
73 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
74     0x55, 0x4F, 0x58, 0x78, 0x72, 0x3a, 0
75 #else
76     0x55, 0x4F, 0x58, 0x78, 0x72, 0
77 #endif
78 };
79 
80 /* length of an array */
81 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0]))
82 
83 //------------------------------------------------------
84 // Strings of last resort.  These are only used if we have no resource
85 // files.  They aren't designed for actual use, just for backup.
86 
87 // These are the month names and abbreviations of last resort.
88 static const UChar gLastResortMonthNames[13][3] =
89 {
90     {0x0030, 0x0031, 0x0000}, /* "01" */
91     {0x0030, 0x0032, 0x0000}, /* "02" */
92     {0x0030, 0x0033, 0x0000}, /* "03" */
93     {0x0030, 0x0034, 0x0000}, /* "04" */
94     {0x0030, 0x0035, 0x0000}, /* "05" */
95     {0x0030, 0x0036, 0x0000}, /* "06" */
96     {0x0030, 0x0037, 0x0000}, /* "07" */
97     {0x0030, 0x0038, 0x0000}, /* "08" */
98     {0x0030, 0x0039, 0x0000}, /* "09" */
99     {0x0031, 0x0030, 0x0000}, /* "10" */
100     {0x0031, 0x0031, 0x0000}, /* "11" */
101     {0x0031, 0x0032, 0x0000}, /* "12" */
102     {0x0031, 0x0033, 0x0000}  /* "13" */
103 };
104 
105 // These are the weekday names and abbreviations of last resort.
106 static const UChar gLastResortDayNames[8][2] =
107 {
108     {0x0030, 0x0000}, /* "0" */
109     {0x0031, 0x0000}, /* "1" */
110     {0x0032, 0x0000}, /* "2" */
111     {0x0033, 0x0000}, /* "3" */
112     {0x0034, 0x0000}, /* "4" */
113     {0x0035, 0x0000}, /* "5" */
114     {0x0036, 0x0000}, /* "6" */
115     {0x0037, 0x0000}  /* "7" */
116 };
117 
118 // These are the quarter names and abbreviations of last resort.
119 static const UChar gLastResortQuarters[4][2] =
120 {
121     {0x0031, 0x0000}, /* "1" */
122     {0x0032, 0x0000}, /* "2" */
123     {0x0033, 0x0000}, /* "3" */
124     {0x0034, 0x0000}, /* "4" */
125 };
126 
127 // These are the am/pm and BC/AD markers of last resort.
128 static const UChar gLastResortAmPmMarkers[2][3] =
129 {
130     {0x0041, 0x004D, 0x0000}, /* "AM" */
131     {0x0050, 0x004D, 0x0000}  /* "PM" */
132 };
133 
134 static const UChar gLastResortEras[2][3] =
135 {
136     {0x0042, 0x0043, 0x0000}, /* "BC" */
137     {0x0041, 0x0044, 0x0000}  /* "AD" */
138 };
139 
140 /* Sizes for the last resort string arrays */
141 typedef enum LastResortSize {
142     kMonthNum = 13,
143     kMonthLen = 3,
144 
145     kDayNum = 8,
146     kDayLen = 2,
147 
148     kAmPmNum = 2,
149     kAmPmLen = 3,
150 
151     kQuarterNum = 4,
152     kQuarterLen = 2,
153 
154     kEraNum = 2,
155     kEraLen = 3,
156 
157     kZoneNum = 5,
158     kZoneLen = 4,
159 
160     kGmtHourNum = 4,
161     kGmtHourLen = 10
162 } LastResortSize;
163 
164 U_NAMESPACE_BEGIN
165 
~SharedDateFormatSymbols()166 SharedDateFormatSymbols::~SharedDateFormatSymbols() {
167 }
168 
169 template<> U_I18N_API
170 const SharedDateFormatSymbols *
createObject(const void *,UErrorCode & status) const171         LocaleCacheKey<SharedDateFormatSymbols>::createObject(
172                 const void */*unusedContext*/, UErrorCode &status) const {
173     char type[256];
174     Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
175     if (U_FAILURE(status)) {
176         return NULL;
177     }
178     SharedDateFormatSymbols *shared
179             = new SharedDateFormatSymbols(fLoc, type, status);
180     if (shared == NULL) {
181         status = U_MEMORY_ALLOCATION_ERROR;
182         return NULL;
183     }
184     if (U_FAILURE(status)) {
185         delete shared;
186         return NULL;
187     }
188     shared->addRef();
189     return shared;
190 }
191 
192 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
193 
194 #define kSUPPLEMENTAL "supplementalData"
195 
196 /**
197  * These are the tags we expect to see in normal resource bundle files associated
198  * with a locale and calendar
199  */
200 static const char gErasTag[]="eras";
201 static const char gCyclicNameSetsTag[]="cyclicNameSets";
202 static const char gNameSetYearsTag[]="years";
203 static const char gNameSetZodiacsTag[]="zodiacs";
204 static const char gMonthNamesTag[]="monthNames";
205 static const char gMonthPatternsTag[]="monthPatterns";
206 static const char gDayNamesTag[]="dayNames";
207 static const char gNamesWideTag[]="wide";
208 static const char gNamesAbbrTag[]="abbreviated";
209 static const char gNamesShortTag[]="short";
210 static const char gNamesNarrowTag[]="narrow";
211 static const char gNamesAllTag[]="all";
212 static const char gNamesLeapTag[]="leap";
213 static const char gNamesFormatTag[]="format";
214 static const char gNamesStandaloneTag[]="stand-alone";
215 static const char gNamesNumericTag[]="numeric";
216 static const char gAmPmMarkersTag[]="AmPmMarkers";
217 static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
218 static const char gQuartersTag[]="quarters";
219 static const char gNumberElementsTag[]="NumberElements";
220 static const char gSymbolsTag[]="symbols";
221 static const char gTimeSeparatorTag[]="timeSeparator";
222 
223 // static const char gZoneStringsTag[]="zoneStrings";
224 
225 // static const char gLocalPatternCharsTag[]="localPatternChars";
226 
227 static const char gContextTransformsTag[]="contextTransforms";
228 
229 static UMutex LOCK = U_MUTEX_INITIALIZER;
230 
231 /**
232  * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
233  * Work around this.
234  */
newUnicodeStringArray(size_t count)235 static inline UnicodeString* newUnicodeStringArray(size_t count) {
236     return new UnicodeString[count ? count : 1];
237 }
238 
239 //------------------------------------------------------
240 
241 DateFormatSymbols * U_EXPORT2
createForLocale(const Locale & locale,UErrorCode & status)242 DateFormatSymbols::createForLocale(
243         const Locale& locale, UErrorCode &status) {
244     const SharedDateFormatSymbols *shared = NULL;
245     UnifiedCache::getByLocale(locale, shared, status);
246     if (U_FAILURE(status)) {
247         return NULL;
248     }
249     DateFormatSymbols *result = new DateFormatSymbols(shared->get());
250     shared->removeRef();
251     if (result == NULL) {
252         status = U_MEMORY_ALLOCATION_ERROR;
253         return NULL;
254     }
255     return result;
256 }
257 
DateFormatSymbols(const Locale & locale,UErrorCode & status)258 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
259                                      UErrorCode& status)
260     : UObject()
261 {
262   initializeData(locale, NULL,  status);
263 }
264 
DateFormatSymbols(UErrorCode & status)265 DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
266     : UObject()
267 {
268   initializeData(Locale::getDefault(), NULL, status, TRUE);
269 }
270 
271 
DateFormatSymbols(const Locale & locale,const char * type,UErrorCode & status)272 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
273                                      const char *type,
274                                      UErrorCode& status)
275     : UObject()
276 {
277   initializeData(locale, type,  status);
278 }
279 
DateFormatSymbols(const char * type,UErrorCode & status)280 DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
281     : UObject()
282 {
283   initializeData(Locale::getDefault(), type, status, TRUE);
284 }
285 
DateFormatSymbols(const DateFormatSymbols & other)286 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
287     : UObject(other)
288 {
289     copyData(other);
290 }
291 
292 void
assignArray(UnicodeString * & dstArray,int32_t & dstCount,const UnicodeString * srcArray,int32_t srcCount)293 DateFormatSymbols::assignArray(UnicodeString*& dstArray,
294                                int32_t& dstCount,
295                                const UnicodeString* srcArray,
296                                int32_t srcCount)
297 {
298     // assignArray() is only called by copyData(), which in turn implements the
299     // copy constructor and the assignment operator.
300     // All strings in a DateFormatSymbols object are created in one of the following
301     // three ways that all allow to safely use UnicodeString::fastCopyFrom():
302     // - readonly-aliases from resource bundles
303     // - readonly-aliases or allocated strings from constants
304     // - safely cloned strings (with owned buffers) from setXYZ() functions
305     //
306     // Note that this is true for as long as DateFormatSymbols can be constructed
307     // only from a locale bundle or set via the cloning API,
308     // *and* for as long as all the strings are in *private* fields, preventing
309     // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
310     dstCount = srcCount;
311     dstArray = newUnicodeStringArray(srcCount);
312     if(dstArray != NULL) {
313         int32_t i;
314         for(i=0; i<srcCount; ++i) {
315             dstArray[i].fastCopyFrom(srcArray[i]);
316         }
317     }
318 }
319 
320 /**
321  * Create a copy, in fZoneStrings, of the given zone strings array.  The
322  * member variables fZoneStringsRowCount and fZoneStringsColCount should
323  * be set already by the caller.
324  */
325 void
createZoneStrings(const UnicodeString * const * otherStrings)326 DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
327 {
328     int32_t row, col;
329     UBool failed = FALSE;
330 
331     fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
332     if (fZoneStrings != NULL) {
333         for (row=0; row<fZoneStringsRowCount; ++row)
334         {
335             fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
336             if (fZoneStrings[row] == NULL) {
337                 failed = TRUE;
338                 break;
339             }
340             for (col=0; col<fZoneStringsColCount; ++col) {
341                 // fastCopyFrom() - see assignArray comments
342                 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
343             }
344         }
345     }
346     // If memory allocation failed, roll back and delete fZoneStrings
347     if (failed) {
348         for (int i = row; i >= 0; i--) {
349             delete[] fZoneStrings[i];
350         }
351         uprv_free(fZoneStrings);
352         fZoneStrings = NULL;
353     }
354 }
355 
356 /**
357  * Copy all of the other's data to this.
358  */
359 void
copyData(const DateFormatSymbols & other)360 DateFormatSymbols::copyData(const DateFormatSymbols& other) {
361     UErrorCode status = U_ZERO_ERROR;
362     U_LOCALE_BASED(locBased, *this);
363     locBased.setLocaleIDs(
364         other.getLocale(ULOC_VALID_LOCALE, status),
365         other.getLocale(ULOC_ACTUAL_LOCALE, status));
366     assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
367     assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
368     assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
369     assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
370     assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
371     assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
372     assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
373     assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
374     assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
375     assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
376     assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
377     assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
378     assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
379     assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
380     assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
381     assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
382     assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
383     assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
384     assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
385     fTimeSeparator.fastCopyFrom(other.fTimeSeparator);  // fastCopyFrom() - see assignArray comments
386     assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
387     assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
388     assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
389     assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
390     if (other.fLeapMonthPatterns != NULL) {
391         assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
392     } else {
393         fLeapMonthPatterns = NULL;
394         fLeapMonthPatternsCount = 0;
395     }
396     if (other.fShortYearNames != NULL) {
397         assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
398     } else {
399         fShortYearNames = NULL;
400         fShortYearNamesCount = 0;
401     }
402     if (other.fShortZodiacNames != NULL) {
403         assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
404     } else {
405         fShortZodiacNames = NULL;
406         fShortZodiacNamesCount = 0;
407     }
408 
409     if (other.fZoneStrings != NULL) {
410         fZoneStringsColCount = other.fZoneStringsColCount;
411         fZoneStringsRowCount = other.fZoneStringsRowCount;
412         createZoneStrings((const UnicodeString**)other.fZoneStrings);
413 
414     } else {
415         fZoneStrings = NULL;
416         fZoneStringsColCount = 0;
417         fZoneStringsRowCount = 0;
418     }
419     fZSFLocale = other.fZSFLocale;
420     // Other zone strings data is created on demand
421     fLocaleZoneStrings = NULL;
422 
423     // fastCopyFrom() - see assignArray comments
424     fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
425 
426     uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
427 }
428 
429 /**
430  * Assignment operator.
431  */
operator =(const DateFormatSymbols & other)432 DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
433 {
434     dispose();
435     copyData(other);
436 
437     return *this;
438 }
439 
~DateFormatSymbols()440 DateFormatSymbols::~DateFormatSymbols()
441 {
442     dispose();
443 }
444 
dispose()445 void DateFormatSymbols::dispose()
446 {
447     if (fEras)                      delete[] fEras;
448     if (fEraNames)                  delete[] fEraNames;
449     if (fNarrowEras)                delete[] fNarrowEras;
450     if (fMonths)                    delete[] fMonths;
451     if (fShortMonths)               delete[] fShortMonths;
452     if (fNarrowMonths)              delete[] fNarrowMonths;
453     if (fStandaloneMonths)          delete[] fStandaloneMonths;
454     if (fStandaloneShortMonths)     delete[] fStandaloneShortMonths;
455     if (fStandaloneNarrowMonths)    delete[] fStandaloneNarrowMonths;
456     if (fWeekdays)                  delete[] fWeekdays;
457     if (fShortWeekdays)             delete[] fShortWeekdays;
458     if (fShorterWeekdays)           delete[] fShorterWeekdays;
459     if (fNarrowWeekdays)            delete[] fNarrowWeekdays;
460     if (fStandaloneWeekdays)        delete[] fStandaloneWeekdays;
461     if (fStandaloneShortWeekdays)   delete[] fStandaloneShortWeekdays;
462     if (fStandaloneShorterWeekdays) delete[] fStandaloneShorterWeekdays;
463     if (fStandaloneNarrowWeekdays)  delete[] fStandaloneNarrowWeekdays;
464     if (fAmPms)                     delete[] fAmPms;
465     if (fNarrowAmPms)               delete[] fNarrowAmPms;
466     if (fQuarters)                  delete[] fQuarters;
467     if (fShortQuarters)             delete[] fShortQuarters;
468     if (fStandaloneQuarters)        delete[] fStandaloneQuarters;
469     if (fStandaloneShortQuarters)   delete[] fStandaloneShortQuarters;
470     if (fLeapMonthPatterns)         delete[] fLeapMonthPatterns;
471     if (fShortYearNames)            delete[] fShortYearNames;
472     if (fShortZodiacNames)          delete[] fShortZodiacNames;
473 
474     disposeZoneStrings();
475 }
476 
disposeZoneStrings()477 void DateFormatSymbols::disposeZoneStrings()
478 {
479     if (fZoneStrings) {
480         for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
481             delete[] fZoneStrings[row];
482         }
483         uprv_free(fZoneStrings);
484     }
485     if (fLocaleZoneStrings) {
486         for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
487             delete[] fLocaleZoneStrings[row];
488         }
489         uprv_free(fLocaleZoneStrings);
490     }
491 
492     fZoneStrings = NULL;
493     fLocaleZoneStrings = NULL;
494     fZoneStringsRowCount = 0;
495     fZoneStringsColCount = 0;
496 }
497 
498 UBool
arrayCompare(const UnicodeString * array1,const UnicodeString * array2,int32_t count)499 DateFormatSymbols::arrayCompare(const UnicodeString* array1,
500                                 const UnicodeString* array2,
501                                 int32_t count)
502 {
503     if (array1 == array2) return TRUE;
504     while (count>0)
505     {
506         --count;
507         if (array1[count] != array2[count]) return FALSE;
508     }
509     return TRUE;
510 }
511 
512 UBool
operator ==(const DateFormatSymbols & other) const513 DateFormatSymbols::operator==(const DateFormatSymbols& other) const
514 {
515     // First do cheap comparisons
516     if (this == &other) {
517         return TRUE;
518     }
519     if (fErasCount == other.fErasCount &&
520         fEraNamesCount == other.fEraNamesCount &&
521         fNarrowErasCount == other.fNarrowErasCount &&
522         fMonthsCount == other.fMonthsCount &&
523         fShortMonthsCount == other.fShortMonthsCount &&
524         fNarrowMonthsCount == other.fNarrowMonthsCount &&
525         fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
526         fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
527         fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
528         fWeekdaysCount == other.fWeekdaysCount &&
529         fShortWeekdaysCount == other.fShortWeekdaysCount &&
530         fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
531         fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
532         fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
533         fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
534         fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
535         fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
536         fAmPmsCount == other.fAmPmsCount &&
537         fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
538         fQuartersCount == other.fQuartersCount &&
539         fShortQuartersCount == other.fShortQuartersCount &&
540         fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
541         fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
542         fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
543         fShortYearNamesCount == other.fShortYearNamesCount &&
544         fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
545         (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
546     {
547         // Now compare the arrays themselves
548         if (arrayCompare(fEras, other.fEras, fErasCount) &&
549             arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
550             arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
551             arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
552             arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
553             arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
554             arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
555             arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
556             arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
557             arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
558             arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
559             arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
560             arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
561             arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
562             arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
563             arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
564             arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
565             arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
566             arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
567             fTimeSeparator == other.fTimeSeparator &&
568             arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
569             arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
570             arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
571             arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
572             arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
573             arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
574             arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount))
575         {
576             // Compare the contents of fZoneStrings
577             if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
578                 if (fZSFLocale == other.fZSFLocale) {
579                     return TRUE;
580                 }
581             } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
582                 if (fZoneStringsRowCount == other.fZoneStringsRowCount
583                     && fZoneStringsColCount == other.fZoneStringsColCount) {
584                     UBool cmpres = TRUE;
585                     for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
586                         cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
587                     }
588                     return cmpres;
589                 }
590             }
591             return FALSE;
592         }
593     }
594     return FALSE;
595 }
596 
597 //------------------------------------------------------
598 
599 const UnicodeString*
getEras(int32_t & count) const600 DateFormatSymbols::getEras(int32_t &count) const
601 {
602     count = fErasCount;
603     return fEras;
604 }
605 
606 const UnicodeString*
getEraNames(int32_t & count) const607 DateFormatSymbols::getEraNames(int32_t &count) const
608 {
609     count = fEraNamesCount;
610     return fEraNames;
611 }
612 
613 const UnicodeString*
getNarrowEras(int32_t & count) const614 DateFormatSymbols::getNarrowEras(int32_t &count) const
615 {
616     count = fNarrowErasCount;
617     return fNarrowEras;
618 }
619 
620 const UnicodeString*
getMonths(int32_t & count) const621 DateFormatSymbols::getMonths(int32_t &count) const
622 {
623     count = fMonthsCount;
624     return fMonths;
625 }
626 
627 const UnicodeString*
getShortMonths(int32_t & count) const628 DateFormatSymbols::getShortMonths(int32_t &count) const
629 {
630     count = fShortMonthsCount;
631     return fShortMonths;
632 }
633 
634 const UnicodeString*
getMonths(int32_t & count,DtContextType context,DtWidthType width) const635 DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
636 {
637     UnicodeString *returnValue = NULL;
638 
639     switch (context) {
640     case FORMAT :
641         switch(width) {
642         case WIDE :
643             count = fMonthsCount;
644             returnValue = fMonths;
645             break;
646         case ABBREVIATED :
647         case SHORT : // no month data for this, defaults to ABBREVIATED
648             count = fShortMonthsCount;
649             returnValue = fShortMonths;
650             break;
651         case NARROW :
652             count = fNarrowMonthsCount;
653             returnValue = fNarrowMonths;
654             break;
655         case DT_WIDTH_COUNT :
656             break;
657         }
658         break;
659     case STANDALONE :
660         switch(width) {
661         case WIDE :
662             count = fStandaloneMonthsCount;
663             returnValue = fStandaloneMonths;
664             break;
665         case ABBREVIATED :
666         case SHORT : // no month data for this, defaults to ABBREVIATED
667             count = fStandaloneShortMonthsCount;
668             returnValue = fStandaloneShortMonths;
669             break;
670         case NARROW :
671             count = fStandaloneNarrowMonthsCount;
672             returnValue = fStandaloneNarrowMonths;
673             break;
674         case DT_WIDTH_COUNT :
675             break;
676         }
677         break;
678     case DT_CONTEXT_COUNT :
679         break;
680     }
681     return returnValue;
682 }
683 
684 const UnicodeString*
getWeekdays(int32_t & count) const685 DateFormatSymbols::getWeekdays(int32_t &count) const
686 {
687     count = fWeekdaysCount;
688     return fWeekdays;
689 }
690 
691 const UnicodeString*
getShortWeekdays(int32_t & count) const692 DateFormatSymbols::getShortWeekdays(int32_t &count) const
693 {
694     count = fShortWeekdaysCount;
695     return fShortWeekdays;
696 }
697 
698 const UnicodeString*
getWeekdays(int32_t & count,DtContextType context,DtWidthType width) const699 DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
700 {
701     UnicodeString *returnValue = NULL;
702     switch (context) {
703     case FORMAT :
704         switch(width) {
705             case WIDE :
706                 count = fWeekdaysCount;
707                 returnValue = fWeekdays;
708                 break;
709             case ABBREVIATED :
710                 count = fShortWeekdaysCount;
711                 returnValue = fShortWeekdays;
712                 break;
713             case SHORT :
714                 count = fShorterWeekdaysCount;
715                 returnValue = fShorterWeekdays;
716                 break;
717             case NARROW :
718                 count = fNarrowWeekdaysCount;
719                 returnValue = fNarrowWeekdays;
720                 break;
721             case DT_WIDTH_COUNT :
722                 break;
723         }
724         break;
725     case STANDALONE :
726         switch(width) {
727             case WIDE :
728                 count = fStandaloneWeekdaysCount;
729                 returnValue = fStandaloneWeekdays;
730                 break;
731             case ABBREVIATED :
732                 count = fStandaloneShortWeekdaysCount;
733                 returnValue = fStandaloneShortWeekdays;
734                 break;
735             case SHORT :
736                 count = fStandaloneShorterWeekdaysCount;
737                 returnValue = fStandaloneShorterWeekdays;
738                 break;
739             case NARROW :
740                 count = fStandaloneNarrowWeekdaysCount;
741                 returnValue = fStandaloneNarrowWeekdays;
742                 break;
743             case DT_WIDTH_COUNT :
744                 break;
745         }
746         break;
747     case DT_CONTEXT_COUNT :
748         break;
749     }
750     return returnValue;
751 }
752 
753 const UnicodeString*
getQuarters(int32_t & count,DtContextType context,DtWidthType width) const754 DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
755 {
756     UnicodeString *returnValue = NULL;
757 
758     switch (context) {
759     case FORMAT :
760         switch(width) {
761         case WIDE :
762             count = fQuartersCount;
763             returnValue = fQuarters;
764             break;
765         case ABBREVIATED :
766         case SHORT : // no quarter data for this, defaults to ABBREVIATED
767             count = fShortQuartersCount;
768             returnValue = fShortQuarters;
769             break;
770         case NARROW :
771             count = 0;
772             returnValue = NULL;
773             break;
774         case DT_WIDTH_COUNT :
775             break;
776         }
777         break;
778     case STANDALONE :
779         switch(width) {
780         case WIDE :
781             count = fStandaloneQuartersCount;
782             returnValue = fStandaloneQuarters;
783             break;
784         case ABBREVIATED :
785         case SHORT : // no quarter data for this, defaults to ABBREVIATED
786             count = fStandaloneShortQuartersCount;
787             returnValue = fStandaloneShortQuarters;
788             break;
789         case NARROW :
790             count = 0;
791             returnValue = NULL;
792             break;
793         case DT_WIDTH_COUNT :
794             break;
795         }
796         break;
797     case DT_CONTEXT_COUNT :
798         break;
799     }
800     return returnValue;
801 }
802 
803 UnicodeString&
getTimeSeparatorString(UnicodeString & result) const804 DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
805 {
806     // fastCopyFrom() - see assignArray comments
807     return result.fastCopyFrom(fTimeSeparator);
808 }
809 
810 const UnicodeString*
getAmPmStrings(int32_t & count) const811 DateFormatSymbols::getAmPmStrings(int32_t &count) const
812 {
813     count = fAmPmsCount;
814     return fAmPms;
815 }
816 
817 const UnicodeString*
getLeapMonthPatterns(int32_t & count) const818 DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
819 {
820     count = fLeapMonthPatternsCount;
821     return fLeapMonthPatterns;
822 }
823 
824 const UnicodeString*
getYearNames(int32_t & count,DtContextType,DtWidthType) const825 DateFormatSymbols::getYearNames(int32_t& count,
826                                 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
827 {
828     count = fShortYearNamesCount;
829     return fShortYearNames;
830 }
831 
832 void
setYearNames(const UnicodeString * yearNames,int32_t count,DtContextType context,DtWidthType width)833 DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
834                                 DtContextType context, DtWidthType width)
835 {
836     if (context == FORMAT && width == ABBREVIATED) {
837         if (fShortYearNames) {
838             delete[] fShortYearNames;
839         }
840         fShortYearNames = newUnicodeStringArray(count);
841         uprv_arrayCopy(yearNames, fShortYearNames, count);
842         fShortYearNamesCount = count;
843     }
844 }
845 
846 const UnicodeString*
getZodiacNames(int32_t & count,DtContextType,DtWidthType) const847 DateFormatSymbols::getZodiacNames(int32_t& count,
848                                 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
849 {
850     count = fShortZodiacNamesCount;
851     return fShortZodiacNames;
852 }
853 
854 void
setZodiacNames(const UnicodeString * zodiacNames,int32_t count,DtContextType context,DtWidthType width)855 DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
856                                 DtContextType context, DtWidthType width)
857 {
858     if (context == FORMAT && width == ABBREVIATED) {
859         if (fShortZodiacNames) {
860             delete[] fShortZodiacNames;
861         }
862         fShortZodiacNames = newUnicodeStringArray(count);
863         uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
864         fShortZodiacNamesCount = count;
865     }
866 }
867 
868 //------------------------------------------------------
869 
870 void
setEras(const UnicodeString * erasArray,int32_t count)871 DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
872 {
873     // delete the old list if we own it
874     if (fEras)
875         delete[] fEras;
876 
877     // we always own the new list, which we create here (we duplicate rather
878     // than adopting the list passed in)
879     fEras = newUnicodeStringArray(count);
880     uprv_arrayCopy(erasArray,fEras,  count);
881     fErasCount = count;
882 }
883 
884 void
setEraNames(const UnicodeString * eraNamesArray,int32_t count)885 DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
886 {
887     // delete the old list if we own it
888     if (fEraNames)
889         delete[] fEraNames;
890 
891     // we always own the new list, which we create here (we duplicate rather
892     // than adopting the list passed in)
893     fEraNames = newUnicodeStringArray(count);
894     uprv_arrayCopy(eraNamesArray,fEraNames,  count);
895     fEraNamesCount = count;
896 }
897 
898 void
setNarrowEras(const UnicodeString * narrowErasArray,int32_t count)899 DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
900 {
901     // delete the old list if we own it
902     if (fNarrowEras)
903         delete[] fNarrowEras;
904 
905     // we always own the new list, which we create here (we duplicate rather
906     // than adopting the list passed in)
907     fNarrowEras = newUnicodeStringArray(count);
908     uprv_arrayCopy(narrowErasArray,fNarrowEras,  count);
909     fNarrowErasCount = count;
910 }
911 
912 void
setMonths(const UnicodeString * monthsArray,int32_t count)913 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
914 {
915     // delete the old list if we own it
916     if (fMonths)
917         delete[] fMonths;
918 
919     // we always own the new list, which we create here (we duplicate rather
920     // than adopting the list passed in)
921     fMonths = newUnicodeStringArray(count);
922     uprv_arrayCopy( monthsArray,fMonths,count);
923     fMonthsCount = count;
924 }
925 
926 void
setShortMonths(const UnicodeString * shortMonthsArray,int32_t count)927 DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
928 {
929     // delete the old list if we own it
930     if (fShortMonths)
931         delete[] fShortMonths;
932 
933     // we always own the new list, which we create here (we duplicate rather
934     // than adopting the list passed in)
935     fShortMonths = newUnicodeStringArray(count);
936     uprv_arrayCopy(shortMonthsArray,fShortMonths,  count);
937     fShortMonthsCount = count;
938 }
939 
940 void
setMonths(const UnicodeString * monthsArray,int32_t count,DtContextType context,DtWidthType width)941 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
942 {
943     // delete the old list if we own it
944     // we always own the new list, which we create here (we duplicate rather
945     // than adopting the list passed in)
946 
947     switch (context) {
948     case FORMAT :
949         switch (width) {
950         case WIDE :
951             if (fMonths)
952                 delete[] fMonths;
953             fMonths = newUnicodeStringArray(count);
954             uprv_arrayCopy( monthsArray,fMonths,count);
955             fMonthsCount = count;
956             break;
957         case ABBREVIATED :
958             if (fShortMonths)
959                 delete[] fShortMonths;
960             fShortMonths = newUnicodeStringArray(count);
961             uprv_arrayCopy( monthsArray,fShortMonths,count);
962             fShortMonthsCount = count;
963             break;
964         case NARROW :
965             if (fNarrowMonths)
966                 delete[] fNarrowMonths;
967             fNarrowMonths = newUnicodeStringArray(count);
968             uprv_arrayCopy( monthsArray,fNarrowMonths,count);
969             fNarrowMonthsCount = count;
970             break;
971         default :
972             break;
973         }
974         break;
975     case STANDALONE :
976         switch (width) {
977         case WIDE :
978             if (fStandaloneMonths)
979                 delete[] fStandaloneMonths;
980             fStandaloneMonths = newUnicodeStringArray(count);
981             uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
982             fStandaloneMonthsCount = count;
983             break;
984         case ABBREVIATED :
985             if (fStandaloneShortMonths)
986                 delete[] fStandaloneShortMonths;
987             fStandaloneShortMonths = newUnicodeStringArray(count);
988             uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
989             fStandaloneShortMonthsCount = count;
990             break;
991         case NARROW :
992            if (fStandaloneNarrowMonths)
993                 delete[] fStandaloneNarrowMonths;
994             fStandaloneNarrowMonths = newUnicodeStringArray(count);
995             uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
996             fStandaloneNarrowMonthsCount = count;
997             break;
998         default :
999             break;
1000         }
1001         break;
1002     case DT_CONTEXT_COUNT :
1003         break;
1004     }
1005 }
1006 
setWeekdays(const UnicodeString * weekdaysArray,int32_t count)1007 void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
1008 {
1009     // delete the old list if we own it
1010     if (fWeekdays)
1011         delete[] fWeekdays;
1012 
1013     // we always own the new list, which we create here (we duplicate rather
1014     // than adopting the list passed in)
1015     fWeekdays = newUnicodeStringArray(count);
1016     uprv_arrayCopy(weekdaysArray,fWeekdays,count);
1017     fWeekdaysCount = count;
1018 }
1019 
1020 void
setShortWeekdays(const UnicodeString * shortWeekdaysArray,int32_t count)1021 DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
1022 {
1023     // delete the old list if we own it
1024     if (fShortWeekdays)
1025         delete[] fShortWeekdays;
1026 
1027     // we always own the new list, which we create here (we duplicate rather
1028     // than adopting the list passed in)
1029     fShortWeekdays = newUnicodeStringArray(count);
1030     uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
1031     fShortWeekdaysCount = count;
1032 }
1033 
1034 void
setWeekdays(const UnicodeString * weekdaysArray,int32_t count,DtContextType context,DtWidthType width)1035 DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
1036 {
1037     // delete the old list if we own it
1038     // we always own the new list, which we create here (we duplicate rather
1039     // than adopting the list passed in)
1040 
1041     switch (context) {
1042     case FORMAT :
1043         switch (width) {
1044         case WIDE :
1045             if (fWeekdays)
1046                 delete[] fWeekdays;
1047             fWeekdays = newUnicodeStringArray(count);
1048             uprv_arrayCopy(weekdaysArray, fWeekdays, count);
1049             fWeekdaysCount = count;
1050             break;
1051         case ABBREVIATED :
1052             if (fShortWeekdays)
1053                 delete[] fShortWeekdays;
1054             fShortWeekdays = newUnicodeStringArray(count);
1055             uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
1056             fShortWeekdaysCount = count;
1057             break;
1058         case SHORT :
1059             if (fShorterWeekdays)
1060                 delete[] fShorterWeekdays;
1061             fShorterWeekdays = newUnicodeStringArray(count);
1062             uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
1063             fShorterWeekdaysCount = count;
1064             break;
1065         case NARROW :
1066             if (fNarrowWeekdays)
1067                 delete[] fNarrowWeekdays;
1068             fNarrowWeekdays = newUnicodeStringArray(count);
1069             uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
1070             fNarrowWeekdaysCount = count;
1071             break;
1072         case DT_WIDTH_COUNT :
1073             break;
1074         }
1075         break;
1076     case STANDALONE :
1077         switch (width) {
1078         case WIDE :
1079             if (fStandaloneWeekdays)
1080                 delete[] fStandaloneWeekdays;
1081             fStandaloneWeekdays = newUnicodeStringArray(count);
1082             uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
1083             fStandaloneWeekdaysCount = count;
1084             break;
1085         case ABBREVIATED :
1086             if (fStandaloneShortWeekdays)
1087                 delete[] fStandaloneShortWeekdays;
1088             fStandaloneShortWeekdays = newUnicodeStringArray(count);
1089             uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
1090             fStandaloneShortWeekdaysCount = count;
1091             break;
1092         case SHORT :
1093             if (fStandaloneShorterWeekdays)
1094                 delete[] fStandaloneShorterWeekdays;
1095             fStandaloneShorterWeekdays = newUnicodeStringArray(count);
1096             uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
1097             fStandaloneShorterWeekdaysCount = count;
1098             break;
1099         case NARROW :
1100             if (fStandaloneNarrowWeekdays)
1101                 delete[] fStandaloneNarrowWeekdays;
1102             fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
1103             uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
1104             fStandaloneNarrowWeekdaysCount = count;
1105             break;
1106         case DT_WIDTH_COUNT :
1107             break;
1108         }
1109         break;
1110     case DT_CONTEXT_COUNT :
1111         break;
1112     }
1113 }
1114 
1115 void
setQuarters(const UnicodeString * quartersArray,int32_t count,DtContextType context,DtWidthType width)1116 DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
1117 {
1118     // delete the old list if we own it
1119     // we always own the new list, which we create here (we duplicate rather
1120     // than adopting the list passed in)
1121 
1122     switch (context) {
1123     case FORMAT :
1124         switch (width) {
1125         case WIDE :
1126             if (fQuarters)
1127                 delete[] fQuarters;
1128             fQuarters = newUnicodeStringArray(count);
1129             uprv_arrayCopy( quartersArray,fQuarters,count);
1130             fQuartersCount = count;
1131             break;
1132         case ABBREVIATED :
1133             if (fShortQuarters)
1134                 delete[] fShortQuarters;
1135             fShortQuarters = newUnicodeStringArray(count);
1136             uprv_arrayCopy( quartersArray,fShortQuarters,count);
1137             fShortQuartersCount = count;
1138             break;
1139         case NARROW :
1140         /*
1141             if (fNarrowQuarters)
1142                 delete[] fNarrowQuarters;
1143             fNarrowQuarters = newUnicodeStringArray(count);
1144             uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1145             fNarrowQuartersCount = count;
1146         */
1147             break;
1148         default :
1149             break;
1150         }
1151         break;
1152     case STANDALONE :
1153         switch (width) {
1154         case WIDE :
1155             if (fStandaloneQuarters)
1156                 delete[] fStandaloneQuarters;
1157             fStandaloneQuarters = newUnicodeStringArray(count);
1158             uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1159             fStandaloneQuartersCount = count;
1160             break;
1161         case ABBREVIATED :
1162             if (fStandaloneShortQuarters)
1163                 delete[] fStandaloneShortQuarters;
1164             fStandaloneShortQuarters = newUnicodeStringArray(count);
1165             uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1166             fStandaloneShortQuartersCount = count;
1167             break;
1168         case NARROW :
1169         /*
1170            if (fStandaloneNarrowQuarters)
1171                 delete[] fStandaloneNarrowQuarters;
1172             fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1173             uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1174             fStandaloneNarrowQuartersCount = count;
1175         */
1176             break;
1177         default :
1178             break;
1179         }
1180         break;
1181     case DT_CONTEXT_COUNT :
1182         break;
1183     }
1184 }
1185 
1186 void
setAmPmStrings(const UnicodeString * amPmsArray,int32_t count)1187 DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1188 {
1189     // delete the old list if we own it
1190     if (fAmPms) delete[] fAmPms;
1191 
1192     // we always own the new list, which we create here (we duplicate rather
1193     // than adopting the list passed in)
1194     fAmPms = newUnicodeStringArray(count);
1195     uprv_arrayCopy(amPmsArray,fAmPms,count);
1196     fAmPmsCount = count;
1197 }
1198 
1199 void
setTimeSeparatorString(const UnicodeString & newTimeSeparator)1200 DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
1201 {
1202     fTimeSeparator = newTimeSeparator;
1203 }
1204 
1205 const UnicodeString**
getZoneStrings(int32_t & rowCount,int32_t & columnCount) const1206 DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1207 {
1208     const UnicodeString **result = NULL;
1209 
1210     umtx_lock(&LOCK);
1211     if (fZoneStrings == NULL) {
1212         if (fLocaleZoneStrings == NULL) {
1213             ((DateFormatSymbols*)this)->initZoneStringsArray();
1214         }
1215         result = (const UnicodeString**)fLocaleZoneStrings;
1216     } else {
1217         result = (const UnicodeString**)fZoneStrings;
1218     }
1219     rowCount = fZoneStringsRowCount;
1220     columnCount = fZoneStringsColCount;
1221     umtx_unlock(&LOCK);
1222 
1223     return result;
1224 }
1225 
1226 // For now, we include all zones
1227 #define ZONE_SET UCAL_ZONE_TYPE_ANY
1228 
1229 // This code must be called within a synchronized block
1230 void
initZoneStringsArray(void)1231 DateFormatSymbols::initZoneStringsArray(void) {
1232     if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
1233         return;
1234     }
1235 
1236     UErrorCode status = U_ZERO_ERROR;
1237 
1238     StringEnumeration *tzids = NULL;
1239     UnicodeString ** zarray = NULL;
1240     TimeZoneNames *tzNames = NULL;
1241     int32_t rows = 0;
1242 
1243     do { // dummy do-while
1244 
1245         tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
1246         rows = tzids->count(status);
1247         if (U_FAILURE(status)) {
1248             break;
1249         }
1250 
1251         // Allocate array
1252         int32_t size = rows * sizeof(UnicodeString*);
1253         zarray = (UnicodeString**)uprv_malloc(size);
1254         if (zarray == NULL) {
1255             status = U_MEMORY_ALLOCATION_ERROR;
1256             break;
1257         }
1258         uprv_memset(zarray, 0, size);
1259 
1260         tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1261 
1262         const UnicodeString *tzid;
1263         int32_t i = 0;
1264         UDate now = Calendar::getNow();
1265         UnicodeString tzDispName;
1266 
1267         while ((tzid = tzids->snext(status))) {
1268             if (U_FAILURE(status)) {
1269                 break;
1270             }
1271 
1272             zarray[i] = new UnicodeString[5];
1273             if (zarray[i] == NULL) {
1274                 status = U_MEMORY_ALLOCATION_ERROR;
1275                 break;
1276             }
1277 
1278             zarray[i][0].setTo(*tzid);
1279             zarray[i][1].setTo(tzNames->getDisplayName(*tzid, UTZNM_LONG_STANDARD, now, tzDispName));
1280             zarray[i][2].setTo(tzNames->getDisplayName(*tzid, UTZNM_SHORT_STANDARD, now, tzDispName));
1281             zarray[i][3].setTo(tzNames->getDisplayName(*tzid, UTZNM_LONG_DAYLIGHT, now, tzDispName));
1282             zarray[i][4].setTo(tzNames->getDisplayName(*tzid, UTZNM_SHORT_DAYLIGHT, now, tzDispName));
1283             i++;
1284         }
1285 
1286     } while (FALSE);
1287 
1288     if (U_FAILURE(status)) {
1289         if (zarray) {
1290             for (int32_t i = 0; i < rows; i++) {
1291                 if (zarray[i]) {
1292                     delete[] zarray[i];
1293                 }
1294             }
1295             uprv_free(zarray);
1296         }
1297     }
1298 
1299     if (tzNames) {
1300         delete tzNames;
1301     }
1302     if (tzids) {
1303         delete tzids;
1304     }
1305 
1306     fLocaleZoneStrings = zarray;
1307     fZoneStringsRowCount = rows;
1308     fZoneStringsColCount = 5;
1309 }
1310 
1311 void
setZoneStrings(const UnicodeString * const * strings,int32_t rowCount,int32_t columnCount)1312 DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1313 {
1314     // since deleting a 2-d array is a pain in the butt, we offload that task to
1315     // a separate function
1316     disposeZoneStrings();
1317     // we always own the new list, which we create here (we duplicate rather
1318     // than adopting the list passed in)
1319     fZoneStringsRowCount = rowCount;
1320     fZoneStringsColCount = columnCount;
1321     createZoneStrings((const UnicodeString**)strings);
1322 }
1323 
1324 //------------------------------------------------------
1325 
1326 const UChar * U_EXPORT2
getPatternUChars(void)1327 DateFormatSymbols::getPatternUChars(void)
1328 {
1329     return gPatternChars;
1330 }
1331 
1332 UDateFormatField U_EXPORT2
getPatternCharIndex(UChar c)1333 DateFormatSymbols::getPatternCharIndex(UChar c) {
1334     const UChar *p = u_strchr(gPatternChars, c);
1335     if (p == NULL) {
1336         return UDAT_FIELD_COUNT;
1337     } else {
1338         return static_cast<UDateFormatField>(p - gPatternChars);
1339     }
1340 }
1341 
1342 static const uint64_t kNumericFieldsAlways =
1343     ((uint64_t)1 << UDAT_YEAR_FIELD) |                      // y
1344     ((uint64_t)1 << UDAT_DATE_FIELD) |                      // d
1345     ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) |              // k
1346     ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) |              // H
1347     ((uint64_t)1 << UDAT_MINUTE_FIELD) |                    // m
1348     ((uint64_t)1 << UDAT_SECOND_FIELD) |                    // s
1349     ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) |         // S
1350     ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) |               // D
1351     ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) |      // F
1352     ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) |              // w
1353     ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) |             // W
1354     ((uint64_t)1 << UDAT_HOUR1_FIELD) |                     // h
1355     ((uint64_t)1 << UDAT_HOUR0_FIELD) |                     // K
1356     ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) |                  // Y
1357     ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) |             // u
1358     ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) |                // g
1359     ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) |       // A
1360     ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD);               // r
1361 
1362 static const uint64_t kNumericFieldsForCount12 =
1363     ((uint64_t)1 << UDAT_MONTH_FIELD) |                     // M or MM
1364     ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) |                 // e or ee
1365     ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) |            // c or cc
1366     ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) |          // L or LL
1367     ((uint64_t)1 << UDAT_QUARTER_FIELD) |                   // Q or QQ
1368     ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD);         // q or qq
1369 
1370 UBool U_EXPORT2
isNumericField(UDateFormatField f,int32_t count)1371 DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1372     if (f == UDAT_FIELD_COUNT) {
1373         return FALSE;
1374     }
1375     uint64_t flag = ((uint64_t)1 << f);
1376     return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1377 }
1378 
1379 UBool U_EXPORT2
isNumericPatternChar(UChar c,int32_t count)1380 DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1381     return isNumericField(getPatternCharIndex(c), count);
1382 }
1383 
1384 //------------------------------------------------------
1385 
1386 UnicodeString&
getLocalPatternChars(UnicodeString & result) const1387 DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1388 {
1389     // fastCopyFrom() - see assignArray comments
1390     return result.fastCopyFrom(fLocalPatternChars);
1391 }
1392 
1393 //------------------------------------------------------
1394 
1395 void
setLocalPatternChars(const UnicodeString & newLocalPatternChars)1396 DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1397 {
1398     fLocalPatternChars = newLocalPatternChars;
1399 }
1400 
1401 //------------------------------------------------------
1402 
1403 static void
initField(UnicodeString ** field,int32_t & length,const UResourceBundle * data,UErrorCode & status)1404 initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) {
1405     if (U_SUCCESS(status)) {
1406         int32_t strLen = 0;
1407         length = ures_getSize(data);
1408         *field = newUnicodeStringArray(length);
1409         if (*field) {
1410             for(int32_t i = 0; i<length; i++) {
1411                 const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status);
1412                 // setTo() - see assignArray comments
1413                 (*(field)+i)->setTo(TRUE, resStr, strLen);
1414             }
1415         }
1416         else {
1417             length = 0;
1418             status = U_MEMORY_ALLOCATION_ERROR;
1419         }
1420     }
1421 }
1422 
1423 static void
initField(UnicodeString ** field,int32_t & length,const UChar * data,LastResortSize numStr,LastResortSize strLen,UErrorCode & status)1424 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1425     if (U_SUCCESS(status)) {
1426         length = numStr;
1427         *field = newUnicodeStringArray((size_t)numStr);
1428         if (*field) {
1429             for(int32_t i = 0; i<length; i++) {
1430                 // readonly aliases - all "data" strings are constant
1431                 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1432                 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1433             }
1434         }
1435         else {
1436             length = 0;
1437             status = U_MEMORY_ALLOCATION_ERROR;
1438         }
1439     }
1440 }
1441 
1442 static void
initLeapMonthPattern(UnicodeString * field,int32_t index,const UResourceBundle * data,UErrorCode & status)1443 initLeapMonthPattern(UnicodeString *field, int32_t index, const UResourceBundle *data, UErrorCode &status) {
1444     field[index].remove();
1445     if (U_SUCCESS(status)) {
1446         int32_t strLen = 0;
1447         const UChar *resStr = ures_getStringByKey(data, gNamesLeapTag, &strLen, &status);
1448         if (U_SUCCESS(status)) {
1449             field[index].setTo(TRUE, resStr, strLen);
1450         }
1451     }
1452     status = U_ZERO_ERROR;
1453 }
1454 
1455 typedef struct {
1456     const char * usageTypeName;
1457     DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1458 } ContextUsageTypeNameToEnumValue;
1459 
1460 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1461    // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1462     { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1463     { "day-narrow",     DateFormatSymbols::kCapContextUsageDayNarrow },
1464     { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1465     { "era-abbr",       DateFormatSymbols::kCapContextUsageEraAbbrev },
1466     { "era-name",       DateFormatSymbols::kCapContextUsageEraWide },
1467     { "era-narrow",     DateFormatSymbols::kCapContextUsageEraNarrow },
1468     { "metazone-long",  DateFormatSymbols::kCapContextUsageMetazoneLong },
1469     { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1470     { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1471     { "month-narrow",   DateFormatSymbols::kCapContextUsageMonthNarrow },
1472     { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1473     { "zone-long",      DateFormatSymbols::kCapContextUsageZoneLong },
1474     { "zone-short",     DateFormatSymbols::kCapContextUsageZoneShort },
1475     { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1476 };
1477 
1478 void
initializeData(const Locale & locale,const char * type,UErrorCode & status,UBool useLastResortData)1479 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
1480 {
1481     int32_t i;
1482     int32_t len = 0;
1483     const UChar *resStr;
1484     /* In case something goes wrong, initialize all of the data to NULL. */
1485     fEras = NULL;
1486     fErasCount = 0;
1487     fEraNames = NULL;
1488     fEraNamesCount = 0;
1489     fNarrowEras = NULL;
1490     fNarrowErasCount = 0;
1491     fMonths = NULL;
1492     fMonthsCount=0;
1493     fShortMonths = NULL;
1494     fShortMonthsCount=0;
1495     fNarrowMonths = NULL;
1496     fNarrowMonthsCount=0;
1497     fStandaloneMonths = NULL;
1498     fStandaloneMonthsCount=0;
1499     fStandaloneShortMonths = NULL;
1500     fStandaloneShortMonthsCount=0;
1501     fStandaloneNarrowMonths = NULL;
1502     fStandaloneNarrowMonthsCount=0;
1503     fWeekdays = NULL;
1504     fWeekdaysCount=0;
1505     fShortWeekdays = NULL;
1506     fShortWeekdaysCount=0;
1507     fShorterWeekdays = NULL;
1508     fShorterWeekdaysCount=0;
1509     fNarrowWeekdays = NULL;
1510     fNarrowWeekdaysCount=0;
1511     fStandaloneWeekdays = NULL;
1512     fStandaloneWeekdaysCount=0;
1513     fStandaloneShortWeekdays = NULL;
1514     fStandaloneShortWeekdaysCount=0;
1515     fStandaloneShorterWeekdays = NULL;
1516     fStandaloneShorterWeekdaysCount=0;
1517     fStandaloneNarrowWeekdays = NULL;
1518     fStandaloneNarrowWeekdaysCount=0;
1519     fAmPms = NULL;
1520     fAmPmsCount=0;
1521     fNarrowAmPms = NULL;
1522     fNarrowAmPmsCount=0;
1523     fTimeSeparator.setToBogus();
1524     fQuarters = NULL;
1525     fQuartersCount = 0;
1526     fShortQuarters = NULL;
1527     fShortQuartersCount = 0;
1528     fStandaloneQuarters = NULL;
1529     fStandaloneQuartersCount = 0;
1530     fStandaloneShortQuarters = NULL;
1531     fStandaloneShortQuartersCount = 0;
1532     fLeapMonthPatterns = NULL;
1533     fLeapMonthPatternsCount = 0;
1534     fShortYearNames = NULL;
1535     fShortYearNamesCount = 0;
1536     fShortZodiacNames = NULL;
1537     fShortZodiacNamesCount = 0;
1538     fZoneStringsRowCount = 0;
1539     fZoneStringsColCount = 0;
1540     fZoneStrings = NULL;
1541     fLocaleZoneStrings = NULL;
1542     uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
1543 
1544     // We need to preserve the requested locale for
1545     // lazy ZoneStringFormat instantiation.  ZoneStringFormat
1546     // is region sensitive, thus, bundle locale bundle's locale
1547     // is not sufficient.
1548     fZSFLocale = locale;
1549 
1550     if (U_FAILURE(status)) return;
1551 
1552     /**
1553      * Retrieve the string arrays we need from the resource bundle file.
1554      * We cast away const here, but that's okay; we won't delete any of
1555      * these.
1556      */
1557     CalendarData calData(locale, type, status);
1558 
1559     // load the first data item
1560     UResourceBundle *erasMain = calData.getByKey(gErasTag, status);
1561     UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1562     UErrorCode oldStatus = status;
1563     UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status);
1564     if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3
1565        status = oldStatus;
1566        eraNames = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1567     }
1568     // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
1569     oldStatus = status;
1570     UResourceBundle *narrowEras = ures_getByKeyWithFallback(erasMain, gNamesNarrowTag, NULL, &status);
1571     if ( status == U_MISSING_RESOURCE_ERROR ) {
1572        status = oldStatus;
1573        narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status);
1574     }
1575 
1576     UErrorCode tempStatus = U_ZERO_ERROR;
1577     UResourceBundle *monthPatterns = calData.getByKey(gMonthPatternsTag, tempStatus);
1578     if (U_SUCCESS(tempStatus) && monthPatterns != NULL) {
1579         fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
1580         if (fLeapMonthPatterns) {
1581             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calData.getByKey2(gMonthPatternsTag, gNamesWideTag, tempStatus), tempStatus);
1582             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calData.getByKey2(gMonthPatternsTag, gNamesAbbrTag, tempStatus), tempStatus);
1583             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calData.getByKey2(gMonthPatternsTag, gNamesNarrowTag, tempStatus), tempStatus);
1584             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
1585             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
1586             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calData.getByKey3(gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
1587             initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calData.getByKey3(gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
1588             if (U_SUCCESS(tempStatus)) {
1589                 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
1590                 // The ordering of the following statements is important.
1591                 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
1592                     fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
1593                 };
1594                 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
1595                     fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
1596                 };
1597                 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
1598                     fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
1599                 };
1600                 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
1601                     fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
1602                 };
1603                 // end of hack
1604                 fLeapMonthPatternsCount = kMonthPatternsCount;
1605             } else {
1606                 delete[] fLeapMonthPatterns;
1607                 fLeapMonthPatterns = NULL;
1608             }
1609         }
1610     }
1611 
1612     tempStatus = U_ZERO_ERROR;
1613     UResourceBundle *cyclicNameSets= calData.getByKey(gCyclicNameSetsTag, tempStatus);
1614     if (U_SUCCESS(tempStatus) && cyclicNameSets != NULL) {
1615         UResourceBundle *nameSetYears = ures_getByKeyWithFallback(cyclicNameSets, gNameSetYearsTag, NULL, &tempStatus);
1616         if (U_SUCCESS(tempStatus)) {
1617             UResourceBundle *nameSetYearsFmt = ures_getByKeyWithFallback(nameSetYears, gNamesFormatTag, NULL, &tempStatus);
1618             if (U_SUCCESS(tempStatus)) {
1619                 UResourceBundle *nameSetYearsFmtAbbrev = ures_getByKeyWithFallback(nameSetYearsFmt, gNamesAbbrTag, NULL, &tempStatus);
1620                 if (U_SUCCESS(tempStatus)) {
1621                     initField(&fShortYearNames, fShortYearNamesCount, nameSetYearsFmtAbbrev, tempStatus);
1622                     ures_close(nameSetYearsFmtAbbrev);
1623                 }
1624                 ures_close(nameSetYearsFmt);
1625             }
1626             ures_close(nameSetYears);
1627         }
1628         UResourceBundle *nameSetZodiacs = ures_getByKeyWithFallback(cyclicNameSets, gNameSetZodiacsTag, NULL, &tempStatus);
1629         if (U_SUCCESS(tempStatus)) {
1630             UResourceBundle *nameSetZodiacsFmt = ures_getByKeyWithFallback(nameSetZodiacs, gNamesFormatTag, NULL, &tempStatus);
1631             if (U_SUCCESS(tempStatus)) {
1632                 UResourceBundle *nameSetZodiacsFmtAbbrev = ures_getByKeyWithFallback(nameSetZodiacsFmt, gNamesAbbrTag, NULL, &tempStatus);
1633                 if (U_SUCCESS(tempStatus)) {
1634                     initField(&fShortZodiacNames, fShortZodiacNamesCount, nameSetZodiacsFmtAbbrev, tempStatus);
1635                     ures_close(nameSetZodiacsFmtAbbrev);
1636                 }
1637                 ures_close(nameSetZodiacsFmt);
1638             }
1639             ures_close(nameSetZodiacs);
1640         }
1641     }
1642 
1643     tempStatus = U_ZERO_ERROR;
1644     UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
1645     if (U_SUCCESS(tempStatus)) {
1646         UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
1647         if (U_SUCCESS(tempStatus)) {
1648             UResourceBundle *contextTransformUsage;
1649             while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
1650                 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
1651                 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
1652                     const char* usageType = ures_getKey(contextTransformUsage);
1653                     if (usageType != NULL) {
1654                         const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
1655                         int32_t compResult = 0;
1656                         // linear search; list is short and we cannot be sure that bsearch is available
1657                         while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
1658                             ++typeMapPtr;
1659                         }
1660                         if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
1661                             fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0];
1662                             fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1];
1663                         }
1664                     }
1665                 }
1666                 tempStatus = U_ZERO_ERROR;
1667                 ures_close(contextTransformUsage);
1668             }
1669             ures_close(contextTransforms);
1670         }
1671 
1672         tempStatus = U_ZERO_ERROR;
1673         const LocalPointer<NumberingSystem> numberingSystem(
1674                 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
1675         if (U_SUCCESS(tempStatus)) {
1676             // These functions all fail gracefully if passed NULL pointers and
1677             // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
1678             // to check for errors once after all calls are made.
1679             const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
1680                     localeBundle, gNumberElementsTag, NULL, &tempStatus));
1681             const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
1682                     numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
1683             const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
1684                     nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
1685             fTimeSeparator = ures_getUnicodeStringByKey(
1686                     symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
1687             if (U_FAILURE(tempStatus)) {
1688                 fTimeSeparator.setToBogus();
1689             }
1690         }
1691 
1692         ures_close(localeBundle);
1693     }
1694 
1695     if (fTimeSeparator.isBogus()) {
1696         fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
1697     }
1698 
1699     UResourceBundle *weekdaysData = NULL; // Data closed by calData
1700     UResourceBundle *abbrWeekdaysData = NULL; // Data closed by calData
1701     UResourceBundle *shorterWeekdaysData = NULL; // Data closed by calData
1702     UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData
1703     UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData
1704     UResourceBundle *standaloneAbbrWeekdaysData = NULL; // Data closed by calData
1705     UResourceBundle *standaloneShorterWeekdaysData = NULL; // Data closed by calData
1706     UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData
1707 
1708     U_LOCALE_BASED(locBased, *this);
1709     if (U_FAILURE(status))
1710     {
1711         if (useLastResortData)
1712         {
1713             // Handle the case in which there is no resource data present.
1714             // We don't have to generate usable patterns in this situation;
1715             // we just need to produce something that will be semi-intelligible
1716             // in most locales.
1717 
1718             status = U_USING_FALLBACK_WARNING;
1719 
1720             initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1721             initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1722             initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
1723             initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
1724             initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1725             initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1726             initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen,  status);
1727             initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1728             initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
1729             initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1730             initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1731             initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1732             initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1733             initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1734             initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1735             initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1736             initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
1737             initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
1738             initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
1739             initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1740             initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1741             initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1742             initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
1743             fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1744         }
1745         goto cleanup;
1746     }
1747 
1748     // if we make it to here, the resource data is cool, and we can get everything out
1749     // of it that we need except for the time-zone and localized-pattern data, which
1750     // are stored in a separate file
1751     locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status),
1752                           ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status));
1753 
1754     initField(&fEras, fErasCount, eras, status);
1755     initField(&fEraNames, fEraNamesCount, eraNames, status);
1756     initField(&fNarrowEras, fNarrowErasCount, narrowEras, status);
1757 
1758     initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1759     initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1760 
1761     initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1762     if(status == U_MISSING_RESOURCE_ERROR) {
1763         status = U_ZERO_ERROR;
1764         initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1765     }
1766     if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */
1767        status = U_ZERO_ERROR;
1768        initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1769     }
1770 
1771     initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1772     if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */
1773        status = U_ZERO_ERROR;
1774        initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status);
1775     }
1776     initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1777     if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/abbreviated not available, use format/abbreviated */
1778        status = U_ZERO_ERROR;
1779        initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1780     }
1781     initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
1782     if ( status == U_MISSING_RESOURCE_ERROR ) { /* if standalone/narrow not availabe, try format/narrow */
1783        status = U_ZERO_ERROR;
1784        initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status);
1785        if ( status == U_MISSING_RESOURCE_ERROR ) { /* if still not there, use format/abbreviated */
1786           status = U_ZERO_ERROR;
1787           initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status);
1788        }
1789     }
1790     initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status);
1791     initField(&fNarrowAmPms, fNarrowAmPmsCount, calData.getByKey(gAmPmMarkersNarrowTag, status), status);
1792 
1793     initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1794     initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1795 
1796     initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
1797     if(status == U_MISSING_RESOURCE_ERROR) {
1798         status = U_ZERO_ERROR;
1799         initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status);
1800     }
1801 
1802     initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
1803     if(status == U_MISSING_RESOURCE_ERROR) {
1804         status = U_ZERO_ERROR;
1805         initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status);
1806     }
1807 
1808     // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
1809     /*
1810     // fastCopyFrom()/setTo() - see assignArray comments
1811     resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
1812     fLocalPatternChars.setTo(TRUE, resStr, len);
1813     // If the locale data does not include new pattern chars, use the defaults
1814     // TODO: Consider making this an error, since this may add conflicting characters.
1815     if (len < PATTERN_CHARS_LEN) {
1816         fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
1817     }
1818     */
1819     fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
1820 
1821     // Format wide weekdays -> fWeekdays
1822     // {sfb} fixed to handle 1-based weekdays
1823     weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1824     fWeekdaysCount = ures_getSize(weekdaysData);
1825     fWeekdays = new UnicodeString[fWeekdaysCount+1];
1826     /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/
1827     if (fWeekdays == NULL) {
1828         status = U_MEMORY_ALLOCATION_ERROR;
1829         goto cleanup;
1830     }
1831     // leave fWeekdays[0] empty
1832     for(i = 0; i<fWeekdaysCount; i++) {
1833         resStr = ures_getStringByIndex(weekdaysData, i, &len, &status);
1834         // setTo() - see assignArray comments
1835         fWeekdays[i+1].setTo(TRUE, resStr, len);
1836     }
1837     fWeekdaysCount++;
1838 
1839     // Format abbreviated weekdays -> fShortWeekdays
1840     abbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1841     fShortWeekdaysCount = ures_getSize(abbrWeekdaysData);
1842     fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1];
1843     /* test for NULL */
1844     if (fShortWeekdays == 0) {
1845         status = U_MEMORY_ALLOCATION_ERROR;
1846         goto cleanup;
1847     }
1848     // leave fShortWeekdays[0] empty
1849     for(i = 0; i<fShortWeekdaysCount; i++) {
1850         resStr = ures_getStringByIndex(abbrWeekdaysData, i, &len, &status);
1851         // setTo() - see assignArray comments
1852         fShortWeekdays[i+1].setTo(TRUE, resStr, len);
1853     }
1854     fShortWeekdaysCount++;
1855 
1856    // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
1857     shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesShortTag, status);
1858     if ( status == U_MISSING_RESOURCE_ERROR ) {
1859        status = U_ZERO_ERROR;
1860        shorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1861     }
1862     fShorterWeekdaysCount = ures_getSize(shorterWeekdaysData);
1863     fShorterWeekdays = new UnicodeString[fShorterWeekdaysCount+1];
1864     /* test for NULL */
1865     if (fShorterWeekdays == 0) {
1866         status = U_MEMORY_ALLOCATION_ERROR;
1867         goto cleanup;
1868     }
1869     // leave fShorterWeekdays[0] empty
1870     for(i = 0; i<fShorterWeekdaysCount; i++) {
1871         resStr = ures_getStringByIndex(shorterWeekdaysData, i, &len, &status);
1872         // setTo() - see assignArray comments
1873         fShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1874     }
1875     fShorterWeekdaysCount++;
1876 
1877    // Format narrow weekdays -> fNarrowWeekdays
1878     narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1879     if(status == U_MISSING_RESOURCE_ERROR) {
1880         status = U_ZERO_ERROR;
1881         narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1882     }
1883     if ( status == U_MISSING_RESOURCE_ERROR ) {
1884        status = U_ZERO_ERROR;
1885        narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1886     }
1887     fNarrowWeekdaysCount = ures_getSize(narrowWeekdaysData);
1888     fNarrowWeekdays = new UnicodeString[fNarrowWeekdaysCount+1];
1889     /* test for NULL */
1890     if (fNarrowWeekdays == 0) {
1891         status = U_MEMORY_ALLOCATION_ERROR;
1892         goto cleanup;
1893     }
1894     // leave fNarrowWeekdays[0] empty
1895     for(i = 0; i<fNarrowWeekdaysCount; i++) {
1896         resStr = ures_getStringByIndex(narrowWeekdaysData, i, &len, &status);
1897         // setTo() - see assignArray comments
1898         fNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1899     }
1900     fNarrowWeekdaysCount++;
1901 
1902    // Stand-alone wide weekdays -> fStandaloneWeekdays
1903     standaloneWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status);
1904     if ( status == U_MISSING_RESOURCE_ERROR ) {
1905        status = U_ZERO_ERROR;
1906        standaloneWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status);
1907     }
1908     fStandaloneWeekdaysCount = ures_getSize(standaloneWeekdaysData);
1909     fStandaloneWeekdays = new UnicodeString[fStandaloneWeekdaysCount+1];
1910     /* test for NULL */
1911     if (fStandaloneWeekdays == 0) {
1912         status = U_MEMORY_ALLOCATION_ERROR;
1913         goto cleanup;
1914     }
1915     // leave fStandaloneWeekdays[0] empty
1916     for(i = 0; i<fStandaloneWeekdaysCount; i++) {
1917         resStr = ures_getStringByIndex(standaloneWeekdaysData, i, &len, &status);
1918         // setTo() - see assignArray comments
1919         fStandaloneWeekdays[i+1].setTo(TRUE, resStr, len);
1920     }
1921     fStandaloneWeekdaysCount++;
1922 
1923    // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
1924     standaloneAbbrWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status);
1925     if ( status == U_MISSING_RESOURCE_ERROR ) {
1926        status = U_ZERO_ERROR;
1927        standaloneAbbrWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1928     }
1929     fStandaloneShortWeekdaysCount = ures_getSize(standaloneAbbrWeekdaysData);
1930     fStandaloneShortWeekdays = new UnicodeString[fStandaloneShortWeekdaysCount+1];
1931     /* test for NULL */
1932     if (fStandaloneShortWeekdays == 0) {
1933         status = U_MEMORY_ALLOCATION_ERROR;
1934         goto cleanup;
1935     }
1936     // leave fStandaloneShortWeekdays[0] empty
1937     for(i = 0; i<fStandaloneShortWeekdaysCount; i++) {
1938         resStr = ures_getStringByIndex(standaloneAbbrWeekdaysData, i, &len, &status);
1939         // setTo() - see assignArray comments
1940         fStandaloneShortWeekdays[i+1].setTo(TRUE, resStr, len);
1941     }
1942     fStandaloneShortWeekdaysCount++;
1943 
1944     // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
1945     standaloneShorterWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status);
1946     if ( status == U_MISSING_RESOURCE_ERROR ) {
1947        status = U_ZERO_ERROR;
1948        standaloneShorterWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1949     }
1950     fStandaloneShorterWeekdaysCount = ures_getSize(standaloneShorterWeekdaysData);
1951     fStandaloneShorterWeekdays = new UnicodeString[fStandaloneShorterWeekdaysCount+1];
1952     /* test for NULL */
1953     if (fStandaloneShorterWeekdays == 0) {
1954         status = U_MEMORY_ALLOCATION_ERROR;
1955         goto cleanup;
1956     }
1957     // leave fStandaloneShorterWeekdays[0] empty
1958     for(i = 0; i<fStandaloneShorterWeekdaysCount; i++) {
1959         resStr = ures_getStringByIndex(standaloneShorterWeekdaysData, i, &len, &status);
1960         // setTo() - see assignArray comments
1961         fStandaloneShorterWeekdays[i+1].setTo(TRUE, resStr, len);
1962     }
1963     fStandaloneShorterWeekdaysCount++;
1964 
1965     // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
1966     standaloneNarrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status);
1967     if ( status == U_MISSING_RESOURCE_ERROR ) {
1968        status = U_ZERO_ERROR;
1969        standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status);
1970        if ( status == U_MISSING_RESOURCE_ERROR ) {
1971           status = U_ZERO_ERROR;
1972           standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status);
1973        }
1974     }
1975     fStandaloneNarrowWeekdaysCount = ures_getSize(standaloneNarrowWeekdaysData);
1976     fStandaloneNarrowWeekdays = new UnicodeString[fStandaloneNarrowWeekdaysCount+1];
1977     /* test for NULL */
1978     if (fStandaloneNarrowWeekdays == 0) {
1979         status = U_MEMORY_ALLOCATION_ERROR;
1980         goto cleanup;
1981     }
1982     // leave fStandaloneNarrowWeekdays[0] empty
1983     for(i = 0; i<fStandaloneNarrowWeekdaysCount; i++) {
1984         resStr = ures_getStringByIndex(standaloneNarrowWeekdaysData, i, &len, &status);
1985         // setTo() - see assignArray comments
1986         fStandaloneNarrowWeekdays[i+1].setTo(TRUE, resStr, len);
1987     }
1988     fStandaloneNarrowWeekdaysCount++;
1989 
1990 cleanup:
1991     ures_close(eras);
1992     ures_close(eraNames);
1993     ures_close(narrowEras);
1994 }
1995 
1996 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const1997 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
1998     U_LOCALE_BASED(locBased, *this);
1999     return locBased.getLocale(type, status);
2000 }
2001 
2002 U_NAMESPACE_END
2003 
2004 #endif /* #if !UCONFIG_NO_FORMATTING */
2005 
2006 //eof
2007