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