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