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