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__anon5578a7220111::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__anon5578a7220111::CalendarDataSink1537 void visitAllResources() {
1538 resourcesToVisit.adoptInstead(NULL);
1539 }
1540
1541 // Actions to be done before enumerating
preEnumerate__anon5578a7220111::CalendarDataSink1542 void preEnumerate(const UnicodeString &calendarType) {
1543 currentCalendarType = calendarType;
1544 nextCalendarType.setToBogus();
1545 aliasPathPairs.removeAllElements();
1546 }
1547
put__anon5578a7220111::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(new UnicodeString(aliasRelativePath), errorCode);
1578 resourcesToVisitNext->addElementX(aliasRelativePathCopy.getAlias(), errorCode);
1579 if (U_FAILURE(errorCode)) { return; }
1580 // Only release ownership after resourcesToVisitNext takes it (no error happened):
1581 aliasRelativePathCopy.orphan();
1582 continue;
1583
1584 } else if (aliasType == SAME_CALENDAR) {
1585 // Register same-calendar alias
1586 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
1587 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1588 aliasPathPairs.addElementX(aliasRelativePathCopy.getAlias(), errorCode);
1589 if (U_FAILURE(errorCode)) { return; }
1590 // Only release ownership after aliasPathPairs takes it (no error happened):
1591 aliasRelativePathCopy.orphan();
1592 LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode);
1593 aliasPathPairs.addElementX(keyUStringCopy.getAlias(), errorCode);
1594 if (U_FAILURE(errorCode)) { return; }
1595 // Only release ownership after aliasPathPairs takes it (no error happened):
1596 keyUStringCopy.orphan();
1597 }
1598 continue;
1599 }
1600
1601 // Only visit the resources that were referenced by an alias on the previous calendar
1602 // (AmPmMarkersAbbr is an exception).
1603 if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1604 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1605
1606 // == Handle data ==
1607 if (uprv_strcmp(key, gAmPmMarkersTag) == 0
1608 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
1609 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1610 if (arrays.get(keyUString) == NULL) {
1611 ResourceArray resourceArray = value.getArray(errorCode);
1612 int32_t arraySize = resourceArray.getSize();
1613 LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1614 value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1615 arrays.put(keyUString, stringArray.orphan(), errorCode);
1616 arraySizes.puti(keyUString, arraySize, errorCode);
1617 if (U_FAILURE(errorCode)) { return; }
1618 }
1619 } else if (uprv_strcmp(key, gErasTag) == 0
1620 || uprv_strcmp(key, gDayNamesTag) == 0
1621 || uprv_strcmp(key, gMonthNamesTag) == 0
1622 || uprv_strcmp(key, gQuartersTag) == 0
1623 || uprv_strcmp(key, gDayPeriodTag) == 0
1624 || uprv_strcmp(key, gMonthPatternsTag) == 0
1625 || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
1626 processResource(keyUString, key, value, errorCode);
1627 }
1628 }
1629
1630 // Apply same-calendar aliases
1631 UBool modified;
1632 do {
1633 modified = false;
1634 for (int32_t i = 0; i < aliasPathPairs.size();) {
1635 UBool mod = false;
1636 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
1637 UnicodeString *aliasArray;
1638 Hashtable *aliasMap;
1639 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
1640 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1641 if (arrays.get(*path) == NULL) {
1642 // Clone the array
1643 int32_t aliasArraySize = arraySizes.geti(*alias);
1644 LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1645 if (U_FAILURE(errorCode)) { return; }
1646 uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1647 // Put the array on the 'arrays' map
1648 arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1649 arraySizes.puti(*path, aliasArraySize, errorCode);
1650 }
1651 if (U_FAILURE(errorCode)) { return; }
1652 mod = true;
1653 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
1654 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1655 if (maps.get(*path) == NULL) {
1656 maps.put(*path, aliasMap, errorCode);
1657 }
1658 if (U_FAILURE(errorCode)) { return; }
1659 mod = true;
1660 }
1661 if (mod) {
1662 aliasPathPairs.removeElementAt(i + 1);
1663 aliasPathPairs.removeElementAt(i);
1664 modified = true;
1665 } else {
1666 i += 2;
1667 }
1668 }
1669 } while (modified && !aliasPathPairs.isEmpty());
1670
1671 // Set the resources to visit on the next calendar
1672 if (!resourcesToVisitNext.isNull()) {
1673 resourcesToVisit = std::move(resourcesToVisitNext);
1674 }
1675 }
1676
1677 // Process the nested resource bundle tables
processResource__anon5578a7220111::CalendarDataSink1678 void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1679 if (U_FAILURE(errorCode)) return;
1680
1681 ResourceTable table = value.getTable(errorCode);
1682 if (U_FAILURE(errorCode)) return;
1683 Hashtable* stringMap = NULL;
1684
1685 // Iterate over all the elements of the table and add them to the map
1686 for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1687 UnicodeString keyUString(key, -1, US_INV);
1688
1689 // Ignore '%variant' keys
1690 if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
1691 continue;
1692 }
1693
1694 // == Handle String elements ==
1695 if (value.getType() == URES_STRING) {
1696 // We are on a leaf, store the map elements into the stringMap
1697 if (i == 0) {
1698 // mapRefs will keep ownership of 'stringMap':
1699 stringMap = mapRefs.create(FALSE, errorCode);
1700 if (stringMap == NULL) {
1701 errorCode = U_MEMORY_ALLOCATION_ERROR;
1702 return;
1703 }
1704 maps.put(path, stringMap, errorCode);
1705 if (U_FAILURE(errorCode)) { return; }
1706 stringMap->setValueDeleter(uprv_deleteUObject);
1707 }
1708 U_ASSERT(stringMap != NULL);
1709 int32_t valueStringSize;
1710 const UChar *valueString = value.getString(valueStringSize, errorCode);
1711 if (U_FAILURE(errorCode)) { return; }
1712 LocalPointer<UnicodeString> valueUString(new UnicodeString(TRUE, valueString, valueStringSize), errorCode);
1713 stringMap->put(keyUString, valueUString.orphan(), errorCode);
1714 if (U_FAILURE(errorCode)) { return; }
1715 continue;
1716 }
1717 U_ASSERT(stringMap == NULL);
1718
1719 // Store the current path's length and append the current key to the path.
1720 int32_t pathLength = path.length();
1721 path.append(SOLIDUS).append(keyUString);
1722
1723 // In cyclicNameSets ignore everything but years/format/abbreviated
1724 // and zodiacs/format/abbreviated
1725 if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
1726 UBool skip = TRUE;
1727 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
1728 int32_t length = 0;
1729 if (startIndex == path.length()
1730 || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
1731 || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
1732 || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
1733 startIndex += length;
1734 length = 0;
1735 if (startIndex == path.length()
1736 || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
1737 startIndex += length;
1738 length = 0;
1739 if (startIndex == path.length()
1740 || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
1741 skip = FALSE;
1742 }
1743 }
1744 }
1745 if (skip) {
1746 // Drop the latest key on the path and continue
1747 path.retainBetween(0, pathLength);
1748 continue;
1749 }
1750 }
1751
1752 // == Handle aliases ==
1753 if (arrays.get(path) != NULL || maps.get(path) != NULL) {
1754 // Drop the latest key on the path and continue
1755 path.retainBetween(0, pathLength);
1756 continue;
1757 }
1758
1759 AliasType aliasType = processAliasFromValue(path, value, errorCode);
1760 if (U_FAILURE(errorCode)) { return; }
1761 if (aliasType == SAME_CALENDAR) {
1762 // Store the alias path and the current path on aliasPathPairs
1763 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1764 aliasPathPairs.addElementX(aliasRelativePathCopy.getAlias(), errorCode);
1765 if (U_FAILURE(errorCode)) { return; }
1766 // Only release ownership after aliasPathPairs takes it (no error happened):
1767 aliasRelativePathCopy.orphan();
1768 LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode);
1769 aliasPathPairs.addElementX(pathCopy.getAlias(), errorCode);
1770 if (U_FAILURE(errorCode)) { return; }
1771 // Only release ownership after aliasPathPairs takes it (no error happened):
1772 pathCopy.orphan();
1773
1774 // Drop the latest key on the path and continue
1775 path.retainBetween(0, pathLength);
1776 continue;
1777 }
1778 U_ASSERT(aliasType == NONE);
1779
1780 // == Handle data ==
1781 if (value.getType() == URES_ARRAY) {
1782 // We are on a leaf, store the array
1783 ResourceArray rDataArray = value.getArray(errorCode);
1784 int32_t dataArraySize = rDataArray.getSize();
1785 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1786 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1787 arrays.put(path, dataArray.orphan(), errorCode);
1788 arraySizes.puti(path, dataArraySize, errorCode);
1789 if (U_FAILURE(errorCode)) { return; }
1790 } else if (value.getType() == URES_TABLE) {
1791 // We are not on a leaf, recursively process the subtable.
1792 processResource(path, key, value, errorCode);
1793 if (U_FAILURE(errorCode)) { return; }
1794 }
1795
1796 // Drop the latest key on the path
1797 path.retainBetween(0, pathLength);
1798 }
1799 }
1800
1801 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
processAliasFromValue__anon5578a7220111::CalendarDataSink1802 AliasType processAliasFromValue(UnicodeString ¤tRelativePath, ResourceValue &value,
1803 UErrorCode &errorCode) {
1804 if (U_FAILURE(errorCode)) { return NONE; }
1805
1806 if (value.getType() == URES_ALIAS) {
1807 int32_t aliasPathSize;
1808 const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1809 if (U_FAILURE(errorCode)) { return NONE; }
1810 UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1811 const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
1812 if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1813 && aliasPath.length() > aliasPrefixLength) {
1814 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
1815 if (typeLimit > aliasPrefixLength) {
1816 const UnicodeString aliasCalendarType =
1817 aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1818 aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1819
1820 if (currentCalendarType == aliasCalendarType
1821 && currentRelativePath != aliasRelativePath) {
1822 // If we have an alias to the same calendar, the path to the resource must be different
1823 return SAME_CALENDAR;
1824
1825 } else if (currentCalendarType != aliasCalendarType
1826 && currentRelativePath == aliasRelativePath) {
1827 // If we have an alias to a different calendar, the path to the resource must be the same
1828 if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
1829 return GREGORIAN;
1830 } else if (nextCalendarType.isBogus()) {
1831 nextCalendarType = aliasCalendarType;
1832 return DIFFERENT_CALENDAR;
1833 } else if (nextCalendarType == aliasCalendarType) {
1834 return DIFFERENT_CALENDAR;
1835 }
1836 }
1837 }
1838 }
1839 errorCode = U_INTERNAL_PROGRAM_ERROR;
1840 return NONE;
1841 }
1842 return NONE;
1843 }
1844
1845 // Deleter function to be used by 'arrays'
deleteUnicodeStringArray__anon5578a7220111::CalendarDataSink1846 static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1847 delete[] static_cast<UnicodeString *>(uArray);
1848 }
1849 };
1850 // Virtual destructors have to be defined out of line
~CalendarDataSink()1851 CalendarDataSink::~CalendarDataSink() {
1852 arrays.setValueDeleter(deleteUnicodeStringArray);
1853 }
1854 }
1855
1856 //------------------------------------------------------
1857
1858 static void
initField(UnicodeString ** field,int32_t & length,const UChar * data,LastResortSize numStr,LastResortSize strLen,UErrorCode & status)1859 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1860 if (U_SUCCESS(status)) {
1861 length = numStr;
1862 *field = newUnicodeStringArray((size_t)numStr);
1863 if (*field) {
1864 for(int32_t i = 0; i<length; i++) {
1865 // readonly aliases - all "data" strings are constant
1866 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1867 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1868 }
1869 }
1870 else {
1871 length = 0;
1872 status = U_MEMORY_ALLOCATION_ERROR;
1873 }
1874 }
1875 }
1876
1877 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,UErrorCode & status)1878 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1879 if (U_SUCCESS(status)) {
1880 UnicodeString keyUString(key.data(), -1, US_INV);
1881 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1882
1883 if (array != NULL) {
1884 length = sink.arraySizes.geti(keyUString);
1885 *field = array;
1886 // DateFormatSymbols takes ownership of the array:
1887 sink.arrays.remove(keyUString);
1888 } else {
1889 length = 0;
1890 status = U_MISSING_RESOURCE_ERROR;
1891 }
1892 }
1893 }
1894
1895 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,int32_t arrayOffset,UErrorCode & status)1896 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1897 if (U_SUCCESS(status)) {
1898 UnicodeString keyUString(key.data(), -1, US_INV);
1899 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1900
1901 if (array != NULL) {
1902 int32_t arrayLength = sink.arraySizes.geti(keyUString);
1903 length = arrayLength + arrayOffset;
1904 *field = new UnicodeString[length];
1905 if (*field == NULL) {
1906 status = U_MEMORY_ALLOCATION_ERROR;
1907 return;
1908 }
1909 uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1910 } else {
1911 length = 0;
1912 status = U_MISSING_RESOURCE_ERROR;
1913 }
1914 }
1915 }
1916
1917 static void
initLeapMonthPattern(UnicodeString * field,int32_t index,CalendarDataSink & sink,CharString & path,UErrorCode & status)1918 initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
1919 field[index].remove();
1920 if (U_SUCCESS(status)) {
1921 UnicodeString pathUString(path.data(), -1, US_INV);
1922 Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
1923 if (leapMonthTable != NULL) {
1924 UnicodeString leapLabel(FALSE, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
1925 UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
1926 if (leapMonthPattern != NULL) {
1927 field[index].fastCopyFrom(*leapMonthPattern);
1928 } else {
1929 field[index].setToBogus();
1930 }
1931 return;
1932 }
1933 status = U_MISSING_RESOURCE_ERROR;
1934 }
1935 }
1936
1937 static CharString
buildResourcePath(CharString & path,const char * segment1,UErrorCode & errorCode)1938 &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
1939 return path.clear().append(segment1, -1, errorCode);
1940 }
1941
1942 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,UErrorCode & errorCode)1943 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1944 UErrorCode &errorCode) {
1945 return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
1946 .append(segment2, -1, errorCode);
1947 }
1948
1949 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,UErrorCode & errorCode)1950 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1951 const char* segment3, UErrorCode &errorCode) {
1952 return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
1953 .append(segment3, -1, errorCode);
1954 }
1955
1956 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,const char * segment4,UErrorCode & errorCode)1957 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1958 const char* segment3, const char* segment4, UErrorCode &errorCode) {
1959 return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
1960 .append(segment4, -1, errorCode);
1961 }
1962
1963 typedef struct {
1964 const char * usageTypeName;
1965 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1966 } ContextUsageTypeNameToEnumValue;
1967
1968 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1969 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1970 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1971 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
1972 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1973 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
1974 { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
1975 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
1976 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
1977 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1978 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1979 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
1980 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1981 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
1982 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
1983 { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1984 };
1985
1986 // Resource keys to look up localized strings for day periods.
1987 // The first one must be midnight and the second must be noon, so that their indices coincide
1988 // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1989 static const char *dayPeriodKeys[] = {"midnight", "noon",
1990 "morning1", "afternoon1", "evening1", "night1",
1991 "morning2", "afternoon2", "evening2", "night2"};
1992
loadDayPeriodStrings(CalendarDataSink & sink,CharString & path,int32_t & stringCount,UErrorCode & status)1993 UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
1994 int32_t &stringCount, UErrorCode &status) {
1995 if (U_FAILURE(status)) { return NULL; }
1996
1997 UnicodeString pathUString(path.data(), -1, US_INV);
1998 Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
1999
2000 stringCount = UPRV_LENGTHOF(dayPeriodKeys);
2001 UnicodeString *strings = new UnicodeString[stringCount];
2002 if (strings == NULL) {
2003 status = U_MEMORY_ALLOCATION_ERROR;
2004 return NULL;
2005 }
2006
2007 if (map != NULL) {
2008 for (int32_t i = 0; i < stringCount; ++i) {
2009 UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
2010 UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2011 if (dayPeriod != NULL) {
2012 strings[i].fastCopyFrom(*dayPeriod);
2013 } else {
2014 strings[i].setToBogus();
2015 }
2016 }
2017 } else {
2018 for (int32_t i = 0; i < stringCount; i++) {
2019 strings[i].setToBogus();
2020 }
2021 }
2022 return strings;
2023 }
2024
2025
2026 void
initializeData(const Locale & locale,const char * type,UErrorCode & status,UBool useLastResortData)2027 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2028 {
2029 int32_t len = 0;
2030 /* In case something goes wrong, initialize all of the data to NULL. */
2031 fEras = NULL;
2032 fErasCount = 0;
2033 fEraNames = NULL;
2034 fEraNamesCount = 0;
2035 fNarrowEras = NULL;
2036 fNarrowErasCount = 0;
2037 fMonths = NULL;
2038 fMonthsCount=0;
2039 fShortMonths = NULL;
2040 fShortMonthsCount=0;
2041 fNarrowMonths = NULL;
2042 fNarrowMonthsCount=0;
2043 fStandaloneMonths = NULL;
2044 fStandaloneMonthsCount=0;
2045 fStandaloneShortMonths = NULL;
2046 fStandaloneShortMonthsCount=0;
2047 fStandaloneNarrowMonths = NULL;
2048 fStandaloneNarrowMonthsCount=0;
2049 fWeekdays = NULL;
2050 fWeekdaysCount=0;
2051 fShortWeekdays = NULL;
2052 fShortWeekdaysCount=0;
2053 fShorterWeekdays = NULL;
2054 fShorterWeekdaysCount=0;
2055 fNarrowWeekdays = NULL;
2056 fNarrowWeekdaysCount=0;
2057 fStandaloneWeekdays = NULL;
2058 fStandaloneWeekdaysCount=0;
2059 fStandaloneShortWeekdays = NULL;
2060 fStandaloneShortWeekdaysCount=0;
2061 fStandaloneShorterWeekdays = NULL;
2062 fStandaloneShorterWeekdaysCount=0;
2063 fStandaloneNarrowWeekdays = NULL;
2064 fStandaloneNarrowWeekdaysCount=0;
2065 fAmPms = NULL;
2066 fAmPmsCount=0;
2067 fNarrowAmPms = NULL;
2068 fNarrowAmPmsCount=0;
2069 fTimeSeparator.setToBogus();
2070 fQuarters = NULL;
2071 fQuartersCount = 0;
2072 fShortQuarters = NULL;
2073 fShortQuartersCount = 0;
2074 fNarrowQuarters = NULL;
2075 fNarrowQuartersCount = 0;
2076 fStandaloneQuarters = NULL;
2077 fStandaloneQuartersCount = 0;
2078 fStandaloneShortQuarters = NULL;
2079 fStandaloneShortQuartersCount = 0;
2080 fStandaloneNarrowQuarters = NULL;
2081 fStandaloneNarrowQuartersCount = 0;
2082 fLeapMonthPatterns = NULL;
2083 fLeapMonthPatternsCount = 0;
2084 fShortYearNames = NULL;
2085 fShortYearNamesCount = 0;
2086 fShortZodiacNames = NULL;
2087 fShortZodiacNamesCount = 0;
2088 fZoneStringsRowCount = 0;
2089 fZoneStringsColCount = 0;
2090 fZoneStrings = NULL;
2091 fLocaleZoneStrings = NULL;
2092 fAbbreviatedDayPeriods = NULL;
2093 fAbbreviatedDayPeriodsCount = 0;
2094 fWideDayPeriods = NULL;
2095 fWideDayPeriodsCount = 0;
2096 fNarrowDayPeriods = NULL;
2097 fNarrowDayPeriodsCount = 0;
2098 fStandaloneAbbreviatedDayPeriods = NULL;
2099 fStandaloneAbbreviatedDayPeriodsCount = 0;
2100 fStandaloneWideDayPeriods = NULL;
2101 fStandaloneWideDayPeriodsCount = 0;
2102 fStandaloneNarrowDayPeriods = NULL;
2103 fStandaloneNarrowDayPeriodsCount = 0;
2104 uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
2105
2106 // We need to preserve the requested locale for
2107 // lazy ZoneStringFormat instantiation. ZoneStringFormat
2108 // is region sensitive, thus, bundle locale bundle's locale
2109 // is not sufficient.
2110 fZSFLocale = locale;
2111
2112 if (U_FAILURE(status)) return;
2113
2114 // Create a CalendarDataSink to process this data and the resource bundles
2115 CalendarDataSink calendarSink(status);
2116 UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
2117 UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
2118
2119 if (U_FAILURE(status)) return;
2120
2121 // Iterate over the resource bundle data following the fallbacks through different calendar types
2122 UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
2123 while (!calendarType.isBogus()) {
2124 CharString calendarTypeBuffer;
2125 calendarTypeBuffer.appendInvariantChars(calendarType, status);
2126 if (U_FAILURE(status)) { return; }
2127 const char *calendarTypeCArray = calendarTypeBuffer.data();
2128
2129 // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2130 UErrorCode oldStatus = status;
2131 UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
2132 if (status == U_MISSING_RESOURCE_ERROR) {
2133 ures_close(ctb);
2134 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
2135 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2136 calendarSink.visitAllResources();
2137 status = oldStatus;
2138 continue;
2139 }
2140 return;
2141 }
2142
2143 calendarSink.preEnumerate(calendarType);
2144 ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
2145 ures_close(ctb);
2146 if (U_FAILURE(status)) break;
2147
2148 // Stop loading when gregorian was loaded
2149 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2150 break;
2151 }
2152
2153 // Get the next calendar type to process from the sink
2154 calendarType = calendarSink.nextCalendarType;
2155
2156 // Gregorian is always the last fallback
2157 if (calendarType.isBogus()) {
2158 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2159 calendarSink.visitAllResources();
2160 }
2161 }
2162
2163 // CharString object to build paths
2164 CharString path;
2165
2166 // Load Leap Month Patterns
2167 UErrorCode tempStatus = status;
2168 fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2169 if (fLeapMonthPatterns) {
2170 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2171 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2172 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2173 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2174 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2175 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2176 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2177 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2178 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2179 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2180 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2181 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2182 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2183 buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2184 if (U_SUCCESS(tempStatus)) {
2185 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2186 // The ordering of the following statements is important.
2187 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
2188 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2189 }
2190 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
2191 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
2192 }
2193 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
2194 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2195 }
2196 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
2197 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
2198 }
2199 // end of hack
2200 fLeapMonthPatternsCount = kMonthPatternsCount;
2201 } else {
2202 delete[] fLeapMonthPatterns;
2203 fLeapMonthPatterns = NULL;
2204 }
2205 }
2206
2207 // Load cyclic names sets
2208 tempStatus = status;
2209 initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2210 buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2211 initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2212 buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2213
2214 // Load context transforms and capitalization
2215 tempStatus = U_ZERO_ERROR;
2216 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
2217 if (U_SUCCESS(tempStatus)) {
2218 UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
2219 if (U_SUCCESS(tempStatus)) {
2220 UResourceBundle *contextTransformUsage;
2221 while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
2222 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
2223 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
2224 const char* usageType = ures_getKey(contextTransformUsage);
2225 if (usageType != NULL) {
2226 const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2227 int32_t compResult = 0;
2228 // linear search; list is short and we cannot be sure that bsearch is available
2229 while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2230 ++typeMapPtr;
2231 }
2232 if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
2233 fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2234 fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2235 }
2236 }
2237 }
2238 tempStatus = U_ZERO_ERROR;
2239 ures_close(contextTransformUsage);
2240 }
2241 ures_close(contextTransforms);
2242 }
2243
2244 tempStatus = U_ZERO_ERROR;
2245 const LocalPointer<NumberingSystem> numberingSystem(
2246 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2247 if (U_SUCCESS(tempStatus)) {
2248 // These functions all fail gracefully if passed NULL pointers and
2249 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2250 // to check for errors once after all calls are made.
2251 const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
2252 localeBundle, gNumberElementsTag, NULL, &tempStatus));
2253 const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
2254 numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
2255 const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
2256 nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
2257 fTimeSeparator = ures_getUnicodeStringByKey(
2258 symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2259 if (U_FAILURE(tempStatus)) {
2260 fTimeSeparator.setToBogus();
2261 }
2262 }
2263
2264 ures_close(localeBundle);
2265 }
2266
2267 if (fTimeSeparator.isBogus()) {
2268 fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2269 }
2270
2271 // Load day periods
2272 fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2273 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2274 fWideDayPeriodsCount, status);
2275 fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2276 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2277 fNarrowDayPeriodsCount, status);
2278 fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2279 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2280 fAbbreviatedDayPeriodsCount, status);
2281 fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2282 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2283 fStandaloneWideDayPeriodsCount, status);
2284 fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2285 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2286 fStandaloneNarrowDayPeriodsCount, status);
2287 fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2288 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2289 fStandaloneAbbreviatedDayPeriodsCount, status);
2290
2291 U_LOCALE_BASED(locBased, *this);
2292 // if we make it to here, the resource data is cool, and we can get everything out
2293 // of it that we need except for the time-zone and localized-pattern data, which
2294 // are stored in a separate file
2295 locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
2296 ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
2297
2298 // Load eras
2299 initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
2300 UErrorCode oldStatus = status;
2301 initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
2302 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2303 status = oldStatus;
2304 assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
2305 }
2306 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2307 oldStatus = status;
2308 initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
2309 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2310 status = oldStatus;
2311 assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
2312 }
2313
2314 // Load month names
2315 initField(&fMonths, fMonthsCount, calendarSink,
2316 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2317 initField(&fShortMonths, fShortMonthsCount, calendarSink,
2318 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2319 initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2320 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2321 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
2322 status = U_ZERO_ERROR;
2323 assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
2324 }
2325 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2326 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2327 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
2328 status = U_ZERO_ERROR;
2329 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
2330 }
2331
2332 UErrorCode narrowMonthsEC = status;
2333 UErrorCode standaloneNarrowMonthsEC = status;
2334 initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2335 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2336 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2337 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2338 if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
2339 // If format/narrow not available, use standalone/narrow
2340 assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
2341 } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2342 // If standalone/narrow not available, use format/narrow
2343 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
2344 } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2345 // If neither is available, use format/abbreviated
2346 assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2347 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2348 }
2349
2350 // Load AM/PM markers; if wide or narrow not available, use short
2351 UErrorCode ampmStatus = U_ZERO_ERROR;
2352 initField(&fAmPms, fAmPmsCount, calendarSink,
2353 buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2354 if (U_FAILURE(ampmStatus)) {
2355 initField(&fAmPms, fAmPmsCount, calendarSink,
2356 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2357 }
2358 ampmStatus = U_ZERO_ERROR;
2359 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2360 buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2361 if (U_FAILURE(ampmStatus)) {
2362 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2363 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2364 }
2365
2366 // Load quarters
2367 initField(&fQuarters, fQuartersCount, calendarSink,
2368 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2369 initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2370 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2371
2372 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2373 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2374 if(status == U_MISSING_RESOURCE_ERROR) {
2375 status = U_ZERO_ERROR;
2376 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2377 }
2378 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2379 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2380 if(status == U_MISSING_RESOURCE_ERROR) {
2381 status = U_ZERO_ERROR;
2382 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
2383 }
2384
2385 // unlike the fields above, narrow format quarters fall back on narrow standalone quarters
2386 initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, calendarSink,
2387 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesNarrowTag, status), status);
2388 initField(&fNarrowQuarters, fNarrowQuartersCount, calendarSink,
2389 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesNarrowTag, status), status);
2390 if(status == U_MISSING_RESOURCE_ERROR) {
2391 status = U_ZERO_ERROR;
2392 assignArray(fNarrowQuarters, fNarrowQuartersCount, fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount);
2393 }
2394
2395 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2396 /*
2397 // fastCopyFrom()/setTo() - see assignArray comments
2398 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2399 fLocalPatternChars.setTo(TRUE, resStr, len);
2400 // If the locale data does not include new pattern chars, use the defaults
2401 // TODO: Consider making this an error, since this may add conflicting characters.
2402 if (len < PATTERN_CHARS_LEN) {
2403 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2404 }
2405 */
2406 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2407
2408 // Format wide weekdays -> fWeekdays
2409 // {sfb} fixed to handle 1-based weekdays
2410 initField(&fWeekdays, fWeekdaysCount, calendarSink,
2411 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2412
2413 // Format abbreviated weekdays -> fShortWeekdays
2414 initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2415 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2416
2417 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2418 initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2419 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2420 if (status == U_MISSING_RESOURCE_ERROR) {
2421 status = U_ZERO_ERROR;
2422 assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2423 }
2424
2425 // Stand-alone wide weekdays -> fStandaloneWeekdays
2426 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2427 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2428 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
2429 status = U_ZERO_ERROR;
2430 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
2431 }
2432
2433 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2434 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2435 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2436 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
2437 status = U_ZERO_ERROR;
2438 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2439 }
2440
2441 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2442 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2443 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2444 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
2445 status = U_ZERO_ERROR;
2446 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
2447 }
2448
2449 // Format narrow weekdays -> fNarrowWeekdays
2450 UErrorCode narrowWeeksEC = status;
2451 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2452 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2453 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2454 UErrorCode standaloneNarrowWeeksEC = status;
2455 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2456 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2457
2458 if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
2459 // If format/narrow not available, use standalone/narrow
2460 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
2461 } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
2462 // If standalone/narrow not available, use format/narrow
2463 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
2464 } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
2465 // If neither is available, use format/abbreviated
2466 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2467 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2468 }
2469
2470 // Last resort fallback in case previous data wasn't loaded
2471 if (U_FAILURE(status))
2472 {
2473 if (useLastResortData)
2474 {
2475 // Handle the case in which there is no resource data present.
2476 // We don't have to generate usable patterns in this situation;
2477 // we just need to produce something that will be semi-intelligible
2478 // in most locales.
2479
2480 status = U_USING_FALLBACK_WARNING;
2481 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2482 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2483 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2484 initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2485 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2486 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2487 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2488 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2489 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2490 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2491 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2492 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2493 initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2494 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2495 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2496 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2497 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2498 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2499 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2500 initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2501 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2502 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2503 initField(&fNarrowQuarters, fNarrowQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2504 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2505 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2506 initField(&fStandaloneNarrowQuarters, fStandaloneNarrowQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2507 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2508 }
2509 }
2510
2511 // Close resources
2512 ures_close(cb);
2513 ures_close(rb);
2514 }
2515
2516 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const2517 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
2518 U_LOCALE_BASED(locBased, *this);
2519 return locBased.getLocale(type, status);
2520 }
2521
2522 U_NAMESPACE_END
2523
2524 #endif /* #if !UCONFIG_NO_FORMATTING */
2525
2526 //eof
2527