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