1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 * Copyright (C) 1997-2016, International Business Machines Corporation and *
6 * others. All Rights Reserved. *
7 *******************************************************************************
8 *
9 * File DTFMTSYM.CPP
10 *
11 * Modification History:
12 *
13 * Date Name Description
14 * 02/19/97 aliu Converted from java.
15 * 07/21/98 stephen Added getZoneIndex
16 * Changed weekdays/short weekdays to be one-based
17 * 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix
18 * 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars
19 * 03/27/00 weiv Keeping resource bundle around!
20 * 06/30/05 emmons Added eraNames, narrow month/day, standalone context
21 * 10/12/05 emmons Added setters for eraNames, month/day by width/context
22 *******************************************************************************
23 */
24
25 #include <utility>
26
27 #include "unicode/utypes.h"
28
29 #if !UCONFIG_NO_FORMATTING
30 #include "unicode/ustring.h"
31 #include "unicode/localpointer.h"
32 #include "unicode/dtfmtsym.h"
33 #include "unicode/smpdtfmt.h"
34 #include "unicode/msgfmt.h"
35 #include "unicode/numsys.h"
36 #include "unicode/tznames.h"
37 #include "cpputils.h"
38 #include "umutex.h"
39 #include "cmemory.h"
40 #include "cstring.h"
41 #include "charstr.h"
42 #include "dt_impl.h"
43 #include "locbased.h"
44 #include "gregoimp.h"
45 #include "hash.h"
46 #include "uassert.h"
47 #include "uresimp.h"
48 #include "ureslocs.h"
49 #include "uvector.h"
50 #include "shareddateformatsymbols.h"
51 #include "unicode/calendar.h"
52 #include "unifiedcache.h"
53
54 // *****************************************************************************
55 // class DateFormatSymbols
56 // *****************************************************************************
57
58 /**
59 * These are static arrays we use only in the case where we have no
60 * resource data.
61 */
62
63 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
64 #define PATTERN_CHARS_LEN 38
65 #else
66 #define PATTERN_CHARS_LEN 37
67 #endif
68
69 /**
70 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All
71 * locales use the same these unlocalized pattern characters.
72 */
73 static const UChar gPatternChars[] = {
74 // if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR:
75 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:
76 // else:
77 // GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB
78
79 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45,
80 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65,
81 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56,
82 0x55, 0x4F, 0x58, 0x78, 0x72, 0x62, 0x42,
83 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
84 0x3a,
85 #endif
86 0
87 };
88
89 //------------------------------------------------------
90 // Strings of last resort. These are only used if we have no resource
91 // files. They aren't designed for actual use, just for backup.
92
93 // These are the month names and abbreviations of last resort.
94 static const UChar gLastResortMonthNames[13][3] =
95 {
96 {0x0030, 0x0031, 0x0000}, /* "01" */
97 {0x0030, 0x0032, 0x0000}, /* "02" */
98 {0x0030, 0x0033, 0x0000}, /* "03" */
99 {0x0030, 0x0034, 0x0000}, /* "04" */
100 {0x0030, 0x0035, 0x0000}, /* "05" */
101 {0x0030, 0x0036, 0x0000}, /* "06" */
102 {0x0030, 0x0037, 0x0000}, /* "07" */
103 {0x0030, 0x0038, 0x0000}, /* "08" */
104 {0x0030, 0x0039, 0x0000}, /* "09" */
105 {0x0031, 0x0030, 0x0000}, /* "10" */
106 {0x0031, 0x0031, 0x0000}, /* "11" */
107 {0x0031, 0x0032, 0x0000}, /* "12" */
108 {0x0031, 0x0033, 0x0000} /* "13" */
109 };
110
111 // These are the weekday names and abbreviations of last resort.
112 static const UChar gLastResortDayNames[8][2] =
113 {
114 {0x0030, 0x0000}, /* "0" */
115 {0x0031, 0x0000}, /* "1" */
116 {0x0032, 0x0000}, /* "2" */
117 {0x0033, 0x0000}, /* "3" */
118 {0x0034, 0x0000}, /* "4" */
119 {0x0035, 0x0000}, /* "5" */
120 {0x0036, 0x0000}, /* "6" */
121 {0x0037, 0x0000} /* "7" */
122 };
123
124 // These are the quarter names and abbreviations of last resort.
125 static const UChar gLastResortQuarters[4][2] =
126 {
127 {0x0031, 0x0000}, /* "1" */
128 {0x0032, 0x0000}, /* "2" */
129 {0x0033, 0x0000}, /* "3" */
130 {0x0034, 0x0000}, /* "4" */
131 };
132
133 // These are the am/pm and BC/AD markers of last resort.
134 static const UChar gLastResortAmPmMarkers[2][3] =
135 {
136 {0x0041, 0x004D, 0x0000}, /* "AM" */
137 {0x0050, 0x004D, 0x0000} /* "PM" */
138 };
139
140 static const UChar gLastResortEras[2][3] =
141 {
142 {0x0042, 0x0043, 0x0000}, /* "BC" */
143 {0x0041, 0x0044, 0x0000} /* "AD" */
144 };
145
146 /* Sizes for the last resort string arrays */
147 typedef enum LastResortSize {
148 kMonthNum = 13,
149 kMonthLen = 3,
150
151 kDayNum = 8,
152 kDayLen = 2,
153
154 kAmPmNum = 2,
155 kAmPmLen = 3,
156
157 kQuarterNum = 4,
158 kQuarterLen = 2,
159
160 kEraNum = 2,
161 kEraLen = 3,
162
163 kZoneNum = 5,
164 kZoneLen = 4,
165
166 kGmtHourNum = 4,
167 kGmtHourLen = 10
168 } LastResortSize;
169
170 U_NAMESPACE_BEGIN
171
~SharedDateFormatSymbols()172 SharedDateFormatSymbols::~SharedDateFormatSymbols() {
173 }
174
175 template<> U_I18N_API
176 const SharedDateFormatSymbols *
createObject(const void *,UErrorCode & status) const177 LocaleCacheKey<SharedDateFormatSymbols>::createObject(
178 const void * /*unusedContext*/, UErrorCode &status) const {
179 char type[256];
180 Calendar::getCalendarTypeFromLocale(fLoc, type, UPRV_LENGTHOF(type), status);
181 if (U_FAILURE(status)) {
182 return NULL;
183 }
184 SharedDateFormatSymbols *shared
185 = new SharedDateFormatSymbols(fLoc, type, status);
186 if (shared == NULL) {
187 status = U_MEMORY_ALLOCATION_ERROR;
188 return NULL;
189 }
190 if (U_FAILURE(status)) {
191 delete shared;
192 return NULL;
193 }
194 shared->addRef();
195 return shared;
196 }
197
198 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols)
199
200 #define kSUPPLEMENTAL "supplementalData"
201
202 /**
203 * These are the tags we expect to see in normal resource bundle files associated
204 * with a locale and calendar
205 */
206 static const char gCalendarTag[]="calendar";
207 static const char gGregorianTag[]="gregorian";
208 static const char gErasTag[]="eras";
209 static const char gCyclicNameSetsTag[]="cyclicNameSets";
210 static const char gNameSetYearsTag[]="years";
211 static const char gNameSetZodiacsTag[]="zodiacs";
212 static const char gMonthNamesTag[]="monthNames";
213 static const char gMonthPatternsTag[]="monthPatterns";
214 static const char gDayNamesTag[]="dayNames";
215 static const char gNamesWideTag[]="wide";
216 static const char gNamesAbbrTag[]="abbreviated";
217 static const char gNamesShortTag[]="short";
218 static const char gNamesNarrowTag[]="narrow";
219 static const char gNamesAllTag[]="all";
220 static const char gNamesFormatTag[]="format";
221 static const char gNamesStandaloneTag[]="stand-alone";
222 static const char gNamesNumericTag[]="numeric";
223 static const char gAmPmMarkersTag[]="AmPmMarkers";
224 static const char gAmPmMarkersAbbrTag[]="AmPmMarkersAbbr";
225 static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow";
226 static const char gQuartersTag[]="quarters";
227 static const char gNumberElementsTag[]="NumberElements";
228 static const char gSymbolsTag[]="symbols";
229 static const char gTimeSeparatorTag[]="timeSeparator";
230 static const char gDayPeriodTag[]="dayPeriod";
231
232 // static const char gZoneStringsTag[]="zoneStrings";
233
234 // static const char gLocalPatternCharsTag[]="localPatternChars";
235
236 static const char gContextTransformsTag[]="contextTransforms";
237
238 /**
239 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
240 * Work around this.
241 */
newUnicodeStringArray(size_t count)242 static inline UnicodeString* newUnicodeStringArray(size_t count) {
243 return new UnicodeString[count ? count : 1];
244 }
245
246 //------------------------------------------------------
247
248 DateFormatSymbols * U_EXPORT2
createForLocale(const Locale & locale,UErrorCode & status)249 DateFormatSymbols::createForLocale(
250 const Locale& locale, UErrorCode &status) {
251 const SharedDateFormatSymbols *shared = NULL;
252 UnifiedCache::getByLocale(locale, shared, status);
253 if (U_FAILURE(status)) {
254 return NULL;
255 }
256 DateFormatSymbols *result = new DateFormatSymbols(shared->get());
257 shared->removeRef();
258 if (result == NULL) {
259 status = U_MEMORY_ALLOCATION_ERROR;
260 return NULL;
261 }
262 return result;
263 }
264
DateFormatSymbols(const Locale & locale,UErrorCode & status)265 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
266 UErrorCode& status)
267 : UObject()
268 {
269 initializeData(locale, NULL, status);
270 }
271
DateFormatSymbols(UErrorCode & status)272 DateFormatSymbols::DateFormatSymbols(UErrorCode& status)
273 : UObject()
274 {
275 initializeData(Locale::getDefault(), NULL, status, true);
276 }
277
278
DateFormatSymbols(const Locale & locale,const char * type,UErrorCode & status)279 DateFormatSymbols::DateFormatSymbols(const Locale& locale,
280 const char *type,
281 UErrorCode& status)
282 : UObject()
283 {
284 initializeData(locale, type, status);
285 }
286
DateFormatSymbols(const char * type,UErrorCode & status)287 DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status)
288 : UObject()
289 {
290 initializeData(Locale::getDefault(), type, status, true);
291 }
292
DateFormatSymbols(const DateFormatSymbols & other)293 DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other)
294 : UObject(other)
295 {
296 copyData(other);
297 }
298
299 void
assignArray(UnicodeString * & dstArray,int32_t & dstCount,const UnicodeString * srcArray,int32_t srcCount)300 DateFormatSymbols::assignArray(UnicodeString*& dstArray,
301 int32_t& dstCount,
302 const UnicodeString* srcArray,
303 int32_t srcCount)
304 {
305 // assignArray() is only called by copyData() and initializeData(), which in turn
306 // implements the copy constructor and the assignment operator.
307 // All strings in a DateFormatSymbols object are created in one of the following
308 // three ways that all allow to safely use UnicodeString::fastCopyFrom():
309 // - readonly-aliases from resource bundles
310 // - readonly-aliases or allocated strings from constants
311 // - safely cloned strings (with owned buffers) from setXYZ() functions
312 //
313 // Note that this is true for as long as DateFormatSymbols can be constructed
314 // only from a locale bundle or set via the cloning API,
315 // *and* for as long as all the strings are in *private* fields, preventing
316 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()).
317 dstCount = srcCount;
318 dstArray = newUnicodeStringArray(srcCount);
319 if(dstArray != NULL) {
320 int32_t i;
321 for(i=0; i<srcCount; ++i) {
322 dstArray[i].fastCopyFrom(srcArray[i]);
323 }
324 }
325 }
326
327 /**
328 * Create a copy, in fZoneStrings, of the given zone strings array. The
329 * member variables fZoneStringsRowCount and fZoneStringsColCount should
330 * be set already by the caller.
331 */
332 void
createZoneStrings(const UnicodeString * const * otherStrings)333 DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings)
334 {
335 int32_t row, col;
336 UBool failed = false;
337
338 fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *));
339 if (fZoneStrings != NULL) {
340 for (row=0; row<fZoneStringsRowCount; ++row)
341 {
342 fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount);
343 if (fZoneStrings[row] == NULL) {
344 failed = true;
345 break;
346 }
347 for (col=0; col<fZoneStringsColCount; ++col) {
348 // fastCopyFrom() - see assignArray comments
349 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]);
350 }
351 }
352 }
353 // If memory allocation failed, roll back and delete fZoneStrings
354 if (failed) {
355 for (int i = row; i >= 0; i--) {
356 delete[] fZoneStrings[i];
357 }
358 uprv_free(fZoneStrings);
359 fZoneStrings = NULL;
360 }
361 }
362
363 /**
364 * Copy all of the other's data to this.
365 */
366 void
copyData(const DateFormatSymbols & other)367 DateFormatSymbols::copyData(const DateFormatSymbols& other) {
368 UErrorCode status = U_ZERO_ERROR;
369 U_LOCALE_BASED(locBased, *this);
370 locBased.setLocaleIDs(
371 other.getLocale(ULOC_VALID_LOCALE, status),
372 other.getLocale(ULOC_ACTUAL_LOCALE, status));
373 assignArray(fEras, fErasCount, other.fEras, other.fErasCount);
374 assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount);
375 assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount);
376 assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount);
377 assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount);
378 assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount);
379 assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount);
380 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount);
381 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount);
382 assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount);
383 assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount);
384 assignArray(fShorterWeekdays, fShorterWeekdaysCount, other.fShorterWeekdays, other.fShorterWeekdaysCount);
385 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount);
386 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount);
387 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount);
388 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount);
389 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount);
390 assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount);
391 assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount );
392 fTimeSeparator.fastCopyFrom(other.fTimeSeparator); // fastCopyFrom() - see assignArray comments
393 assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount);
394 assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount);
395 assignArray(fNarrowQuarters, fNarrowQuartersCount, other.fNarrowQuarters, other.fNarrowQuartersCount);
396 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
397 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
398 assignArray(fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, other.fStandaloneNarrowQuarters, other.fStandaloneNarrowQuartersCount);
399 assignArray(fWideDayPeriods, fWideDayPeriodsCount,
400 other.fWideDayPeriods, other.fWideDayPeriodsCount);
401 assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
402 other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
403 assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
404 other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
405 assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
406 other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
407 assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
408 other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
409 assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
410 other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
411 if (other.fLeapMonthPatterns != NULL) {
412 assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
413 } else {
414 fLeapMonthPatterns = NULL;
415 fLeapMonthPatternsCount = 0;
416 }
417 if (other.fShortYearNames != NULL) {
418 assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
419 } else {
420 fShortYearNames = NULL;
421 fShortYearNamesCount = 0;
422 }
423 if (other.fShortZodiacNames != NULL) {
424 assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
425 } else {
426 fShortZodiacNames = NULL;
427 fShortZodiacNamesCount = 0;
428 }
429
430 if (other.fZoneStrings != NULL) {
431 fZoneStringsColCount = other.fZoneStringsColCount;
432 fZoneStringsRowCount = other.fZoneStringsRowCount;
433 createZoneStrings((const UnicodeString**)other.fZoneStrings);
434
435 } else {
436 fZoneStrings = NULL;
437 fZoneStringsColCount = 0;
438 fZoneStringsRowCount = 0;
439 }
440 fZSFLocale = other.fZSFLocale;
441 // Other zone strings data is created on demand
442 fLocaleZoneStrings = NULL;
443
444 // fastCopyFrom() - see assignArray comments
445 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
446
447 uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
448 }
449
450 /**
451 * Assignment operator.
452 */
operator =(const DateFormatSymbols & other)453 DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
454 {
455 if (this == &other) { return *this; } // self-assignment: no-op
456 dispose();
457 copyData(other);
458
459 return *this;
460 }
461
~DateFormatSymbols()462 DateFormatSymbols::~DateFormatSymbols()
463 {
464 dispose();
465 }
466
dispose()467 void DateFormatSymbols::dispose()
468 {
469 delete[] fEras;
470 delete[] fEraNames;
471 delete[] fNarrowEras;
472 delete[] fMonths;
473 delete[] fShortMonths;
474 delete[] fNarrowMonths;
475 delete[] fStandaloneMonths;
476 delete[] fStandaloneShortMonths;
477 delete[] fStandaloneNarrowMonths;
478 delete[] fWeekdays;
479 delete[] fShortWeekdays;
480 delete[] fShorterWeekdays;
481 delete[] fNarrowWeekdays;
482 delete[] fStandaloneWeekdays;
483 delete[] fStandaloneShortWeekdays;
484 delete[] fStandaloneShorterWeekdays;
485 delete[] fStandaloneNarrowWeekdays;
486 delete[] fAmPms;
487 delete[] fNarrowAmPms;
488 delete[] fQuarters;
489 delete[] fShortQuarters;
490 delete[] fNarrowQuarters;
491 delete[] fStandaloneQuarters;
492 delete[] fStandaloneShortQuarters;
493 delete[] fStandaloneNarrowQuarters;
494 delete[] fLeapMonthPatterns;
495 delete[] fShortYearNames;
496 delete[] fShortZodiacNames;
497 delete[] fAbbreviatedDayPeriods;
498 delete[] fWideDayPeriods;
499 delete[] fNarrowDayPeriods;
500 delete[] fStandaloneAbbreviatedDayPeriods;
501 delete[] fStandaloneWideDayPeriods;
502 delete[] fStandaloneNarrowDayPeriods;
503
504 disposeZoneStrings();
505 }
506
disposeZoneStrings()507 void DateFormatSymbols::disposeZoneStrings()
508 {
509 if (fZoneStrings) {
510 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
511 delete[] fZoneStrings[row];
512 }
513 uprv_free(fZoneStrings);
514 }
515 if (fLocaleZoneStrings) {
516 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
517 delete[] fLocaleZoneStrings[row];
518 }
519 uprv_free(fLocaleZoneStrings);
520 }
521
522 fZoneStrings = NULL;
523 fLocaleZoneStrings = NULL;
524 fZoneStringsRowCount = 0;
525 fZoneStringsColCount = 0;
526 }
527
528 UBool
arrayCompare(const UnicodeString * array1,const UnicodeString * array2,int32_t count)529 DateFormatSymbols::arrayCompare(const UnicodeString* array1,
530 const UnicodeString* array2,
531 int32_t count)
532 {
533 if (array1 == array2) return true;
534 while (count>0)
535 {
536 --count;
537 if (array1[count] != array2[count]) return false;
538 }
539 return true;
540 }
541
542 bool
operator ==(const DateFormatSymbols & other) const543 DateFormatSymbols::operator==(const DateFormatSymbols& other) const
544 {
545 // First do cheap comparisons
546 if (this == &other) {
547 return true;
548 }
549 if (fErasCount == other.fErasCount &&
550 fEraNamesCount == other.fEraNamesCount &&
551 fNarrowErasCount == other.fNarrowErasCount &&
552 fMonthsCount == other.fMonthsCount &&
553 fShortMonthsCount == other.fShortMonthsCount &&
554 fNarrowMonthsCount == other.fNarrowMonthsCount &&
555 fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
556 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
557 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
558 fWeekdaysCount == other.fWeekdaysCount &&
559 fShortWeekdaysCount == other.fShortWeekdaysCount &&
560 fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
561 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
562 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
563 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
564 fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
565 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
566 fAmPmsCount == other.fAmPmsCount &&
567 fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
568 fQuartersCount == other.fQuartersCount &&
569 fShortQuartersCount == other.fShortQuartersCount &&
570 fNarrowQuartersCount == other.fNarrowQuartersCount &&
571 fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
572 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
573 fStandaloneNarrowQuartersCount == other.fStandaloneNarrowQuartersCount &&
574 fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
575 fShortYearNamesCount == other.fShortYearNamesCount &&
576 fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
577 fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
578 fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
579 fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
580 fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
581 fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
582 fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
583 (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
584 {
585 // Now compare the arrays themselves
586 if (arrayCompare(fEras, other.fEras, fErasCount) &&
587 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
588 arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
589 arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
590 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
591 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
592 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
593 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
594 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
595 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
596 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
597 arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
598 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
599 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
600 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
601 arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
602 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
603 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
604 arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
605 fTimeSeparator == other.fTimeSeparator &&
606 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
607 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
608 arrayCompare(fNarrowQuarters, other.fNarrowQuarters, fNarrowQuartersCount) &&
609 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
610 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
611 arrayCompare(fStandaloneNarrowQuarters, other.fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount) &&
612 arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
613 arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
614 arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
615 arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
616 arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
617 arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
618 arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
619 fStandaloneAbbreviatedDayPeriodsCount) &&
620 arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
621 fStandaloneWideDayPeriodsCount) &&
622 arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
623 fStandaloneWideDayPeriodsCount))
624 {
625 // Compare the contents of fZoneStrings
626 if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
627 if (fZSFLocale == other.fZSFLocale) {
628 return true;
629 }
630 } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
631 if (fZoneStringsRowCount == other.fZoneStringsRowCount
632 && fZoneStringsColCount == other.fZoneStringsColCount) {
633 bool cmpres = true;
634 for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
635 cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
636 }
637 return cmpres;
638 }
639 }
640 return false;
641 }
642 }
643 return false;
644 }
645
646 //------------------------------------------------------
647
648 const UnicodeString*
getEras(int32_t & count) const649 DateFormatSymbols::getEras(int32_t &count) const
650 {
651 count = fErasCount;
652 return fEras;
653 }
654
655 const UnicodeString*
getEraNames(int32_t & count) const656 DateFormatSymbols::getEraNames(int32_t &count) const
657 {
658 count = fEraNamesCount;
659 return fEraNames;
660 }
661
662 const UnicodeString*
getNarrowEras(int32_t & count) const663 DateFormatSymbols::getNarrowEras(int32_t &count) const
664 {
665 count = fNarrowErasCount;
666 return fNarrowEras;
667 }
668
669 const UnicodeString*
getMonths(int32_t & count) const670 DateFormatSymbols::getMonths(int32_t &count) const
671 {
672 count = fMonthsCount;
673 return fMonths;
674 }
675
676 const UnicodeString*
getShortMonths(int32_t & count) const677 DateFormatSymbols::getShortMonths(int32_t &count) const
678 {
679 count = fShortMonthsCount;
680 return fShortMonths;
681 }
682
683 const UnicodeString*
getMonths(int32_t & count,DtContextType context,DtWidthType width) const684 DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
685 {
686 UnicodeString *returnValue = NULL;
687
688 switch (context) {
689 case FORMAT :
690 switch(width) {
691 case WIDE :
692 count = fMonthsCount;
693 returnValue = fMonths;
694 break;
695 case ABBREVIATED :
696 case SHORT : // no month data for this, defaults to ABBREVIATED
697 count = fShortMonthsCount;
698 returnValue = fShortMonths;
699 break;
700 case NARROW :
701 count = fNarrowMonthsCount;
702 returnValue = fNarrowMonths;
703 break;
704 case DT_WIDTH_COUNT :
705 break;
706 }
707 break;
708 case STANDALONE :
709 switch(width) {
710 case WIDE :
711 count = fStandaloneMonthsCount;
712 returnValue = fStandaloneMonths;
713 break;
714 case ABBREVIATED :
715 case SHORT : // no month data for this, defaults to ABBREVIATED
716 count = fStandaloneShortMonthsCount;
717 returnValue = fStandaloneShortMonths;
718 break;
719 case NARROW :
720 count = fStandaloneNarrowMonthsCount;
721 returnValue = fStandaloneNarrowMonths;
722 break;
723 case DT_WIDTH_COUNT :
724 break;
725 }
726 break;
727 case DT_CONTEXT_COUNT :
728 break;
729 }
730 return returnValue;
731 }
732
733 const UnicodeString*
getWeekdays(int32_t & count) const734 DateFormatSymbols::getWeekdays(int32_t &count) const
735 {
736 count = fWeekdaysCount;
737 return fWeekdays;
738 }
739
740 const UnicodeString*
getShortWeekdays(int32_t & count) const741 DateFormatSymbols::getShortWeekdays(int32_t &count) const
742 {
743 count = fShortWeekdaysCount;
744 return fShortWeekdays;
745 }
746
747 const UnicodeString*
getWeekdays(int32_t & count,DtContextType context,DtWidthType width) const748 DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
749 {
750 UnicodeString *returnValue = NULL;
751 switch (context) {
752 case FORMAT :
753 switch(width) {
754 case WIDE :
755 count = fWeekdaysCount;
756 returnValue = fWeekdays;
757 break;
758 case ABBREVIATED :
759 count = fShortWeekdaysCount;
760 returnValue = fShortWeekdays;
761 break;
762 case SHORT :
763 count = fShorterWeekdaysCount;
764 returnValue = fShorterWeekdays;
765 break;
766 case NARROW :
767 count = fNarrowWeekdaysCount;
768 returnValue = fNarrowWeekdays;
769 break;
770 case DT_WIDTH_COUNT :
771 break;
772 }
773 break;
774 case STANDALONE :
775 switch(width) {
776 case WIDE :
777 count = fStandaloneWeekdaysCount;
778 returnValue = fStandaloneWeekdays;
779 break;
780 case ABBREVIATED :
781 count = fStandaloneShortWeekdaysCount;
782 returnValue = fStandaloneShortWeekdays;
783 break;
784 case SHORT :
785 count = fStandaloneShorterWeekdaysCount;
786 returnValue = fStandaloneShorterWeekdays;
787 break;
788 case NARROW :
789 count = fStandaloneNarrowWeekdaysCount;
790 returnValue = fStandaloneNarrowWeekdays;
791 break;
792 case DT_WIDTH_COUNT :
793 break;
794 }
795 break;
796 case DT_CONTEXT_COUNT :
797 break;
798 }
799 return returnValue;
800 }
801
802 const UnicodeString*
getQuarters(int32_t & count,DtContextType context,DtWidthType width) const803 DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
804 {
805 UnicodeString *returnValue = NULL;
806
807 switch (context) {
808 case FORMAT :
809 switch(width) {
810 case WIDE :
811 count = fQuartersCount;
812 returnValue = fQuarters;
813 break;
814 case ABBREVIATED :
815 case SHORT : // no quarter data for this, defaults to ABBREVIATED
816 count = fShortQuartersCount;
817 returnValue = fShortQuarters;
818 break;
819 case NARROW :
820 count = fNarrowQuartersCount;
821 returnValue = fNarrowQuarters;
822 break;
823 case DT_WIDTH_COUNT :
824 break;
825 }
826 break;
827 case STANDALONE :
828 switch(width) {
829 case WIDE :
830 count = fStandaloneQuartersCount;
831 returnValue = fStandaloneQuarters;
832 break;
833 case ABBREVIATED :
834 case SHORT : // no quarter data for this, defaults to ABBREVIATED
835 count = fStandaloneShortQuartersCount;
836 returnValue = fStandaloneShortQuarters;
837 break;
838 case NARROW :
839 count = fStandaloneNarrowQuartersCount;
840 returnValue = fStandaloneNarrowQuarters;
841 break;
842 case DT_WIDTH_COUNT :
843 break;
844 }
845 break;
846 case DT_CONTEXT_COUNT :
847 break;
848 }
849 return returnValue;
850 }
851
852 UnicodeString&
getTimeSeparatorString(UnicodeString & result) const853 DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
854 {
855 // fastCopyFrom() - see assignArray comments
856 return result.fastCopyFrom(fTimeSeparator);
857 }
858
859 const UnicodeString*
getAmPmStrings(int32_t & count) const860 DateFormatSymbols::getAmPmStrings(int32_t &count) const
861 {
862 count = fAmPmsCount;
863 return fAmPms;
864 }
865
866 const UnicodeString*
getLeapMonthPatterns(int32_t & count) const867 DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
868 {
869 count = fLeapMonthPatternsCount;
870 return fLeapMonthPatterns;
871 }
872
873 const UnicodeString*
getYearNames(int32_t & count,DtContextType,DtWidthType) const874 DateFormatSymbols::getYearNames(int32_t& count,
875 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
876 {
877 count = fShortYearNamesCount;
878 return fShortYearNames;
879 }
880
881 void
setYearNames(const UnicodeString * yearNames,int32_t count,DtContextType context,DtWidthType width)882 DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
883 DtContextType context, DtWidthType width)
884 {
885 if (context == FORMAT && width == ABBREVIATED) {
886 if (fShortYearNames) {
887 delete[] fShortYearNames;
888 }
889 fShortYearNames = newUnicodeStringArray(count);
890 uprv_arrayCopy(yearNames, fShortYearNames, count);
891 fShortYearNamesCount = count;
892 }
893 }
894
895 const UnicodeString*
getZodiacNames(int32_t & count,DtContextType,DtWidthType) const896 DateFormatSymbols::getZodiacNames(int32_t& count,
897 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
898 {
899 count = fShortZodiacNamesCount;
900 return fShortZodiacNames;
901 }
902
903 void
setZodiacNames(const UnicodeString * zodiacNames,int32_t count,DtContextType context,DtWidthType width)904 DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
905 DtContextType context, DtWidthType width)
906 {
907 if (context == FORMAT && width == ABBREVIATED) {
908 if (fShortZodiacNames) {
909 delete[] fShortZodiacNames;
910 }
911 fShortZodiacNames = newUnicodeStringArray(count);
912 uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
913 fShortZodiacNamesCount = count;
914 }
915 }
916
917 //------------------------------------------------------
918
919 void
setEras(const UnicodeString * erasArray,int32_t count)920 DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
921 {
922 // delete the old list if we own it
923 if (fEras)
924 delete[] fEras;
925
926 // we always own the new list, which we create here (we duplicate rather
927 // than adopting the list passed in)
928 fEras = newUnicodeStringArray(count);
929 uprv_arrayCopy(erasArray,fEras, count);
930 fErasCount = count;
931 }
932
933 void
setEraNames(const UnicodeString * eraNamesArray,int32_t count)934 DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
935 {
936 // delete the old list if we own it
937 if (fEraNames)
938 delete[] fEraNames;
939
940 // we always own the new list, which we create here (we duplicate rather
941 // than adopting the list passed in)
942 fEraNames = newUnicodeStringArray(count);
943 uprv_arrayCopy(eraNamesArray,fEraNames, count);
944 fEraNamesCount = count;
945 }
946
947 void
setNarrowEras(const UnicodeString * narrowErasArray,int32_t count)948 DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
949 {
950 // delete the old list if we own it
951 if (fNarrowEras)
952 delete[] fNarrowEras;
953
954 // we always own the new list, which we create here (we duplicate rather
955 // than adopting the list passed in)
956 fNarrowEras = newUnicodeStringArray(count);
957 uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
958 fNarrowErasCount = count;
959 }
960
961 void
setMonths(const UnicodeString * monthsArray,int32_t count)962 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
963 {
964 // delete the old list if we own it
965 if (fMonths)
966 delete[] fMonths;
967
968 // we always own the new list, which we create here (we duplicate rather
969 // than adopting the list passed in)
970 fMonths = newUnicodeStringArray(count);
971 uprv_arrayCopy( monthsArray,fMonths,count);
972 fMonthsCount = count;
973 }
974
975 void
setShortMonths(const UnicodeString * shortMonthsArray,int32_t count)976 DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
977 {
978 // delete the old list if we own it
979 if (fShortMonths)
980 delete[] fShortMonths;
981
982 // we always own the new list, which we create here (we duplicate rather
983 // than adopting the list passed in)
984 fShortMonths = newUnicodeStringArray(count);
985 uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
986 fShortMonthsCount = count;
987 }
988
989 void
setMonths(const UnicodeString * monthsArray,int32_t count,DtContextType context,DtWidthType width)990 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
991 {
992 // delete the old list if we own it
993 // we always own the new list, which we create here (we duplicate rather
994 // than adopting the list passed in)
995
996 switch (context) {
997 case FORMAT :
998 switch (width) {
999 case WIDE :
1000 if (fMonths)
1001 delete[] fMonths;
1002 fMonths = newUnicodeStringArray(count);
1003 uprv_arrayCopy( monthsArray,fMonths,count);
1004 fMonthsCount = count;
1005 break;
1006 case ABBREVIATED :
1007 if (fShortMonths)
1008 delete[] fShortMonths;
1009 fShortMonths = newUnicodeStringArray(count);
1010 uprv_arrayCopy( monthsArray,fShortMonths,count);
1011 fShortMonthsCount = count;
1012 break;
1013 case NARROW :
1014 if (fNarrowMonths)
1015 delete[] fNarrowMonths;
1016 fNarrowMonths = newUnicodeStringArray(count);
1017 uprv_arrayCopy( monthsArray,fNarrowMonths,count);
1018 fNarrowMonthsCount = count;
1019 break;
1020 default :
1021 break;
1022 }
1023 break;
1024 case STANDALONE :
1025 switch (width) {
1026 case WIDE :
1027 if (fStandaloneMonths)
1028 delete[] fStandaloneMonths;
1029 fStandaloneMonths = newUnicodeStringArray(count);
1030 uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
1031 fStandaloneMonthsCount = count;
1032 break;
1033 case ABBREVIATED :
1034 if (fStandaloneShortMonths)
1035 delete[] fStandaloneShortMonths;
1036 fStandaloneShortMonths = newUnicodeStringArray(count);
1037 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
1038 fStandaloneShortMonthsCount = count;
1039 break;
1040 case NARROW :
1041 if (fStandaloneNarrowMonths)
1042 delete[] fStandaloneNarrowMonths;
1043 fStandaloneNarrowMonths = newUnicodeStringArray(count);
1044 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
1045 fStandaloneNarrowMonthsCount = count;
1046 break;
1047 default :
1048 break;
1049 }
1050 break;
1051 case DT_CONTEXT_COUNT :
1052 break;
1053 }
1054 }
1055
setWeekdays(const UnicodeString * weekdaysArray,int32_t count)1056 void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
1057 {
1058 // delete the old list if we own it
1059 if (fWeekdays)
1060 delete[] fWeekdays;
1061
1062 // we always own the new list, which we create here (we duplicate rather
1063 // than adopting the list passed in)
1064 fWeekdays = newUnicodeStringArray(count);
1065 uprv_arrayCopy(weekdaysArray,fWeekdays,count);
1066 fWeekdaysCount = count;
1067 }
1068
1069 void
setShortWeekdays(const UnicodeString * shortWeekdaysArray,int32_t count)1070 DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
1071 {
1072 // delete the old list if we own it
1073 if (fShortWeekdays)
1074 delete[] fShortWeekdays;
1075
1076 // we always own the new list, which we create here (we duplicate rather
1077 // than adopting the list passed in)
1078 fShortWeekdays = newUnicodeStringArray(count);
1079 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
1080 fShortWeekdaysCount = count;
1081 }
1082
1083 void
setWeekdays(const UnicodeString * weekdaysArray,int32_t count,DtContextType context,DtWidthType width)1084 DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
1085 {
1086 // delete the old list if we own it
1087 // we always own the new list, which we create here (we duplicate rather
1088 // than adopting the list passed in)
1089
1090 switch (context) {
1091 case FORMAT :
1092 switch (width) {
1093 case WIDE :
1094 if (fWeekdays)
1095 delete[] fWeekdays;
1096 fWeekdays = newUnicodeStringArray(count);
1097 uprv_arrayCopy(weekdaysArray, fWeekdays, count);
1098 fWeekdaysCount = count;
1099 break;
1100 case ABBREVIATED :
1101 if (fShortWeekdays)
1102 delete[] fShortWeekdays;
1103 fShortWeekdays = newUnicodeStringArray(count);
1104 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
1105 fShortWeekdaysCount = count;
1106 break;
1107 case SHORT :
1108 if (fShorterWeekdays)
1109 delete[] fShorterWeekdays;
1110 fShorterWeekdays = newUnicodeStringArray(count);
1111 uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
1112 fShorterWeekdaysCount = count;
1113 break;
1114 case NARROW :
1115 if (fNarrowWeekdays)
1116 delete[] fNarrowWeekdays;
1117 fNarrowWeekdays = newUnicodeStringArray(count);
1118 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
1119 fNarrowWeekdaysCount = count;
1120 break;
1121 case DT_WIDTH_COUNT :
1122 break;
1123 }
1124 break;
1125 case STANDALONE :
1126 switch (width) {
1127 case WIDE :
1128 if (fStandaloneWeekdays)
1129 delete[] fStandaloneWeekdays;
1130 fStandaloneWeekdays = newUnicodeStringArray(count);
1131 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
1132 fStandaloneWeekdaysCount = count;
1133 break;
1134 case ABBREVIATED :
1135 if (fStandaloneShortWeekdays)
1136 delete[] fStandaloneShortWeekdays;
1137 fStandaloneShortWeekdays = newUnicodeStringArray(count);
1138 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
1139 fStandaloneShortWeekdaysCount = count;
1140 break;
1141 case SHORT :
1142 if (fStandaloneShorterWeekdays)
1143 delete[] fStandaloneShorterWeekdays;
1144 fStandaloneShorterWeekdays = newUnicodeStringArray(count);
1145 uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
1146 fStandaloneShorterWeekdaysCount = count;
1147 break;
1148 case NARROW :
1149 if (fStandaloneNarrowWeekdays)
1150 delete[] fStandaloneNarrowWeekdays;
1151 fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
1152 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
1153 fStandaloneNarrowWeekdaysCount = count;
1154 break;
1155 case DT_WIDTH_COUNT :
1156 break;
1157 }
1158 break;
1159 case DT_CONTEXT_COUNT :
1160 break;
1161 }
1162 }
1163
1164 void
setQuarters(const UnicodeString * quartersArray,int32_t count,DtContextType context,DtWidthType width)1165 DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
1166 {
1167 // delete the old list if we own it
1168 // we always own the new list, which we create here (we duplicate rather
1169 // than adopting the list passed in)
1170
1171 switch (context) {
1172 case FORMAT :
1173 switch (width) {
1174 case WIDE :
1175 if (fQuarters)
1176 delete[] fQuarters;
1177 fQuarters = newUnicodeStringArray(count);
1178 uprv_arrayCopy( quartersArray,fQuarters,count);
1179 fQuartersCount = count;
1180 break;
1181 case ABBREVIATED :
1182 if (fShortQuarters)
1183 delete[] fShortQuarters;
1184 fShortQuarters = newUnicodeStringArray(count);
1185 uprv_arrayCopy( quartersArray,fShortQuarters,count);
1186 fShortQuartersCount = count;
1187 break;
1188 case NARROW :
1189 if (fNarrowQuarters)
1190 delete[] fNarrowQuarters;
1191 fNarrowQuarters = newUnicodeStringArray(count);
1192 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1193 fNarrowQuartersCount = count;
1194 break;
1195 default :
1196 break;
1197 }
1198 break;
1199 case STANDALONE :
1200 switch (width) {
1201 case WIDE :
1202 if (fStandaloneQuarters)
1203 delete[] fStandaloneQuarters;
1204 fStandaloneQuarters = newUnicodeStringArray(count);
1205 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1206 fStandaloneQuartersCount = count;
1207 break;
1208 case ABBREVIATED :
1209 if (fStandaloneShortQuarters)
1210 delete[] fStandaloneShortQuarters;
1211 fStandaloneShortQuarters = newUnicodeStringArray(count);
1212 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1213 fStandaloneShortQuartersCount = count;
1214 break;
1215 case NARROW :
1216 if (fStandaloneNarrowQuarters)
1217 delete[] fStandaloneNarrowQuarters;
1218 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1219 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1220 fStandaloneNarrowQuartersCount = count;
1221 break;
1222 default :
1223 break;
1224 }
1225 break;
1226 case DT_CONTEXT_COUNT :
1227 break;
1228 }
1229 }
1230
1231 void
setAmPmStrings(const UnicodeString * amPmsArray,int32_t count)1232 DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1233 {
1234 // delete the old list if we own it
1235 if (fAmPms) delete[] fAmPms;
1236
1237 // we always own the new list, which we create here (we duplicate rather
1238 // than adopting the list passed in)
1239 fAmPms = newUnicodeStringArray(count);
1240 uprv_arrayCopy(amPmsArray,fAmPms,count);
1241 fAmPmsCount = count;
1242 }
1243
1244 void
setTimeSeparatorString(const UnicodeString & newTimeSeparator)1245 DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
1246 {
1247 fTimeSeparator = newTimeSeparator;
1248 }
1249
1250 const UnicodeString**
getZoneStrings(int32_t & rowCount,int32_t & columnCount) const1251 DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1252 {
1253 const UnicodeString **result = NULL;
1254 static UMutex LOCK;
1255
1256 umtx_lock(&LOCK);
1257 if (fZoneStrings == NULL) {
1258 if (fLocaleZoneStrings == NULL) {
1259 ((DateFormatSymbols*)this)->initZoneStringsArray();
1260 }
1261 result = (const UnicodeString**)fLocaleZoneStrings;
1262 } else {
1263 result = (const UnicodeString**)fZoneStrings;
1264 }
1265 rowCount = fZoneStringsRowCount;
1266 columnCount = fZoneStringsColCount;
1267 umtx_unlock(&LOCK);
1268
1269 return result;
1270 }
1271
1272 // For now, we include all zones
1273 #define ZONE_SET UCAL_ZONE_TYPE_ANY
1274
1275 // This code must be called within a synchronized block
1276 void
initZoneStringsArray(void)1277 DateFormatSymbols::initZoneStringsArray(void) {
1278 if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
1279 return;
1280 }
1281
1282 UErrorCode status = U_ZERO_ERROR;
1283
1284 StringEnumeration *tzids = NULL;
1285 UnicodeString ** zarray = NULL;
1286 TimeZoneNames *tzNames = NULL;
1287 int32_t rows = 0;
1288
1289 static const UTimeZoneNameType TYPES[] = {
1290 UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
1291 UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
1292 };
1293 static const int32_t NUM_TYPES = 4;
1294
1295 do { // dummy do-while
1296
1297 tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
1298 rows = tzids->count(status);
1299 if (U_FAILURE(status)) {
1300 break;
1301 }
1302
1303 // Allocate array
1304 int32_t size = rows * sizeof(UnicodeString*);
1305 zarray = (UnicodeString**)uprv_malloc(size);
1306 if (zarray == NULL) {
1307 status = U_MEMORY_ALLOCATION_ERROR;
1308 break;
1309 }
1310 uprv_memset(zarray, 0, size);
1311
1312 tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1313 tzNames->loadAllDisplayNames(status);
1314 if (U_FAILURE(status)) { break; }
1315
1316 const UnicodeString *tzid;
1317 int32_t i = 0;
1318 UDate now = Calendar::getNow();
1319 UnicodeString tzDispName;
1320
1321 while ((tzid = tzids->snext(status)) != 0) {
1322 if (U_FAILURE(status)) {
1323 break;
1324 }
1325
1326 zarray[i] = new UnicodeString[5];
1327 if (zarray[i] == NULL) {
1328 status = U_MEMORY_ALLOCATION_ERROR;
1329 break;
1330 }
1331
1332 zarray[i][0].setTo(*tzid);
1333 tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
1334 i++;
1335 }
1336
1337 } while (false);
1338
1339 if (U_FAILURE(status)) {
1340 if (zarray) {
1341 for (int32_t i = 0; i < rows; i++) {
1342 if (zarray[i]) {
1343 delete[] zarray[i];
1344 }
1345 }
1346 uprv_free(zarray);
1347 zarray = NULL;
1348 }
1349 }
1350
1351 if (tzNames) {
1352 delete tzNames;
1353 }
1354 if (tzids) {
1355 delete tzids;
1356 }
1357
1358 fLocaleZoneStrings = zarray;
1359 fZoneStringsRowCount = rows;
1360 fZoneStringsColCount = 1 + NUM_TYPES;
1361 }
1362
1363 void
setZoneStrings(const UnicodeString * const * strings,int32_t rowCount,int32_t columnCount)1364 DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1365 {
1366 // since deleting a 2-d array is a pain in the butt, we offload that task to
1367 // a separate function
1368 disposeZoneStrings();
1369 // we always own the new list, which we create here (we duplicate rather
1370 // than adopting the list passed in)
1371 fZoneStringsRowCount = rowCount;
1372 fZoneStringsColCount = columnCount;
1373 createZoneStrings((const UnicodeString**)strings);
1374 }
1375
1376 //------------------------------------------------------
1377
1378 const char16_t * U_EXPORT2
getPatternUChars(void)1379 DateFormatSymbols::getPatternUChars(void)
1380 {
1381 return gPatternChars;
1382 }
1383
1384 UDateFormatField U_EXPORT2
getPatternCharIndex(UChar c)1385 DateFormatSymbols::getPatternCharIndex(UChar c) {
1386 const UChar *p = u_strchr(gPatternChars, c);
1387 if (p == NULL) {
1388 return UDAT_FIELD_COUNT;
1389 } else {
1390 return static_cast<UDateFormatField>(p - gPatternChars);
1391 }
1392 }
1393
1394 static const uint64_t kNumericFieldsAlways =
1395 ((uint64_t)1 << UDAT_YEAR_FIELD) | // y
1396 ((uint64_t)1 << UDAT_DATE_FIELD) | // d
1397 ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) | // k
1398 ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) | // H
1399 ((uint64_t)1 << UDAT_MINUTE_FIELD) | // m
1400 ((uint64_t)1 << UDAT_SECOND_FIELD) | // s
1401 ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) | // S
1402 ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) | // D
1403 ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) | // F
1404 ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) | // w
1405 ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) | // W
1406 ((uint64_t)1 << UDAT_HOUR1_FIELD) | // h
1407 ((uint64_t)1 << UDAT_HOUR0_FIELD) | // K
1408 ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) | // Y
1409 ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) | // u
1410 ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) | // g
1411 ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) | // A
1412 ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD); // r
1413
1414 static const uint64_t kNumericFieldsForCount12 =
1415 ((uint64_t)1 << UDAT_MONTH_FIELD) | // M or MM
1416 ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) | // e or ee
1417 ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) | // c or cc
1418 ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) | // L or LL
1419 ((uint64_t)1 << UDAT_QUARTER_FIELD) | // Q or QQ
1420 ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD); // q or qq
1421
1422 UBool U_EXPORT2
isNumericField(UDateFormatField f,int32_t count)1423 DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1424 if (f == UDAT_FIELD_COUNT) {
1425 return false;
1426 }
1427 uint64_t flag = ((uint64_t)1 << f);
1428 return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1429 }
1430
1431 UBool U_EXPORT2
isNumericPatternChar(UChar c,int32_t count)1432 DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1433 return isNumericField(getPatternCharIndex(c), count);
1434 }
1435
1436 //------------------------------------------------------
1437
1438 UnicodeString&
getLocalPatternChars(UnicodeString & result) const1439 DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1440 {
1441 // fastCopyFrom() - see assignArray comments
1442 return result.fastCopyFrom(fLocalPatternChars);
1443 }
1444
1445 //------------------------------------------------------
1446
1447 void
setLocalPatternChars(const UnicodeString & newLocalPatternChars)1448 DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1449 {
1450 fLocalPatternChars = newLocalPatternChars;
1451 }
1452
1453 //------------------------------------------------------
1454
1455 namespace {
1456
1457 // Constants declarations
1458 static const UChar kCalendarAliasPrefixUChar[] = {
1459 SOLIDUS, CAP_L, CAP_O, CAP_C, CAP_A, CAP_L, CAP_E, SOLIDUS,
1460 LOW_C, LOW_A, LOW_L, LOW_E, LOW_N, LOW_D, LOW_A, LOW_R, SOLIDUS
1461 };
1462 static const UChar kGregorianTagUChar[] = {
1463 LOW_G, LOW_R, LOW_E, LOW_G, LOW_O, LOW_R, LOW_I, LOW_A, LOW_N
1464 };
1465 static const UChar kVariantTagUChar[] = {
1466 PERCENT, LOW_V, LOW_A, LOW_R, LOW_I, LOW_A, LOW_N, LOW_T
1467 };
1468 static const UChar kLeapTagUChar[] = {
1469 LOW_L, LOW_E, LOW_A, LOW_P
1470 };
1471 static const UChar kCyclicNameSetsTagUChar[] = {
1472 LOW_C, LOW_Y, LOW_C, LOW_L, LOW_I, LOW_C, CAP_N, LOW_A, LOW_M, LOW_E, CAP_S, LOW_E, LOW_T, LOW_S
1473 };
1474 static const UChar kYearsTagUChar[] = {
1475 SOLIDUS, LOW_Y, LOW_E, LOW_A, LOW_R, LOW_S
1476 };
1477 static const UChar kZodiacsUChar[] = {
1478 SOLIDUS, LOW_Z, LOW_O, LOW_D, LOW_I, LOW_A, LOW_C, LOW_S
1479 };
1480 static const UChar kDayPartsTagUChar[] = {
1481 SOLIDUS, LOW_D, LOW_A, LOW_Y, CAP_P, LOW_A, LOW_R, LOW_T, LOW_S
1482 };
1483 static const UChar kFormatTagUChar[] = {
1484 SOLIDUS, LOW_F, LOW_O, LOW_R, LOW_M, LOW_A, LOW_T
1485 };
1486 static const UChar kAbbrTagUChar[] = {
1487 SOLIDUS, LOW_A, LOW_B, LOW_B, LOW_R, LOW_E, LOW_V, LOW_I, LOW_A, LOW_T, LOW_E, LOW_D
1488 };
1489
1490 // ResourceSink to enumerate all calendar resources
1491 struct CalendarDataSink : public ResourceSink {
1492
1493 // Enum which specifies the type of alias received, or no alias
1494 enum AliasType {
1495 SAME_CALENDAR,
1496 DIFFERENT_CALENDAR,
1497 GREGORIAN,
1498 NONE
1499 };
1500
1501 // Data structures to store resources from the current resource bundle
1502 Hashtable arrays;
1503 Hashtable arraySizes;
1504 Hashtable maps;
1505 /**
1506 * Whenever there are aliases, the same object will be added twice to 'map'.
1507 * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
1508 * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
1509 */
1510 MemoryPool<Hashtable> mapRefs;
1511
1512 // Paths and the aliases they point to
1513 UVector aliasPathPairs;
1514
1515 // Current and next calendar resource table which should be loaded
1516 UnicodeString currentCalendarType;
1517 UnicodeString nextCalendarType;
1518
1519 // Resources to visit when enumerating fallback calendars
1520 LocalPointer<UVector> resourcesToVisit;
1521
1522 // Alias' relative path populated whenever an alias is read
1523 UnicodeString aliasRelativePath;
1524
1525 // Initializes CalendarDataSink with default values
CalendarDataSink__anon95dbcaa50111::CalendarDataSink1526 CalendarDataSink(UErrorCode& status)
1527 : arrays(false, status), arraySizes(false, status), maps(false, status),
1528 mapRefs(),
1529 aliasPathPairs(uprv_deleteUObject, uhash_compareUnicodeString, status),
1530 currentCalendarType(), nextCalendarType(),
1531 resourcesToVisit(NULL), aliasRelativePath() {
1532 if (U_FAILURE(status)) { return; }
1533 }
1534 virtual ~CalendarDataSink();
1535
1536 // Configure the CalendarSink to visit all the resources
visitAllResources__anon95dbcaa50111::CalendarDataSink1537 void visitAllResources() {
1538 resourcesToVisit.adoptInstead(NULL);
1539 }
1540
1541 // Actions to be done before enumerating
preEnumerate__anon95dbcaa50111::CalendarDataSink1542 void preEnumerate(const UnicodeString &calendarType) {
1543 currentCalendarType = calendarType;
1544 nextCalendarType.setToBogus();
1545 aliasPathPairs.removeAllElements();
1546 }
1547
put__anon95dbcaa50111::CalendarDataSink1548 virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) override {
1549 if (U_FAILURE(errorCode)) { return; }
1550 U_ASSERT(!currentCalendarType.isEmpty());
1551
1552 // Stores the resources to visit on the next calendar.
1553 LocalPointer<UVector> resourcesToVisitNext(NULL);
1554 ResourceTable calendarData = value.getTable(errorCode);
1555 if (U_FAILURE(errorCode)) { return; }
1556
1557 // Enumerate all resources for this calendar
1558 for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
1559 UnicodeString keyUString(key, -1, US_INV);
1560
1561 // == Handle aliases ==
1562 AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
1563 if (U_FAILURE(errorCode)) { return; }
1564 if (aliasType == GREGORIAN) {
1565 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
1566 continue;
1567
1568 } else if (aliasType == DIFFERENT_CALENDAR) {
1569 // Whenever an alias to the next calendar (except gregorian) is encountered, register the
1570 // calendar type it's pointing to
1571 if (resourcesToVisitNext.isNull()) {
1572 resourcesToVisitNext
1573 .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
1574 errorCode);
1575 if (U_FAILURE(errorCode)) { return; }
1576 }
1577 LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1578 resourcesToVisitNext->adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1579 if (U_FAILURE(errorCode)) { return; }
1580 continue;
1581
1582 } else if (aliasType == SAME_CALENDAR) {
1583 // Register same-calendar alias
1584 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
1585 LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1586 aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1587 if (U_FAILURE(errorCode)) { return; }
1588 LocalPointer<UnicodeString> keyUStringCopy(keyUString.clone(), errorCode);
1589 aliasPathPairs.adoptElement(keyUStringCopy.orphan(), errorCode);
1590 if (U_FAILURE(errorCode)) { return; }
1591 }
1592 continue;
1593 }
1594
1595 // Only visit the resources that were referenced by an alias on the previous calendar
1596 // (AmPmMarkersAbbr is an exception).
1597 if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1598 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1599
1600 // == Handle data ==
1601 if (uprv_strcmp(key, gAmPmMarkersTag) == 0
1602 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
1603 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1604 if (arrays.get(keyUString) == NULL) {
1605 ResourceArray resourceArray = value.getArray(errorCode);
1606 int32_t arraySize = resourceArray.getSize();
1607 LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1608 value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1609 arrays.put(keyUString, stringArray.orphan(), errorCode);
1610 arraySizes.puti(keyUString, arraySize, errorCode);
1611 if (U_FAILURE(errorCode)) { return; }
1612 }
1613 } else if (uprv_strcmp(key, gErasTag) == 0
1614 || uprv_strcmp(key, gDayNamesTag) == 0
1615 || uprv_strcmp(key, gMonthNamesTag) == 0
1616 || uprv_strcmp(key, gQuartersTag) == 0
1617 || uprv_strcmp(key, gDayPeriodTag) == 0
1618 || uprv_strcmp(key, gMonthPatternsTag) == 0
1619 || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
1620 processResource(keyUString, key, value, errorCode);
1621 }
1622 }
1623
1624 // Apply same-calendar aliases
1625 UBool modified;
1626 do {
1627 modified = false;
1628 for (int32_t i = 0; i < aliasPathPairs.size();) {
1629 UBool mod = false;
1630 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
1631 UnicodeString *aliasArray;
1632 Hashtable *aliasMap;
1633 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
1634 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1635 if (arrays.get(*path) == NULL) {
1636 // Clone the array
1637 int32_t aliasArraySize = arraySizes.geti(*alias);
1638 LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1639 if (U_FAILURE(errorCode)) { return; }
1640 uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1641 // Put the array on the 'arrays' map
1642 arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1643 arraySizes.puti(*path, aliasArraySize, errorCode);
1644 }
1645 if (U_FAILURE(errorCode)) { return; }
1646 mod = true;
1647 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
1648 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1649 if (maps.get(*path) == NULL) {
1650 maps.put(*path, aliasMap, errorCode);
1651 }
1652 if (U_FAILURE(errorCode)) { return; }
1653 mod = true;
1654 }
1655 if (mod) {
1656 aliasPathPairs.removeElementAt(i + 1);
1657 aliasPathPairs.removeElementAt(i);
1658 modified = true;
1659 } else {
1660 i += 2;
1661 }
1662 }
1663 } while (modified && !aliasPathPairs.isEmpty());
1664
1665 // Set the resources to visit on the next calendar
1666 if (!resourcesToVisitNext.isNull()) {
1667 resourcesToVisit = std::move(resourcesToVisitNext);
1668 }
1669 }
1670
1671 // Process the nested resource bundle tables
processResource__anon95dbcaa50111::CalendarDataSink1672 void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1673 if (U_FAILURE(errorCode)) return;
1674
1675 ResourceTable table = value.getTable(errorCode);
1676 if (U_FAILURE(errorCode)) return;
1677 Hashtable* stringMap = NULL;
1678
1679 // Iterate over all the elements of the table and add them to the map
1680 for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1681 UnicodeString keyUString(key, -1, US_INV);
1682
1683 // Ignore '%variant' keys
1684 if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
1685 continue;
1686 }
1687
1688 // == Handle String elements ==
1689 if (value.getType() == URES_STRING) {
1690 // We are on a leaf, store the map elements into the stringMap
1691 if (i == 0) {
1692 // mapRefs will keep ownership of 'stringMap':
1693 stringMap = mapRefs.create(false, errorCode);
1694 if (stringMap == NULL) {
1695 errorCode = U_MEMORY_ALLOCATION_ERROR;
1696 return;
1697 }
1698 maps.put(path, stringMap, errorCode);
1699 if (U_FAILURE(errorCode)) { return; }
1700 stringMap->setValueDeleter(uprv_deleteUObject);
1701 }
1702 U_ASSERT(stringMap != NULL);
1703 int32_t valueStringSize;
1704 const UChar *valueString = value.getString(valueStringSize, errorCode);
1705 if (U_FAILURE(errorCode)) { return; }
1706 LocalPointer<UnicodeString> valueUString(new UnicodeString(true, valueString, valueStringSize), errorCode);
1707 stringMap->put(keyUString, valueUString.orphan(), errorCode);
1708 if (U_FAILURE(errorCode)) { return; }
1709 continue;
1710 }
1711 U_ASSERT(stringMap == NULL);
1712
1713 // Store the current path's length and append the current key to the path.
1714 int32_t pathLength = path.length();
1715 path.append(SOLIDUS).append(keyUString);
1716
1717 // In cyclicNameSets ignore everything but years/format/abbreviated
1718 // and zodiacs/format/abbreviated
1719 if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
1720 UBool skip = true;
1721 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
1722 int32_t length = 0;
1723 if (startIndex == path.length()
1724 || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
1725 || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
1726 || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
1727 startIndex += length;
1728 length = 0;
1729 if (startIndex == path.length()
1730 || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
1731 startIndex += length;
1732 length = 0;
1733 if (startIndex == path.length()
1734 || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
1735 skip = false;
1736 }
1737 }
1738 }
1739 if (skip) {
1740 // Drop the latest key on the path and continue
1741 path.retainBetween(0, pathLength);
1742 continue;
1743 }
1744 }
1745
1746 // == Handle aliases ==
1747 if (arrays.get(path) != NULL || maps.get(path) != NULL) {
1748 // Drop the latest key on the path and continue
1749 path.retainBetween(0, pathLength);
1750 continue;
1751 }
1752
1753 AliasType aliasType = processAliasFromValue(path, value, errorCode);
1754 if (U_FAILURE(errorCode)) { return; }
1755 if (aliasType == SAME_CALENDAR) {
1756 // Store the alias path and the current path on aliasPathPairs
1757 LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode);
1758 aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode);
1759 if (U_FAILURE(errorCode)) { return; }
1760 LocalPointer<UnicodeString> pathCopy(path.clone(), errorCode);
1761 aliasPathPairs.adoptElement(pathCopy.orphan(), errorCode);
1762 if (U_FAILURE(errorCode)) { return; }
1763
1764 // Drop the latest key on the path and continue
1765 path.retainBetween(0, pathLength);
1766 continue;
1767 }
1768 U_ASSERT(aliasType == NONE);
1769
1770 // == Handle data ==
1771 if (value.getType() == URES_ARRAY) {
1772 // We are on a leaf, store the array
1773 ResourceArray rDataArray = value.getArray(errorCode);
1774 int32_t dataArraySize = rDataArray.getSize();
1775 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1776 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1777 arrays.put(path, dataArray.orphan(), errorCode);
1778 arraySizes.puti(path, dataArraySize, errorCode);
1779 if (U_FAILURE(errorCode)) { return; }
1780 } else if (value.getType() == URES_TABLE) {
1781 // We are not on a leaf, recursively process the subtable.
1782 processResource(path, key, value, errorCode);
1783 if (U_FAILURE(errorCode)) { return; }
1784 }
1785
1786 // Drop the latest key on the path
1787 path.retainBetween(0, pathLength);
1788 }
1789 }
1790
1791 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
processAliasFromValue__anon95dbcaa50111::CalendarDataSink1792 AliasType processAliasFromValue(UnicodeString ¤tRelativePath, ResourceValue &value,
1793 UErrorCode &errorCode) {
1794 if (U_FAILURE(errorCode)) { return NONE; }
1795
1796 if (value.getType() == URES_ALIAS) {
1797 int32_t aliasPathSize;
1798 const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1799 if (U_FAILURE(errorCode)) { return NONE; }
1800 UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1801 const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
1802 if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1803 && aliasPath.length() > aliasPrefixLength) {
1804 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
1805 if (typeLimit > aliasPrefixLength) {
1806 const UnicodeString aliasCalendarType =
1807 aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1808 aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1809
1810 if (currentCalendarType == aliasCalendarType
1811 && currentRelativePath != aliasRelativePath) {
1812 // If we have an alias to the same calendar, the path to the resource must be different
1813 return SAME_CALENDAR;
1814
1815 } else if (currentCalendarType != aliasCalendarType
1816 && currentRelativePath == aliasRelativePath) {
1817 // If we have an alias to a different calendar, the path to the resource must be the same
1818 if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
1819 return GREGORIAN;
1820 } else if (nextCalendarType.isBogus()) {
1821 nextCalendarType = aliasCalendarType;
1822 return DIFFERENT_CALENDAR;
1823 } else if (nextCalendarType == aliasCalendarType) {
1824 return DIFFERENT_CALENDAR;
1825 }
1826 }
1827 }
1828 }
1829 errorCode = U_INTERNAL_PROGRAM_ERROR;
1830 return NONE;
1831 }
1832 return NONE;
1833 }
1834
1835 // Deleter function to be used by 'arrays'
deleteUnicodeStringArray__anon95dbcaa50111::CalendarDataSink1836 static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1837 delete[] static_cast<UnicodeString *>(uArray);
1838 }
1839 };
1840 // Virtual destructors have to be defined out of line
~CalendarDataSink()1841 CalendarDataSink::~CalendarDataSink() {
1842 arrays.setValueDeleter(deleteUnicodeStringArray);
1843 }
1844 }
1845
1846 //------------------------------------------------------
1847
1848 static void
initField(UnicodeString ** field,int32_t & length,const UChar * data,LastResortSize numStr,LastResortSize strLen,UErrorCode & status)1849 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1850 if (U_SUCCESS(status)) {
1851 length = numStr;
1852 *field = newUnicodeStringArray((size_t)numStr);
1853 if (*field) {
1854 for(int32_t i = 0; i<length; i++) {
1855 // readonly aliases - all "data" strings are constant
1856 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1857 (*(field)+i)->setTo(true, data+(i*((int32_t)strLen)), -1);
1858 }
1859 }
1860 else {
1861 length = 0;
1862 status = U_MEMORY_ALLOCATION_ERROR;
1863 }
1864 }
1865 }
1866
1867 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,UErrorCode & status)1868 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1869 if (U_SUCCESS(status)) {
1870 UnicodeString keyUString(key.data(), -1, US_INV);
1871 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1872
1873 if (array != NULL) {
1874 length = sink.arraySizes.geti(keyUString);
1875 *field = array;
1876 // DateFormatSymbols takes ownership of the array:
1877 sink.arrays.remove(keyUString);
1878 } else {
1879 length = 0;
1880 status = U_MISSING_RESOURCE_ERROR;
1881 }
1882 }
1883 }
1884
1885 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,int32_t arrayOffset,UErrorCode & status)1886 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1887 if (U_SUCCESS(status)) {
1888 UnicodeString keyUString(key.data(), -1, US_INV);
1889 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1890
1891 if (array != NULL) {
1892 int32_t arrayLength = sink.arraySizes.geti(keyUString);
1893 length = arrayLength + arrayOffset;
1894 *field = new UnicodeString[length];
1895 if (*field == NULL) {
1896 status = U_MEMORY_ALLOCATION_ERROR;
1897 return;
1898 }
1899 uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1900 } else {
1901 length = 0;
1902 status = U_MISSING_RESOURCE_ERROR;
1903 }
1904 }
1905 }
1906
1907 static void
initLeapMonthPattern(UnicodeString * field,int32_t index,CalendarDataSink & sink,CharString & path,UErrorCode & status)1908 initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
1909 field[index].remove();
1910 if (U_SUCCESS(status)) {
1911 UnicodeString pathUString(path.data(), -1, US_INV);
1912 Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
1913 if (leapMonthTable != NULL) {
1914 UnicodeString leapLabel(false, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
1915 UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
1916 if (leapMonthPattern != NULL) {
1917 field[index].fastCopyFrom(*leapMonthPattern);
1918 } else {
1919 field[index].setToBogus();
1920 }
1921 return;
1922 }
1923 status = U_MISSING_RESOURCE_ERROR;
1924 }
1925 }
1926
1927 static CharString
buildResourcePath(CharString & path,const char * segment1,UErrorCode & errorCode)1928 &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
1929 return path.clear().append(segment1, -1, errorCode);
1930 }
1931
1932 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,UErrorCode & errorCode)1933 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1934 UErrorCode &errorCode) {
1935 return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
1936 .append(segment2, -1, errorCode);
1937 }
1938
1939 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,UErrorCode & errorCode)1940 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1941 const char* segment3, UErrorCode &errorCode) {
1942 return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
1943 .append(segment3, -1, errorCode);
1944 }
1945
1946 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,const char * segment4,UErrorCode & errorCode)1947 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1948 const char* segment3, const char* segment4, UErrorCode &errorCode) {
1949 return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
1950 .append(segment4, -1, errorCode);
1951 }
1952
1953 typedef struct {
1954 const char * usageTypeName;
1955 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1956 } ContextUsageTypeNameToEnumValue;
1957
1958 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1959 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1960 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1961 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
1962 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1963 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
1964 { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
1965 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
1966 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
1967 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1968 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1969 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
1970 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1971 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
1972 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
1973 { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1974 };
1975
1976 // Resource keys to look up localized strings for day periods.
1977 // The first one must be midnight and the second must be noon, so that their indices coincide
1978 // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1979 static const char *dayPeriodKeys[] = {"midnight", "noon",
1980 "morning1", "afternoon1", "evening1", "night1",
1981 "morning2", "afternoon2", "evening2", "night2"};
1982
loadDayPeriodStrings(CalendarDataSink & sink,CharString & path,int32_t & stringCount,UErrorCode & status)1983 UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
1984 int32_t &stringCount, UErrorCode &status) {
1985 if (U_FAILURE(status)) { return NULL; }
1986
1987 UnicodeString pathUString(path.data(), -1, US_INV);
1988 Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
1989
1990 stringCount = UPRV_LENGTHOF(dayPeriodKeys);
1991 UnicodeString *strings = new UnicodeString[stringCount];
1992 if (strings == NULL) {
1993 status = U_MEMORY_ALLOCATION_ERROR;
1994 return NULL;
1995 }
1996
1997 if (map != NULL) {
1998 for (int32_t i = 0; i < stringCount; ++i) {
1999 UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
2000 UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2001 if (dayPeriod != NULL) {
2002 strings[i].fastCopyFrom(*dayPeriod);
2003 } else {
2004 strings[i].setToBogus();
2005 }
2006 }
2007 } else {
2008 for (int32_t i = 0; i < stringCount; i++) {
2009 strings[i].setToBogus();
2010 }
2011 }
2012 return strings;
2013 }
2014
2015
2016 void
initializeData(const Locale & locale,const char * type,UErrorCode & status,UBool useLastResortData)2017 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2018 {
2019 int32_t len = 0;
2020 /* In case something goes wrong, initialize all of the data to NULL. */
2021 fEras = NULL;
2022 fErasCount = 0;
2023 fEraNames = NULL;
2024 fEraNamesCount = 0;
2025 fNarrowEras = NULL;
2026 fNarrowErasCount = 0;
2027 fMonths = NULL;
2028 fMonthsCount=0;
2029 fShortMonths = NULL;
2030 fShortMonthsCount=0;
2031 fNarrowMonths = NULL;
2032 fNarrowMonthsCount=0;
2033 fStandaloneMonths = NULL;
2034 fStandaloneMonthsCount=0;
2035 fStandaloneShortMonths = NULL;
2036 fStandaloneShortMonthsCount=0;
2037 fStandaloneNarrowMonths = NULL;
2038 fStandaloneNarrowMonthsCount=0;
2039 fWeekdays = NULL;
2040 fWeekdaysCount=0;
2041 fShortWeekdays = NULL;
2042 fShortWeekdaysCount=0;
2043 fShorterWeekdays = NULL;
2044 fShorterWeekdaysCount=0;
2045 fNarrowWeekdays = NULL;
2046 fNarrowWeekdaysCount=0;
2047 fStandaloneWeekdays = NULL;
2048 fStandaloneWeekdaysCount=0;
2049 fStandaloneShortWeekdays = NULL;
2050 fStandaloneShortWeekdaysCount=0;
2051 fStandaloneShorterWeekdays = NULL;
2052 fStandaloneShorterWeekdaysCount=0;
2053 fStandaloneNarrowWeekdays = NULL;
2054 fStandaloneNarrowWeekdaysCount=0;
2055 fAmPms = NULL;
2056 fAmPmsCount=0;
2057 fNarrowAmPms = NULL;
2058 fNarrowAmPmsCount=0;
2059 fTimeSeparator.setToBogus();
2060 fQuarters = NULL;
2061 fQuartersCount = 0;
2062 fShortQuarters = NULL;
2063 fShortQuartersCount = 0;
2064 fNarrowQuarters = NULL;
2065 fNarrowQuartersCount = 0;
2066 fStandaloneQuarters = NULL;
2067 fStandaloneQuartersCount = 0;
2068 fStandaloneShortQuarters = NULL;
2069 fStandaloneShortQuartersCount = 0;
2070 fStandaloneNarrowQuarters = NULL;
2071 fStandaloneNarrowQuartersCount = 0;
2072 fLeapMonthPatterns = NULL;
2073 fLeapMonthPatternsCount = 0;
2074 fShortYearNames = NULL;
2075 fShortYearNamesCount = 0;
2076 fShortZodiacNames = NULL;
2077 fShortZodiacNamesCount = 0;
2078 fZoneStringsRowCount = 0;
2079 fZoneStringsColCount = 0;
2080 fZoneStrings = NULL;
2081 fLocaleZoneStrings = NULL;
2082 fAbbreviatedDayPeriods = NULL;
2083 fAbbreviatedDayPeriodsCount = 0;
2084 fWideDayPeriods = NULL;
2085 fWideDayPeriodsCount = 0;
2086 fNarrowDayPeriods = NULL;
2087 fNarrowDayPeriodsCount = 0;
2088 fStandaloneAbbreviatedDayPeriods = NULL;
2089 fStandaloneAbbreviatedDayPeriodsCount = 0;
2090 fStandaloneWideDayPeriods = NULL;
2091 fStandaloneWideDayPeriodsCount = 0;
2092 fStandaloneNarrowDayPeriods = NULL;
2093 fStandaloneNarrowDayPeriodsCount = 0;
2094 uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
2095
2096 // We need to preserve the requested locale for
2097 // lazy ZoneStringFormat instantiation. ZoneStringFormat
2098 // is region sensitive, thus, bundle locale bundle's locale
2099 // is not sufficient.
2100 fZSFLocale = locale;
2101
2102 if (U_FAILURE(status)) return;
2103
2104 // Create a CalendarDataSink to process this data and the resource bundles
2105 CalendarDataSink calendarSink(status);
2106 UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
2107 UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
2108
2109 if (U_FAILURE(status)) return;
2110
2111 // Iterate over the resource bundle data following the fallbacks through different calendar types
2112 UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
2113 while (!calendarType.isBogus()) {
2114 CharString calendarTypeBuffer;
2115 calendarTypeBuffer.appendInvariantChars(calendarType, status);
2116 if (U_FAILURE(status)) { return; }
2117 const char *calendarTypeCArray = calendarTypeBuffer.data();
2118
2119 // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2120 UErrorCode oldStatus = status;
2121 UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
2122 if (status == U_MISSING_RESOURCE_ERROR) {
2123 ures_close(ctb);
2124 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
2125 calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2126 calendarSink.visitAllResources();
2127 status = oldStatus;
2128 continue;
2129 }
2130 return;
2131 }
2132
2133 calendarSink.preEnumerate(calendarType);
2134 ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
2135 ures_close(ctb);
2136 if (U_FAILURE(status)) break;
2137
2138 // Stop loading when gregorian was loaded
2139 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2140 break;
2141 }
2142
2143 // Get the next calendar type to process from the sink
2144 calendarType = calendarSink.nextCalendarType;
2145
2146 // Gregorian is always the last fallback
2147 if (calendarType.isBogus()) {
2148 calendarType.setTo(false, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2149 calendarSink.visitAllResources();
2150 }
2151 }
2152
2153 // CharString object to build paths
2154 CharString path;
2155
2156 // Load Leap Month Patterns
2157 UErrorCode tempStatus = status;
2158 fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2159 if (fLeapMonthPatterns) {
2160 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2161 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2162 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2163 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2164 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2165 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2166 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2167 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2168 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2169 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2170 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2171 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2172 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2173 buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2174 if (U_SUCCESS(tempStatus)) {
2175 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2176 // The ordering of the following statements is important.
2177 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
2178 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2179 }
2180 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
2181 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
2182 }
2183 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
2184 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2185 }
2186 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
2187 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
2188 }
2189 // end of hack
2190 fLeapMonthPatternsCount = kMonthPatternsCount;
2191 } else {
2192 delete[] fLeapMonthPatterns;
2193 fLeapMonthPatterns = NULL;
2194 }
2195 }
2196
2197 // Load cyclic names sets
2198 tempStatus = status;
2199 initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2200 buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2201 initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2202 buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2203
2204 // Load context transforms and capitalization
2205 tempStatus = U_ZERO_ERROR;
2206 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
2207 if (U_SUCCESS(tempStatus)) {
2208 UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
2209 if (U_SUCCESS(tempStatus)) {
2210 UResourceBundle *contextTransformUsage;
2211 while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
2212 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
2213 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
2214 const char* usageType = ures_getKey(contextTransformUsage);
2215 if (usageType != NULL) {
2216 const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2217 int32_t compResult = 0;
2218 // linear search; list is short and we cannot be sure that bsearch is available
2219 while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2220 ++typeMapPtr;
2221 }
2222 if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
2223 fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2224 fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2225 }
2226 }
2227 }
2228 tempStatus = U_ZERO_ERROR;
2229 ures_close(contextTransformUsage);
2230 }
2231 ures_close(contextTransforms);
2232 }
2233
2234 tempStatus = U_ZERO_ERROR;
2235 const LocalPointer<NumberingSystem> numberingSystem(
2236 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2237 if (U_SUCCESS(tempStatus)) {
2238 // These functions all fail gracefully if passed NULL pointers and
2239 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2240 // to check for errors once after all calls are made.
2241 const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
2242 localeBundle, gNumberElementsTag, NULL, &tempStatus));
2243 const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
2244 numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
2245 const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
2246 nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
2247 fTimeSeparator = ures_getUnicodeStringByKey(
2248 symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2249 if (U_FAILURE(tempStatus)) {
2250 fTimeSeparator.setToBogus();
2251 }
2252 }
2253
2254 ures_close(localeBundle);
2255 }
2256
2257 if (fTimeSeparator.isBogus()) {
2258 fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2259 }
2260
2261 // Load day periods
2262 fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2263 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2264 fWideDayPeriodsCount, status);
2265 fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2266 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2267 fNarrowDayPeriodsCount, status);
2268 fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2269 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2270 fAbbreviatedDayPeriodsCount, status);
2271 fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2272 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2273 fStandaloneWideDayPeriodsCount, status);
2274 fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2275 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2276 fStandaloneNarrowDayPeriodsCount, status);
2277 fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2278 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2279 fStandaloneAbbreviatedDayPeriodsCount, status);
2280
2281 U_LOCALE_BASED(locBased, *this);
2282 // if we make it to here, the resource data is cool, and we can get everything out
2283 // of it that we need except for the time-zone and localized-pattern data, which
2284 // are stored in a separate file
2285 locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
2286 ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
2287
2288 // Load eras
2289 initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
2290 UErrorCode oldStatus = status;
2291 initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
2292 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2293 status = oldStatus;
2294 assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
2295 }
2296 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2297 oldStatus = status;
2298 initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
2299 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2300 status = oldStatus;
2301 assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
2302 }
2303
2304 // Load month names
2305 initField(&fMonths, fMonthsCount, calendarSink,
2306 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2307 initField(&fShortMonths, fShortMonthsCount, calendarSink,
2308 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2309 initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2310 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2311 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
2312 status = U_ZERO_ERROR;
2313 assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
2314 }
2315 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2316 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2317 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
2318 status = U_ZERO_ERROR;
2319 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
2320 }
2321
2322 UErrorCode narrowMonthsEC = status;
2323 UErrorCode standaloneNarrowMonthsEC = status;
2324 initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2325 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2326 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2327 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2328 if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
2329 // If format/narrow not available, use standalone/narrow
2330 assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
2331 } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2332 // If standalone/narrow not available, use format/narrow
2333 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
2334 } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2335 // If neither is available, use format/abbreviated
2336 assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2337 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2338 }
2339
2340 // Load AM/PM markers; if wide or narrow not available, use short
2341 UErrorCode ampmStatus = U_ZERO_ERROR;
2342 initField(&fAmPms, fAmPmsCount, calendarSink,
2343 buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2344 if (U_FAILURE(ampmStatus)) {
2345 initField(&fAmPms, fAmPmsCount, calendarSink,
2346 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2347 }
2348 ampmStatus = U_ZERO_ERROR;
2349 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2350 buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2351 if (U_FAILURE(ampmStatus)) {
2352 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2353 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2354 }
2355
2356 // Load quarters
2357 initField(&fQuarters, fQuartersCount, calendarSink,
2358 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2359 initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2360 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2361
2362 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2363 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2364 if(status == U_MISSING_RESOURCE_ERROR) {
2365 status = U_ZERO_ERROR;
2366 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2367 }
2368 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2369 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2370 if(status == U_MISSING_RESOURCE_ERROR) {
2371 status = U_ZERO_ERROR;
2372 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
2373 }
2374
2375 // unlike the fields above, narrow format quarters fall back on narrow standalone quarters
2376 initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, calendarSink,
2377 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
2378 initField(&fNarrowQuarters, fNarrowQuartersCount, calendarSink,
2379 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesNarrowTag, status), status);
2380 if(status == U_MISSING_RESOURCE_ERROR) {
2381 status = U_ZERO_ERROR;
2382 assignArray(fNarrowQuarters, fNarrowQuartersCount, fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount);
2383 }
2384
2385 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2386 /*
2387 // fastCopyFrom()/setTo() - see assignArray comments
2388 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2389 fLocalPatternChars.setTo(true, resStr, len);
2390 // If the locale data does not include new pattern chars, use the defaults
2391 // TODO: Consider making this an error, since this may add conflicting characters.
2392 if (len < PATTERN_CHARS_LEN) {
2393 fLocalPatternChars.append(UnicodeString(true, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2394 }
2395 */
2396 fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN);
2397
2398 // Format wide weekdays -> fWeekdays
2399 // {sfb} fixed to handle 1-based weekdays
2400 initField(&fWeekdays, fWeekdaysCount, calendarSink,
2401 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2402
2403 // Format abbreviated weekdays -> fShortWeekdays
2404 initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2405 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2406
2407 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2408 initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2409 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2410 if (status == U_MISSING_RESOURCE_ERROR) {
2411 status = U_ZERO_ERROR;
2412 assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2413 }
2414
2415 // Stand-alone wide weekdays -> fStandaloneWeekdays
2416 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2417 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2418 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
2419 status = U_ZERO_ERROR;
2420 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
2421 }
2422
2423 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2424 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2425 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2426 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
2427 status = U_ZERO_ERROR;
2428 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2429 }
2430
2431 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2432 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2433 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2434 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
2435 status = U_ZERO_ERROR;
2436 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
2437 }
2438
2439 // Format narrow weekdays -> fNarrowWeekdays
2440 UErrorCode narrowWeeksEC = status;
2441 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2442 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2443 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2444 UErrorCode standaloneNarrowWeeksEC = status;
2445 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2446 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2447
2448 if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
2449 // If format/narrow not available, use standalone/narrow
2450 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
2451 } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
2452 // If standalone/narrow not available, use format/narrow
2453 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
2454 } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
2455 // If neither is available, use format/abbreviated
2456 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2457 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2458 }
2459
2460 // Last resort fallback in case previous data wasn't loaded
2461 if (U_FAILURE(status))
2462 {
2463 if (useLastResortData)
2464 {
2465 // Handle the case in which there is no resource data present.
2466 // We don't have to generate usable patterns in this situation;
2467 // we just need to produce something that will be semi-intelligible
2468 // in most locales.
2469
2470 status = U_USING_FALLBACK_WARNING;
2471 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2472 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2473 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2474 initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2475 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2476 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2477 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2478 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2479 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2480 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2481 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2482 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2483 initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2484 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2485 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2486 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2487 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2488 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2489 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2490 initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2491 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2492 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2493 initField(&fNarrowQuarters, fNarrowQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2494 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2495 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2496 initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2497 fLocalPatternChars.setTo(true, gPatternChars, PATTERN_CHARS_LEN);
2498 }
2499 }
2500
2501 // Close resources
2502 ures_close(cb);
2503 ures_close(rb);
2504 }
2505
2506 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const2507 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
2508 U_LOCALE_BASED(locBased, *this);
2509 return locBased.getLocale(type, status);
2510 }
2511
2512 U_NAMESPACE_END
2513
2514 #endif /* #if !UCONFIG_NO_FORMATTING */
2515
2516 //eof
2517