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