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