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(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount);
396 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount);
397 assignArray(fWideDayPeriods, fWideDayPeriodsCount,
398 other.fWideDayPeriods, other.fWideDayPeriodsCount);
399 assignArray(fNarrowDayPeriods, fNarrowDayPeriodsCount,
400 other.fNarrowDayPeriods, other.fNarrowDayPeriodsCount);
401 assignArray(fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount,
402 other.fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriodsCount);
403 assignArray(fStandaloneWideDayPeriods, fStandaloneWideDayPeriodsCount,
404 other.fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriodsCount);
405 assignArray(fStandaloneNarrowDayPeriods, fStandaloneNarrowDayPeriodsCount,
406 other.fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriodsCount);
407 assignArray(fStandaloneAbbreviatedDayPeriods, fStandaloneAbbreviatedDayPeriodsCount,
408 other.fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriodsCount);
409 if (other.fLeapMonthPatterns != NULL) {
410 assignArray(fLeapMonthPatterns, fLeapMonthPatternsCount, other.fLeapMonthPatterns, other.fLeapMonthPatternsCount);
411 } else {
412 fLeapMonthPatterns = NULL;
413 fLeapMonthPatternsCount = 0;
414 }
415 if (other.fShortYearNames != NULL) {
416 assignArray(fShortYearNames, fShortYearNamesCount, other.fShortYearNames, other.fShortYearNamesCount);
417 } else {
418 fShortYearNames = NULL;
419 fShortYearNamesCount = 0;
420 }
421 if (other.fShortZodiacNames != NULL) {
422 assignArray(fShortZodiacNames, fShortZodiacNamesCount, other.fShortZodiacNames, other.fShortZodiacNamesCount);
423 } else {
424 fShortZodiacNames = NULL;
425 fShortZodiacNamesCount = 0;
426 }
427
428 if (other.fZoneStrings != NULL) {
429 fZoneStringsColCount = other.fZoneStringsColCount;
430 fZoneStringsRowCount = other.fZoneStringsRowCount;
431 createZoneStrings((const UnicodeString**)other.fZoneStrings);
432
433 } else {
434 fZoneStrings = NULL;
435 fZoneStringsColCount = 0;
436 fZoneStringsRowCount = 0;
437 }
438 fZSFLocale = other.fZSFLocale;
439 // Other zone strings data is created on demand
440 fLocaleZoneStrings = NULL;
441
442 // fastCopyFrom() - see assignArray comments
443 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars);
444
445 uprv_memcpy(fCapitalization, other.fCapitalization, sizeof(fCapitalization));
446 }
447
448 /**
449 * Assignment operator.
450 */
operator =(const DateFormatSymbols & other)451 DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
452 {
453 if (this == &other) { return *this; } // self-assignment: no-op
454 dispose();
455 copyData(other);
456
457 return *this;
458 }
459
~DateFormatSymbols()460 DateFormatSymbols::~DateFormatSymbols()
461 {
462 dispose();
463 }
464
dispose()465 void DateFormatSymbols::dispose()
466 {
467 delete[] fEras;
468 delete[] fEraNames;
469 delete[] fNarrowEras;
470 delete[] fMonths;
471 delete[] fShortMonths;
472 delete[] fNarrowMonths;
473 delete[] fStandaloneMonths;
474 delete[] fStandaloneShortMonths;
475 delete[] fStandaloneNarrowMonths;
476 delete[] fWeekdays;
477 delete[] fShortWeekdays;
478 delete[] fShorterWeekdays;
479 delete[] fNarrowWeekdays;
480 delete[] fStandaloneWeekdays;
481 delete[] fStandaloneShortWeekdays;
482 delete[] fStandaloneShorterWeekdays;
483 delete[] fStandaloneNarrowWeekdays;
484 delete[] fAmPms;
485 delete[] fNarrowAmPms;
486 delete[] fQuarters;
487 delete[] fShortQuarters;
488 delete[] fStandaloneQuarters;
489 delete[] fStandaloneShortQuarters;
490 delete[] fLeapMonthPatterns;
491 delete[] fShortYearNames;
492 delete[] fShortZodiacNames;
493 delete[] fAbbreviatedDayPeriods;
494 delete[] fWideDayPeriods;
495 delete[] fNarrowDayPeriods;
496 delete[] fStandaloneAbbreviatedDayPeriods;
497 delete[] fStandaloneWideDayPeriods;
498 delete[] fStandaloneNarrowDayPeriods;
499
500 disposeZoneStrings();
501 }
502
disposeZoneStrings()503 void DateFormatSymbols::disposeZoneStrings()
504 {
505 if (fZoneStrings) {
506 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
507 delete[] fZoneStrings[row];
508 }
509 uprv_free(fZoneStrings);
510 }
511 if (fLocaleZoneStrings) {
512 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) {
513 delete[] fLocaleZoneStrings[row];
514 }
515 uprv_free(fLocaleZoneStrings);
516 }
517
518 fZoneStrings = NULL;
519 fLocaleZoneStrings = NULL;
520 fZoneStringsRowCount = 0;
521 fZoneStringsColCount = 0;
522 }
523
524 UBool
arrayCompare(const UnicodeString * array1,const UnicodeString * array2,int32_t count)525 DateFormatSymbols::arrayCompare(const UnicodeString* array1,
526 const UnicodeString* array2,
527 int32_t count)
528 {
529 if (array1 == array2) return TRUE;
530 while (count>0)
531 {
532 --count;
533 if (array1[count] != array2[count]) return FALSE;
534 }
535 return TRUE;
536 }
537
538 UBool
operator ==(const DateFormatSymbols & other) const539 DateFormatSymbols::operator==(const DateFormatSymbols& other) const
540 {
541 // First do cheap comparisons
542 if (this == &other) {
543 return TRUE;
544 }
545 if (fErasCount == other.fErasCount &&
546 fEraNamesCount == other.fEraNamesCount &&
547 fNarrowErasCount == other.fNarrowErasCount &&
548 fMonthsCount == other.fMonthsCount &&
549 fShortMonthsCount == other.fShortMonthsCount &&
550 fNarrowMonthsCount == other.fNarrowMonthsCount &&
551 fStandaloneMonthsCount == other.fStandaloneMonthsCount &&
552 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount &&
553 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount &&
554 fWeekdaysCount == other.fWeekdaysCount &&
555 fShortWeekdaysCount == other.fShortWeekdaysCount &&
556 fShorterWeekdaysCount == other.fShorterWeekdaysCount &&
557 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount &&
558 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount &&
559 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount &&
560 fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount &&
561 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount &&
562 fAmPmsCount == other.fAmPmsCount &&
563 fNarrowAmPmsCount == other.fNarrowAmPmsCount &&
564 fQuartersCount == other.fQuartersCount &&
565 fShortQuartersCount == other.fShortQuartersCount &&
566 fStandaloneQuartersCount == other.fStandaloneQuartersCount &&
567 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount &&
568 fLeapMonthPatternsCount == other.fLeapMonthPatternsCount &&
569 fShortYearNamesCount == other.fShortYearNamesCount &&
570 fShortZodiacNamesCount == other.fShortZodiacNamesCount &&
571 fAbbreviatedDayPeriodsCount == other.fAbbreviatedDayPeriodsCount &&
572 fWideDayPeriodsCount == other.fWideDayPeriodsCount &&
573 fNarrowDayPeriodsCount == other.fNarrowDayPeriodsCount &&
574 fStandaloneAbbreviatedDayPeriodsCount == other.fStandaloneAbbreviatedDayPeriodsCount &&
575 fStandaloneWideDayPeriodsCount == other.fStandaloneWideDayPeriodsCount &&
576 fStandaloneNarrowDayPeriodsCount == other.fStandaloneNarrowDayPeriodsCount &&
577 (uprv_memcmp(fCapitalization, other.fCapitalization, sizeof(fCapitalization))==0))
578 {
579 // Now compare the arrays themselves
580 if (arrayCompare(fEras, other.fEras, fErasCount) &&
581 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) &&
582 arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) &&
583 arrayCompare(fMonths, other.fMonths, fMonthsCount) &&
584 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) &&
585 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) &&
586 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) &&
587 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) &&
588 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) &&
589 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) &&
590 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) &&
591 arrayCompare(fShorterWeekdays, other.fShorterWeekdays, fShorterWeekdaysCount) &&
592 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) &&
593 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) &&
594 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) &&
595 arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) &&
596 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) &&
597 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) &&
598 arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) &&
599 fTimeSeparator == other.fTimeSeparator &&
600 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) &&
601 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) &&
602 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) &&
603 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) &&
604 arrayCompare(fLeapMonthPatterns, other.fLeapMonthPatterns, fLeapMonthPatternsCount) &&
605 arrayCompare(fShortYearNames, other.fShortYearNames, fShortYearNamesCount) &&
606 arrayCompare(fShortZodiacNames, other.fShortZodiacNames, fShortZodiacNamesCount) &&
607 arrayCompare(fAbbreviatedDayPeriods, other.fAbbreviatedDayPeriods, fAbbreviatedDayPeriodsCount) &&
608 arrayCompare(fWideDayPeriods, other.fWideDayPeriods, fWideDayPeriodsCount) &&
609 arrayCompare(fNarrowDayPeriods, other.fNarrowDayPeriods, fNarrowDayPeriodsCount) &&
610 arrayCompare(fStandaloneAbbreviatedDayPeriods, other.fStandaloneAbbreviatedDayPeriods,
611 fStandaloneAbbreviatedDayPeriodsCount) &&
612 arrayCompare(fStandaloneWideDayPeriods, other.fStandaloneWideDayPeriods,
613 fStandaloneWideDayPeriodsCount) &&
614 arrayCompare(fStandaloneNarrowDayPeriods, other.fStandaloneNarrowDayPeriods,
615 fStandaloneWideDayPeriodsCount))
616 {
617 // Compare the contents of fZoneStrings
618 if (fZoneStrings == NULL && other.fZoneStrings == NULL) {
619 if (fZSFLocale == other.fZSFLocale) {
620 return TRUE;
621 }
622 } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) {
623 if (fZoneStringsRowCount == other.fZoneStringsRowCount
624 && fZoneStringsColCount == other.fZoneStringsColCount) {
625 UBool cmpres = TRUE;
626 for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) {
627 cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount);
628 }
629 return cmpres;
630 }
631 }
632 return FALSE;
633 }
634 }
635 return FALSE;
636 }
637
638 //------------------------------------------------------
639
640 const UnicodeString*
getEras(int32_t & count) const641 DateFormatSymbols::getEras(int32_t &count) const
642 {
643 count = fErasCount;
644 return fEras;
645 }
646
647 const UnicodeString*
getEraNames(int32_t & count) const648 DateFormatSymbols::getEraNames(int32_t &count) const
649 {
650 count = fEraNamesCount;
651 return fEraNames;
652 }
653
654 const UnicodeString*
getNarrowEras(int32_t & count) const655 DateFormatSymbols::getNarrowEras(int32_t &count) const
656 {
657 count = fNarrowErasCount;
658 return fNarrowEras;
659 }
660
661 const UnicodeString*
getMonths(int32_t & count) const662 DateFormatSymbols::getMonths(int32_t &count) const
663 {
664 count = fMonthsCount;
665 return fMonths;
666 }
667
668 const UnicodeString*
getShortMonths(int32_t & count) const669 DateFormatSymbols::getShortMonths(int32_t &count) const
670 {
671 count = fShortMonthsCount;
672 return fShortMonths;
673 }
674
675 const UnicodeString*
getMonths(int32_t & count,DtContextType context,DtWidthType width) const676 DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const
677 {
678 UnicodeString *returnValue = NULL;
679
680 switch (context) {
681 case FORMAT :
682 switch(width) {
683 case WIDE :
684 count = fMonthsCount;
685 returnValue = fMonths;
686 break;
687 case ABBREVIATED :
688 case SHORT : // no month data for this, defaults to ABBREVIATED
689 count = fShortMonthsCount;
690 returnValue = fShortMonths;
691 break;
692 case NARROW :
693 count = fNarrowMonthsCount;
694 returnValue = fNarrowMonths;
695 break;
696 case DT_WIDTH_COUNT :
697 break;
698 }
699 break;
700 case STANDALONE :
701 switch(width) {
702 case WIDE :
703 count = fStandaloneMonthsCount;
704 returnValue = fStandaloneMonths;
705 break;
706 case ABBREVIATED :
707 case SHORT : // no month data for this, defaults to ABBREVIATED
708 count = fStandaloneShortMonthsCount;
709 returnValue = fStandaloneShortMonths;
710 break;
711 case NARROW :
712 count = fStandaloneNarrowMonthsCount;
713 returnValue = fStandaloneNarrowMonths;
714 break;
715 case DT_WIDTH_COUNT :
716 break;
717 }
718 break;
719 case DT_CONTEXT_COUNT :
720 break;
721 }
722 return returnValue;
723 }
724
725 const UnicodeString*
getWeekdays(int32_t & count) const726 DateFormatSymbols::getWeekdays(int32_t &count) const
727 {
728 count = fWeekdaysCount;
729 return fWeekdays;
730 }
731
732 const UnicodeString*
getShortWeekdays(int32_t & count) const733 DateFormatSymbols::getShortWeekdays(int32_t &count) const
734 {
735 count = fShortWeekdaysCount;
736 return fShortWeekdays;
737 }
738
739 const UnicodeString*
getWeekdays(int32_t & count,DtContextType context,DtWidthType width) const740 DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const
741 {
742 UnicodeString *returnValue = NULL;
743 switch (context) {
744 case FORMAT :
745 switch(width) {
746 case WIDE :
747 count = fWeekdaysCount;
748 returnValue = fWeekdays;
749 break;
750 case ABBREVIATED :
751 count = fShortWeekdaysCount;
752 returnValue = fShortWeekdays;
753 break;
754 case SHORT :
755 count = fShorterWeekdaysCount;
756 returnValue = fShorterWeekdays;
757 break;
758 case NARROW :
759 count = fNarrowWeekdaysCount;
760 returnValue = fNarrowWeekdays;
761 break;
762 case DT_WIDTH_COUNT :
763 break;
764 }
765 break;
766 case STANDALONE :
767 switch(width) {
768 case WIDE :
769 count = fStandaloneWeekdaysCount;
770 returnValue = fStandaloneWeekdays;
771 break;
772 case ABBREVIATED :
773 count = fStandaloneShortWeekdaysCount;
774 returnValue = fStandaloneShortWeekdays;
775 break;
776 case SHORT :
777 count = fStandaloneShorterWeekdaysCount;
778 returnValue = fStandaloneShorterWeekdays;
779 break;
780 case NARROW :
781 count = fStandaloneNarrowWeekdaysCount;
782 returnValue = fStandaloneNarrowWeekdays;
783 break;
784 case DT_WIDTH_COUNT :
785 break;
786 }
787 break;
788 case DT_CONTEXT_COUNT :
789 break;
790 }
791 return returnValue;
792 }
793
794 const UnicodeString*
getQuarters(int32_t & count,DtContextType context,DtWidthType width) const795 DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const
796 {
797 UnicodeString *returnValue = NULL;
798
799 switch (context) {
800 case FORMAT :
801 switch(width) {
802 case WIDE :
803 count = fQuartersCount;
804 returnValue = fQuarters;
805 break;
806 case ABBREVIATED :
807 case SHORT : // no quarter data for this, defaults to ABBREVIATED
808 count = fShortQuartersCount;
809 returnValue = fShortQuarters;
810 break;
811 case NARROW :
812 count = 0;
813 returnValue = NULL;
814 break;
815 case DT_WIDTH_COUNT :
816 break;
817 }
818 break;
819 case STANDALONE :
820 switch(width) {
821 case WIDE :
822 count = fStandaloneQuartersCount;
823 returnValue = fStandaloneQuarters;
824 break;
825 case ABBREVIATED :
826 case SHORT : // no quarter data for this, defaults to ABBREVIATED
827 count = fStandaloneShortQuartersCount;
828 returnValue = fStandaloneShortQuarters;
829 break;
830 case NARROW :
831 count = 0;
832 returnValue = NULL;
833 break;
834 case DT_WIDTH_COUNT :
835 break;
836 }
837 break;
838 case DT_CONTEXT_COUNT :
839 break;
840 }
841 return returnValue;
842 }
843
844 UnicodeString&
getTimeSeparatorString(UnicodeString & result) const845 DateFormatSymbols::getTimeSeparatorString(UnicodeString& result) const
846 {
847 // fastCopyFrom() - see assignArray comments
848 return result.fastCopyFrom(fTimeSeparator);
849 }
850
851 const UnicodeString*
getAmPmStrings(int32_t & count) const852 DateFormatSymbols::getAmPmStrings(int32_t &count) const
853 {
854 count = fAmPmsCount;
855 return fAmPms;
856 }
857
858 const UnicodeString*
getLeapMonthPatterns(int32_t & count) const859 DateFormatSymbols::getLeapMonthPatterns(int32_t &count) const
860 {
861 count = fLeapMonthPatternsCount;
862 return fLeapMonthPatterns;
863 }
864
865 const UnicodeString*
getYearNames(int32_t & count,DtContextType,DtWidthType) const866 DateFormatSymbols::getYearNames(int32_t& count,
867 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
868 {
869 count = fShortYearNamesCount;
870 return fShortYearNames;
871 }
872
873 void
setYearNames(const UnicodeString * yearNames,int32_t count,DtContextType context,DtWidthType width)874 DateFormatSymbols::setYearNames(const UnicodeString* yearNames, int32_t count,
875 DtContextType context, DtWidthType width)
876 {
877 if (context == FORMAT && width == ABBREVIATED) {
878 if (fShortYearNames) {
879 delete[] fShortYearNames;
880 }
881 fShortYearNames = newUnicodeStringArray(count);
882 uprv_arrayCopy(yearNames, fShortYearNames, count);
883 fShortYearNamesCount = count;
884 }
885 }
886
887 const UnicodeString*
getZodiacNames(int32_t & count,DtContextType,DtWidthType) const888 DateFormatSymbols::getZodiacNames(int32_t& count,
889 DtContextType /*ignored*/, DtWidthType /*ignored*/) const
890 {
891 count = fShortZodiacNamesCount;
892 return fShortZodiacNames;
893 }
894
895 void
setZodiacNames(const UnicodeString * zodiacNames,int32_t count,DtContextType context,DtWidthType width)896 DateFormatSymbols::setZodiacNames(const UnicodeString* zodiacNames, int32_t count,
897 DtContextType context, DtWidthType width)
898 {
899 if (context == FORMAT && width == ABBREVIATED) {
900 if (fShortZodiacNames) {
901 delete[] fShortZodiacNames;
902 }
903 fShortZodiacNames = newUnicodeStringArray(count);
904 uprv_arrayCopy(zodiacNames, fShortZodiacNames, count);
905 fShortZodiacNamesCount = count;
906 }
907 }
908
909 //------------------------------------------------------
910
911 void
setEras(const UnicodeString * erasArray,int32_t count)912 DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count)
913 {
914 // delete the old list if we own it
915 if (fEras)
916 delete[] fEras;
917
918 // we always own the new list, which we create here (we duplicate rather
919 // than adopting the list passed in)
920 fEras = newUnicodeStringArray(count);
921 uprv_arrayCopy(erasArray,fEras, count);
922 fErasCount = count;
923 }
924
925 void
setEraNames(const UnicodeString * eraNamesArray,int32_t count)926 DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count)
927 {
928 // delete the old list if we own it
929 if (fEraNames)
930 delete[] fEraNames;
931
932 // we always own the new list, which we create here (we duplicate rather
933 // than adopting the list passed in)
934 fEraNames = newUnicodeStringArray(count);
935 uprv_arrayCopy(eraNamesArray,fEraNames, count);
936 fEraNamesCount = count;
937 }
938
939 void
setNarrowEras(const UnicodeString * narrowErasArray,int32_t count)940 DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count)
941 {
942 // delete the old list if we own it
943 if (fNarrowEras)
944 delete[] fNarrowEras;
945
946 // we always own the new list, which we create here (we duplicate rather
947 // than adopting the list passed in)
948 fNarrowEras = newUnicodeStringArray(count);
949 uprv_arrayCopy(narrowErasArray,fNarrowEras, count);
950 fNarrowErasCount = count;
951 }
952
953 void
setMonths(const UnicodeString * monthsArray,int32_t count)954 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count)
955 {
956 // delete the old list if we own it
957 if (fMonths)
958 delete[] fMonths;
959
960 // we always own the new list, which we create here (we duplicate rather
961 // than adopting the list passed in)
962 fMonths = newUnicodeStringArray(count);
963 uprv_arrayCopy( monthsArray,fMonths,count);
964 fMonthsCount = count;
965 }
966
967 void
setShortMonths(const UnicodeString * shortMonthsArray,int32_t count)968 DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count)
969 {
970 // delete the old list if we own it
971 if (fShortMonths)
972 delete[] fShortMonths;
973
974 // we always own the new list, which we create here (we duplicate rather
975 // than adopting the list passed in)
976 fShortMonths = newUnicodeStringArray(count);
977 uprv_arrayCopy(shortMonthsArray,fShortMonths, count);
978 fShortMonthsCount = count;
979 }
980
981 void
setMonths(const UnicodeString * monthsArray,int32_t count,DtContextType context,DtWidthType width)982 DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width)
983 {
984 // delete the old list if we own it
985 // we always own the new list, which we create here (we duplicate rather
986 // than adopting the list passed in)
987
988 switch (context) {
989 case FORMAT :
990 switch (width) {
991 case WIDE :
992 if (fMonths)
993 delete[] fMonths;
994 fMonths = newUnicodeStringArray(count);
995 uprv_arrayCopy( monthsArray,fMonths,count);
996 fMonthsCount = count;
997 break;
998 case ABBREVIATED :
999 if (fShortMonths)
1000 delete[] fShortMonths;
1001 fShortMonths = newUnicodeStringArray(count);
1002 uprv_arrayCopy( monthsArray,fShortMonths,count);
1003 fShortMonthsCount = count;
1004 break;
1005 case NARROW :
1006 if (fNarrowMonths)
1007 delete[] fNarrowMonths;
1008 fNarrowMonths = newUnicodeStringArray(count);
1009 uprv_arrayCopy( monthsArray,fNarrowMonths,count);
1010 fNarrowMonthsCount = count;
1011 break;
1012 default :
1013 break;
1014 }
1015 break;
1016 case STANDALONE :
1017 switch (width) {
1018 case WIDE :
1019 if (fStandaloneMonths)
1020 delete[] fStandaloneMonths;
1021 fStandaloneMonths = newUnicodeStringArray(count);
1022 uprv_arrayCopy( monthsArray,fStandaloneMonths,count);
1023 fStandaloneMonthsCount = count;
1024 break;
1025 case ABBREVIATED :
1026 if (fStandaloneShortMonths)
1027 delete[] fStandaloneShortMonths;
1028 fStandaloneShortMonths = newUnicodeStringArray(count);
1029 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count);
1030 fStandaloneShortMonthsCount = count;
1031 break;
1032 case NARROW :
1033 if (fStandaloneNarrowMonths)
1034 delete[] fStandaloneNarrowMonths;
1035 fStandaloneNarrowMonths = newUnicodeStringArray(count);
1036 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count);
1037 fStandaloneNarrowMonthsCount = count;
1038 break;
1039 default :
1040 break;
1041 }
1042 break;
1043 case DT_CONTEXT_COUNT :
1044 break;
1045 }
1046 }
1047
setWeekdays(const UnicodeString * weekdaysArray,int32_t count)1048 void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count)
1049 {
1050 // delete the old list if we own it
1051 if (fWeekdays)
1052 delete[] fWeekdays;
1053
1054 // we always own the new list, which we create here (we duplicate rather
1055 // than adopting the list passed in)
1056 fWeekdays = newUnicodeStringArray(count);
1057 uprv_arrayCopy(weekdaysArray,fWeekdays,count);
1058 fWeekdaysCount = count;
1059 }
1060
1061 void
setShortWeekdays(const UnicodeString * shortWeekdaysArray,int32_t count)1062 DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count)
1063 {
1064 // delete the old list if we own it
1065 if (fShortWeekdays)
1066 delete[] fShortWeekdays;
1067
1068 // we always own the new list, which we create here (we duplicate rather
1069 // than adopting the list passed in)
1070 fShortWeekdays = newUnicodeStringArray(count);
1071 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count);
1072 fShortWeekdaysCount = count;
1073 }
1074
1075 void
setWeekdays(const UnicodeString * weekdaysArray,int32_t count,DtContextType context,DtWidthType width)1076 DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width)
1077 {
1078 // delete the old list if we own it
1079 // we always own the new list, which we create here (we duplicate rather
1080 // than adopting the list passed in)
1081
1082 switch (context) {
1083 case FORMAT :
1084 switch (width) {
1085 case WIDE :
1086 if (fWeekdays)
1087 delete[] fWeekdays;
1088 fWeekdays = newUnicodeStringArray(count);
1089 uprv_arrayCopy(weekdaysArray, fWeekdays, count);
1090 fWeekdaysCount = count;
1091 break;
1092 case ABBREVIATED :
1093 if (fShortWeekdays)
1094 delete[] fShortWeekdays;
1095 fShortWeekdays = newUnicodeStringArray(count);
1096 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count);
1097 fShortWeekdaysCount = count;
1098 break;
1099 case SHORT :
1100 if (fShorterWeekdays)
1101 delete[] fShorterWeekdays;
1102 fShorterWeekdays = newUnicodeStringArray(count);
1103 uprv_arrayCopy(weekdaysArray, fShorterWeekdays, count);
1104 fShorterWeekdaysCount = count;
1105 break;
1106 case NARROW :
1107 if (fNarrowWeekdays)
1108 delete[] fNarrowWeekdays;
1109 fNarrowWeekdays = newUnicodeStringArray(count);
1110 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count);
1111 fNarrowWeekdaysCount = count;
1112 break;
1113 case DT_WIDTH_COUNT :
1114 break;
1115 }
1116 break;
1117 case STANDALONE :
1118 switch (width) {
1119 case WIDE :
1120 if (fStandaloneWeekdays)
1121 delete[] fStandaloneWeekdays;
1122 fStandaloneWeekdays = newUnicodeStringArray(count);
1123 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count);
1124 fStandaloneWeekdaysCount = count;
1125 break;
1126 case ABBREVIATED :
1127 if (fStandaloneShortWeekdays)
1128 delete[] fStandaloneShortWeekdays;
1129 fStandaloneShortWeekdays = newUnicodeStringArray(count);
1130 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count);
1131 fStandaloneShortWeekdaysCount = count;
1132 break;
1133 case SHORT :
1134 if (fStandaloneShorterWeekdays)
1135 delete[] fStandaloneShorterWeekdays;
1136 fStandaloneShorterWeekdays = newUnicodeStringArray(count);
1137 uprv_arrayCopy(weekdaysArray, fStandaloneShorterWeekdays, count);
1138 fStandaloneShorterWeekdaysCount = count;
1139 break;
1140 case NARROW :
1141 if (fStandaloneNarrowWeekdays)
1142 delete[] fStandaloneNarrowWeekdays;
1143 fStandaloneNarrowWeekdays = newUnicodeStringArray(count);
1144 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count);
1145 fStandaloneNarrowWeekdaysCount = count;
1146 break;
1147 case DT_WIDTH_COUNT :
1148 break;
1149 }
1150 break;
1151 case DT_CONTEXT_COUNT :
1152 break;
1153 }
1154 }
1155
1156 void
setQuarters(const UnicodeString * quartersArray,int32_t count,DtContextType context,DtWidthType width)1157 DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width)
1158 {
1159 // delete the old list if we own it
1160 // we always own the new list, which we create here (we duplicate rather
1161 // than adopting the list passed in)
1162
1163 switch (context) {
1164 case FORMAT :
1165 switch (width) {
1166 case WIDE :
1167 if (fQuarters)
1168 delete[] fQuarters;
1169 fQuarters = newUnicodeStringArray(count);
1170 uprv_arrayCopy( quartersArray,fQuarters,count);
1171 fQuartersCount = count;
1172 break;
1173 case ABBREVIATED :
1174 if (fShortQuarters)
1175 delete[] fShortQuarters;
1176 fShortQuarters = newUnicodeStringArray(count);
1177 uprv_arrayCopy( quartersArray,fShortQuarters,count);
1178 fShortQuartersCount = count;
1179 break;
1180 case NARROW :
1181 /*
1182 if (fNarrowQuarters)
1183 delete[] fNarrowQuarters;
1184 fNarrowQuarters = newUnicodeStringArray(count);
1185 uprv_arrayCopy( quartersArray,fNarrowQuarters,count);
1186 fNarrowQuartersCount = count;
1187 */
1188 break;
1189 default :
1190 break;
1191 }
1192 break;
1193 case STANDALONE :
1194 switch (width) {
1195 case WIDE :
1196 if (fStandaloneQuarters)
1197 delete[] fStandaloneQuarters;
1198 fStandaloneQuarters = newUnicodeStringArray(count);
1199 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count);
1200 fStandaloneQuartersCount = count;
1201 break;
1202 case ABBREVIATED :
1203 if (fStandaloneShortQuarters)
1204 delete[] fStandaloneShortQuarters;
1205 fStandaloneShortQuarters = newUnicodeStringArray(count);
1206 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count);
1207 fStandaloneShortQuartersCount = count;
1208 break;
1209 case NARROW :
1210 /*
1211 if (fStandaloneNarrowQuarters)
1212 delete[] fStandaloneNarrowQuarters;
1213 fStandaloneNarrowQuarters = newUnicodeStringArray(count);
1214 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count);
1215 fStandaloneNarrowQuartersCount = count;
1216 */
1217 break;
1218 default :
1219 break;
1220 }
1221 break;
1222 case DT_CONTEXT_COUNT :
1223 break;
1224 }
1225 }
1226
1227 void
setAmPmStrings(const UnicodeString * amPmsArray,int32_t count)1228 DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count)
1229 {
1230 // delete the old list if we own it
1231 if (fAmPms) delete[] fAmPms;
1232
1233 // we always own the new list, which we create here (we duplicate rather
1234 // than adopting the list passed in)
1235 fAmPms = newUnicodeStringArray(count);
1236 uprv_arrayCopy(amPmsArray,fAmPms,count);
1237 fAmPmsCount = count;
1238 }
1239
1240 void
setTimeSeparatorString(const UnicodeString & newTimeSeparator)1241 DateFormatSymbols::setTimeSeparatorString(const UnicodeString& newTimeSeparator)
1242 {
1243 fTimeSeparator = newTimeSeparator;
1244 }
1245
1246 const UnicodeString**
getZoneStrings(int32_t & rowCount,int32_t & columnCount) const1247 DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const
1248 {
1249 const UnicodeString **result = NULL;
1250 static UMutex LOCK;
1251
1252 umtx_lock(&LOCK);
1253 if (fZoneStrings == NULL) {
1254 if (fLocaleZoneStrings == NULL) {
1255 ((DateFormatSymbols*)this)->initZoneStringsArray();
1256 }
1257 result = (const UnicodeString**)fLocaleZoneStrings;
1258 } else {
1259 result = (const UnicodeString**)fZoneStrings;
1260 }
1261 rowCount = fZoneStringsRowCount;
1262 columnCount = fZoneStringsColCount;
1263 umtx_unlock(&LOCK);
1264
1265 return result;
1266 }
1267
1268 // For now, we include all zones
1269 #define ZONE_SET UCAL_ZONE_TYPE_ANY
1270
1271 // This code must be called within a synchronized block
1272 void
initZoneStringsArray(void)1273 DateFormatSymbols::initZoneStringsArray(void) {
1274 if (fZoneStrings != NULL || fLocaleZoneStrings != NULL) {
1275 return;
1276 }
1277
1278 UErrorCode status = U_ZERO_ERROR;
1279
1280 StringEnumeration *tzids = NULL;
1281 UnicodeString ** zarray = NULL;
1282 TimeZoneNames *tzNames = NULL;
1283 int32_t rows = 0;
1284
1285 static const UTimeZoneNameType TYPES[] = {
1286 UTZNM_LONG_STANDARD, UTZNM_SHORT_STANDARD,
1287 UTZNM_LONG_DAYLIGHT, UTZNM_SHORT_DAYLIGHT
1288 };
1289 static const int32_t NUM_TYPES = 4;
1290
1291 do { // dummy do-while
1292
1293 tzids = TimeZone::createTimeZoneIDEnumeration(ZONE_SET, NULL, NULL, status);
1294 rows = tzids->count(status);
1295 if (U_FAILURE(status)) {
1296 break;
1297 }
1298
1299 // Allocate array
1300 int32_t size = rows * sizeof(UnicodeString*);
1301 zarray = (UnicodeString**)uprv_malloc(size);
1302 if (zarray == NULL) {
1303 status = U_MEMORY_ALLOCATION_ERROR;
1304 break;
1305 }
1306 uprv_memset(zarray, 0, size);
1307
1308 tzNames = TimeZoneNames::createInstance(fZSFLocale, status);
1309 tzNames->loadAllDisplayNames(status);
1310 if (U_FAILURE(status)) { break; }
1311
1312 const UnicodeString *tzid;
1313 int32_t i = 0;
1314 UDate now = Calendar::getNow();
1315 UnicodeString tzDispName;
1316
1317 while ((tzid = tzids->snext(status)) != 0) {
1318 if (U_FAILURE(status)) {
1319 break;
1320 }
1321
1322 zarray[i] = new UnicodeString[5];
1323 if (zarray[i] == NULL) {
1324 status = U_MEMORY_ALLOCATION_ERROR;
1325 break;
1326 }
1327
1328 zarray[i][0].setTo(*tzid);
1329 tzNames->getDisplayNames(*tzid, TYPES, NUM_TYPES, now, zarray[i]+1, status);
1330 i++;
1331 }
1332
1333 } while (FALSE);
1334
1335 if (U_FAILURE(status)) {
1336 if (zarray) {
1337 for (int32_t i = 0; i < rows; i++) {
1338 if (zarray[i]) {
1339 delete[] zarray[i];
1340 }
1341 }
1342 uprv_free(zarray);
1343 zarray = NULL;
1344 }
1345 }
1346
1347 if (tzNames) {
1348 delete tzNames;
1349 }
1350 if (tzids) {
1351 delete tzids;
1352 }
1353
1354 fLocaleZoneStrings = zarray;
1355 fZoneStringsRowCount = rows;
1356 fZoneStringsColCount = 1 + NUM_TYPES;
1357 }
1358
1359 void
setZoneStrings(const UnicodeString * const * strings,int32_t rowCount,int32_t columnCount)1360 DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount)
1361 {
1362 // since deleting a 2-d array is a pain in the butt, we offload that task to
1363 // a separate function
1364 disposeZoneStrings();
1365 // we always own the new list, which we create here (we duplicate rather
1366 // than adopting the list passed in)
1367 fZoneStringsRowCount = rowCount;
1368 fZoneStringsColCount = columnCount;
1369 createZoneStrings((const UnicodeString**)strings);
1370 }
1371
1372 //------------------------------------------------------
1373
1374 const char16_t * U_EXPORT2
getPatternUChars(void)1375 DateFormatSymbols::getPatternUChars(void)
1376 {
1377 return gPatternChars;
1378 }
1379
1380 UDateFormatField U_EXPORT2
getPatternCharIndex(UChar c)1381 DateFormatSymbols::getPatternCharIndex(UChar c) {
1382 const UChar *p = u_strchr(gPatternChars, c);
1383 if (p == NULL) {
1384 return UDAT_FIELD_COUNT;
1385 } else {
1386 return static_cast<UDateFormatField>(p - gPatternChars);
1387 }
1388 }
1389
1390 static const uint64_t kNumericFieldsAlways =
1391 ((uint64_t)1 << UDAT_YEAR_FIELD) | // y
1392 ((uint64_t)1 << UDAT_DATE_FIELD) | // d
1393 ((uint64_t)1 << UDAT_HOUR_OF_DAY1_FIELD) | // k
1394 ((uint64_t)1 << UDAT_HOUR_OF_DAY0_FIELD) | // H
1395 ((uint64_t)1 << UDAT_MINUTE_FIELD) | // m
1396 ((uint64_t)1 << UDAT_SECOND_FIELD) | // s
1397 ((uint64_t)1 << UDAT_FRACTIONAL_SECOND_FIELD) | // S
1398 ((uint64_t)1 << UDAT_DAY_OF_YEAR_FIELD) | // D
1399 ((uint64_t)1 << UDAT_DAY_OF_WEEK_IN_MONTH_FIELD) | // F
1400 ((uint64_t)1 << UDAT_WEEK_OF_YEAR_FIELD) | // w
1401 ((uint64_t)1 << UDAT_WEEK_OF_MONTH_FIELD) | // W
1402 ((uint64_t)1 << UDAT_HOUR1_FIELD) | // h
1403 ((uint64_t)1 << UDAT_HOUR0_FIELD) | // K
1404 ((uint64_t)1 << UDAT_YEAR_WOY_FIELD) | // Y
1405 ((uint64_t)1 << UDAT_EXTENDED_YEAR_FIELD) | // u
1406 ((uint64_t)1 << UDAT_JULIAN_DAY_FIELD) | // g
1407 ((uint64_t)1 << UDAT_MILLISECONDS_IN_DAY_FIELD) | // A
1408 ((uint64_t)1 << UDAT_RELATED_YEAR_FIELD); // r
1409
1410 static const uint64_t kNumericFieldsForCount12 =
1411 ((uint64_t)1 << UDAT_MONTH_FIELD) | // M or MM
1412 ((uint64_t)1 << UDAT_DOW_LOCAL_FIELD) | // e or ee
1413 ((uint64_t)1 << UDAT_STANDALONE_DAY_FIELD) | // c or cc
1414 ((uint64_t)1 << UDAT_STANDALONE_MONTH_FIELD) | // L or LL
1415 ((uint64_t)1 << UDAT_QUARTER_FIELD) | // Q or QQ
1416 ((uint64_t)1 << UDAT_STANDALONE_QUARTER_FIELD); // q or qq
1417
1418 UBool U_EXPORT2
isNumericField(UDateFormatField f,int32_t count)1419 DateFormatSymbols::isNumericField(UDateFormatField f, int32_t count) {
1420 if (f == UDAT_FIELD_COUNT) {
1421 return FALSE;
1422 }
1423 uint64_t flag = ((uint64_t)1 << f);
1424 return ((kNumericFieldsAlways & flag) != 0 || ((kNumericFieldsForCount12 & flag) != 0 && count < 3));
1425 }
1426
1427 UBool U_EXPORT2
isNumericPatternChar(UChar c,int32_t count)1428 DateFormatSymbols::isNumericPatternChar(UChar c, int32_t count) {
1429 return isNumericField(getPatternCharIndex(c), count);
1430 }
1431
1432 //------------------------------------------------------
1433
1434 UnicodeString&
getLocalPatternChars(UnicodeString & result) const1435 DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const
1436 {
1437 // fastCopyFrom() - see assignArray comments
1438 return result.fastCopyFrom(fLocalPatternChars);
1439 }
1440
1441 //------------------------------------------------------
1442
1443 void
setLocalPatternChars(const UnicodeString & newLocalPatternChars)1444 DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars)
1445 {
1446 fLocalPatternChars = newLocalPatternChars;
1447 }
1448
1449 //------------------------------------------------------
1450
1451 namespace {
1452
1453 // Constants declarations
1454 static const UChar kCalendarAliasPrefixUChar[] = {
1455 SOLIDUS, CAP_L, CAP_O, CAP_C, CAP_A, CAP_L, CAP_E, SOLIDUS,
1456 LOW_C, LOW_A, LOW_L, LOW_E, LOW_N, LOW_D, LOW_A, LOW_R, SOLIDUS
1457 };
1458 static const UChar kGregorianTagUChar[] = {
1459 LOW_G, LOW_R, LOW_E, LOW_G, LOW_O, LOW_R, LOW_I, LOW_A, LOW_N
1460 };
1461 static const UChar kVariantTagUChar[] = {
1462 PERCENT, LOW_V, LOW_A, LOW_R, LOW_I, LOW_A, LOW_N, LOW_T
1463 };
1464 static const UChar kLeapTagUChar[] = {
1465 LOW_L, LOW_E, LOW_A, LOW_P
1466 };
1467 static const UChar kCyclicNameSetsTagUChar[] = {
1468 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
1469 };
1470 static const UChar kYearsTagUChar[] = {
1471 SOLIDUS, LOW_Y, LOW_E, LOW_A, LOW_R, LOW_S
1472 };
1473 static const UChar kZodiacsUChar[] = {
1474 SOLIDUS, LOW_Z, LOW_O, LOW_D, LOW_I, LOW_A, LOW_C, LOW_S
1475 };
1476 static const UChar kDayPartsTagUChar[] = {
1477 SOLIDUS, LOW_D, LOW_A, LOW_Y, CAP_P, LOW_A, LOW_R, LOW_T, LOW_S
1478 };
1479 static const UChar kFormatTagUChar[] = {
1480 SOLIDUS, LOW_F, LOW_O, LOW_R, LOW_M, LOW_A, LOW_T
1481 };
1482 static const UChar kAbbrTagUChar[] = {
1483 SOLIDUS, LOW_A, LOW_B, LOW_B, LOW_R, LOW_E, LOW_V, LOW_I, LOW_A, LOW_T, LOW_E, LOW_D
1484 };
1485
1486 // ResourceSink to enumerate all calendar resources
1487 struct CalendarDataSink : public ResourceSink {
1488
1489 // Enum which specifies the type of alias received, or no alias
1490 enum AliasType {
1491 SAME_CALENDAR,
1492 DIFFERENT_CALENDAR,
1493 GREGORIAN,
1494 NONE
1495 };
1496
1497 // Data structures to store resources from the current resource bundle
1498 Hashtable arrays;
1499 Hashtable arraySizes;
1500 Hashtable maps;
1501 /**
1502 * Whenever there are aliases, the same object will be added twice to 'map'.
1503 * To avoid double deletion, 'maps' won't take ownership of the objects. Instead,
1504 * 'mapRefs' will own them and will delete them when CalendarDataSink is deleted.
1505 */
1506 MemoryPool<Hashtable> mapRefs;
1507
1508 // Paths and the aliases they point to
1509 UVector aliasPathPairs;
1510
1511 // Current and next calendar resource table which should be loaded
1512 UnicodeString currentCalendarType;
1513 UnicodeString nextCalendarType;
1514
1515 // Resources to visit when enumerating fallback calendars
1516 LocalPointer<UVector> resourcesToVisit;
1517
1518 // Alias' relative path populated whenever an alias is read
1519 UnicodeString aliasRelativePath;
1520
1521 // Initializes CalendarDataSink with default values
CalendarDataSink__anond3cb33c70111::CalendarDataSink1522 CalendarDataSink(UErrorCode& status)
1523 : arrays(FALSE, status), arraySizes(FALSE, status), maps(FALSE, status),
1524 mapRefs(),
1525 aliasPathPairs(uprv_deleteUObject, uhash_compareUnicodeString, status),
1526 currentCalendarType(), nextCalendarType(),
1527 resourcesToVisit(NULL), aliasRelativePath() {
1528 if (U_FAILURE(status)) { return; }
1529 }
1530 virtual ~CalendarDataSink();
1531
1532 // Configure the CalendarSink to visit all the resources
visitAllResources__anond3cb33c70111::CalendarDataSink1533 void visitAllResources() {
1534 resourcesToVisit.adoptInstead(NULL);
1535 }
1536
1537 // Actions to be done before enumerating
preEnumerate__anond3cb33c70111::CalendarDataSink1538 void preEnumerate(const UnicodeString &calendarType) {
1539 currentCalendarType = calendarType;
1540 nextCalendarType.setToBogus();
1541 aliasPathPairs.removeAllElements();
1542 }
1543
put__anond3cb33c70111::CalendarDataSink1544 virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) {
1545 if (U_FAILURE(errorCode)) { return; }
1546 U_ASSERT(!currentCalendarType.isEmpty());
1547
1548 // Stores the resources to visit on the next calendar.
1549 LocalPointer<UVector> resourcesToVisitNext(NULL);
1550 ResourceTable calendarData = value.getTable(errorCode);
1551 if (U_FAILURE(errorCode)) { return; }
1552
1553 // Enumerate all resources for this calendar
1554 for (int i = 0; calendarData.getKeyAndValue(i, key, value); i++) {
1555 UnicodeString keyUString(key, -1, US_INV);
1556
1557 // == Handle aliases ==
1558 AliasType aliasType = processAliasFromValue(keyUString, value, errorCode);
1559 if (U_FAILURE(errorCode)) { return; }
1560 if (aliasType == GREGORIAN) {
1561 // Ignore aliases to the gregorian calendar, all of its resources will be loaded anyway.
1562 continue;
1563
1564 } else if (aliasType == DIFFERENT_CALENDAR) {
1565 // Whenever an alias to the next calendar (except gregorian) is encountered, register the
1566 // calendar type it's pointing to
1567 if (resourcesToVisitNext.isNull()) {
1568 resourcesToVisitNext
1569 .adoptInsteadAndCheckErrorCode(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, errorCode),
1570 errorCode);
1571 if (U_FAILURE(errorCode)) { return; }
1572 }
1573 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1574 resourcesToVisitNext->addElement(aliasRelativePathCopy.getAlias(), errorCode);
1575 if (U_FAILURE(errorCode)) { return; }
1576 // Only release ownership after resourcesToVisitNext takes it (no error happened):
1577 aliasRelativePathCopy.orphan();
1578 continue;
1579
1580 } else if (aliasType == SAME_CALENDAR) {
1581 // Register same-calendar alias
1582 if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) {
1583 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1584 aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
1585 if (U_FAILURE(errorCode)) { return; }
1586 // Only release ownership after aliasPathPairs takes it (no error happened):
1587 aliasRelativePathCopy.orphan();
1588 LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode);
1589 aliasPathPairs.addElement(keyUStringCopy.getAlias(), errorCode);
1590 if (U_FAILURE(errorCode)) { return; }
1591 // Only release ownership after aliasPathPairs takes it (no error happened):
1592 keyUStringCopy.orphan();
1593 }
1594 continue;
1595 }
1596
1597 // Only visit the resources that were referenced by an alias on the previous calendar
1598 // (AmPmMarkersAbbr is an exception).
1599 if (!resourcesToVisit.isNull() && !resourcesToVisit->isEmpty() && !resourcesToVisit->contains(&keyUString)
1600 && uprv_strcmp(key, gAmPmMarkersAbbrTag) != 0) { continue; }
1601
1602 // == Handle data ==
1603 if (uprv_strcmp(key, gAmPmMarkersTag) == 0
1604 || uprv_strcmp(key, gAmPmMarkersAbbrTag) == 0
1605 || uprv_strcmp(key, gAmPmMarkersNarrowTag) == 0) {
1606 if (arrays.get(keyUString) == NULL) {
1607 ResourceArray resourceArray = value.getArray(errorCode);
1608 int32_t arraySize = resourceArray.getSize();
1609 LocalArray<UnicodeString> stringArray(new UnicodeString[arraySize], errorCode);
1610 value.getStringArray(stringArray.getAlias(), arraySize, errorCode);
1611 arrays.put(keyUString, stringArray.orphan(), errorCode);
1612 arraySizes.puti(keyUString, arraySize, errorCode);
1613 if (U_FAILURE(errorCode)) { return; }
1614 }
1615 } else if (uprv_strcmp(key, gErasTag) == 0
1616 || uprv_strcmp(key, gDayNamesTag) == 0
1617 || uprv_strcmp(key, gMonthNamesTag) == 0
1618 || uprv_strcmp(key, gQuartersTag) == 0
1619 || uprv_strcmp(key, gDayPeriodTag) == 0
1620 || uprv_strcmp(key, gMonthPatternsTag) == 0
1621 || uprv_strcmp(key, gCyclicNameSetsTag) == 0) {
1622 processResource(keyUString, key, value, errorCode);
1623 }
1624 }
1625
1626 // Apply same-calendar aliases
1627 UBool modified;
1628 do {
1629 modified = false;
1630 for (int32_t i = 0; i < aliasPathPairs.size();) {
1631 UBool mod = false;
1632 UnicodeString *alias = (UnicodeString*)aliasPathPairs[i];
1633 UnicodeString *aliasArray;
1634 Hashtable *aliasMap;
1635 if ((aliasArray = (UnicodeString*)arrays.get(*alias)) != NULL) {
1636 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1637 if (arrays.get(*path) == NULL) {
1638 // Clone the array
1639 int32_t aliasArraySize = arraySizes.geti(*alias);
1640 LocalArray<UnicodeString> aliasArrayCopy(new UnicodeString[aliasArraySize], errorCode);
1641 if (U_FAILURE(errorCode)) { return; }
1642 uprv_arrayCopy(aliasArray, aliasArrayCopy.getAlias(), aliasArraySize);
1643 // Put the array on the 'arrays' map
1644 arrays.put(*path, aliasArrayCopy.orphan(), errorCode);
1645 arraySizes.puti(*path, aliasArraySize, errorCode);
1646 }
1647 if (U_FAILURE(errorCode)) { return; }
1648 mod = true;
1649 } else if ((aliasMap = (Hashtable*)maps.get(*alias)) != NULL) {
1650 UnicodeString *path = (UnicodeString*)aliasPathPairs[i + 1];
1651 if (maps.get(*path) == NULL) {
1652 maps.put(*path, aliasMap, errorCode);
1653 }
1654 if (U_FAILURE(errorCode)) { return; }
1655 mod = true;
1656 }
1657 if (mod) {
1658 aliasPathPairs.removeElementAt(i + 1);
1659 aliasPathPairs.removeElementAt(i);
1660 modified = true;
1661 } else {
1662 i += 2;
1663 }
1664 }
1665 } while (modified && !aliasPathPairs.isEmpty());
1666
1667 // Set the resources to visit on the next calendar
1668 if (!resourcesToVisitNext.isNull()) {
1669 resourcesToVisit = std::move(resourcesToVisitNext);
1670 }
1671 }
1672
1673 // Process the nested resource bundle tables
processResource__anond3cb33c70111::CalendarDataSink1674 void processResource(UnicodeString &path, const char *key, ResourceValue &value, UErrorCode &errorCode) {
1675 if (U_FAILURE(errorCode)) return;
1676
1677 ResourceTable table = value.getTable(errorCode);
1678 if (U_FAILURE(errorCode)) return;
1679 Hashtable* stringMap = NULL;
1680
1681 // Iterate over all the elements of the table and add them to the map
1682 for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
1683 UnicodeString keyUString(key, -1, US_INV);
1684
1685 // Ignore '%variant' keys
1686 if (keyUString.endsWith(kVariantTagUChar, UPRV_LENGTHOF(kVariantTagUChar))) {
1687 continue;
1688 }
1689
1690 // == Handle String elements ==
1691 if (value.getType() == URES_STRING) {
1692 // We are on a leaf, store the map elements into the stringMap
1693 if (i == 0) {
1694 // mapRefs will keep ownership of 'stringMap':
1695 stringMap = mapRefs.create(FALSE, errorCode);
1696 if (stringMap == NULL) {
1697 errorCode = U_MEMORY_ALLOCATION_ERROR;
1698 return;
1699 }
1700 maps.put(path, stringMap, errorCode);
1701 if (U_FAILURE(errorCode)) { return; }
1702 stringMap->setValueDeleter(uprv_deleteUObject);
1703 }
1704 U_ASSERT(stringMap != NULL);
1705 int32_t valueStringSize;
1706 const UChar *valueString = value.getString(valueStringSize, errorCode);
1707 if (U_FAILURE(errorCode)) { return; }
1708 LocalPointer<UnicodeString> valueUString(new UnicodeString(TRUE, valueString, valueStringSize), errorCode);
1709 stringMap->put(keyUString, valueUString.orphan(), errorCode);
1710 if (U_FAILURE(errorCode)) { return; }
1711 continue;
1712 }
1713 U_ASSERT(stringMap == NULL);
1714
1715 // Store the current path's length and append the current key to the path.
1716 int32_t pathLength = path.length();
1717 path.append(SOLIDUS).append(keyUString);
1718
1719 // In cyclicNameSets ignore everything but years/format/abbreviated
1720 // and zodiacs/format/abbreviated
1721 if (path.startsWith(kCyclicNameSetsTagUChar, UPRV_LENGTHOF(kCyclicNameSetsTagUChar))) {
1722 UBool skip = TRUE;
1723 int32_t startIndex = UPRV_LENGTHOF(kCyclicNameSetsTagUChar);
1724 int32_t length = 0;
1725 if (startIndex == path.length()
1726 || path.compare(startIndex, (length = UPRV_LENGTHOF(kZodiacsUChar)), kZodiacsUChar, 0, UPRV_LENGTHOF(kZodiacsUChar)) == 0
1727 || path.compare(startIndex, (length = UPRV_LENGTHOF(kYearsTagUChar)), kYearsTagUChar, 0, UPRV_LENGTHOF(kYearsTagUChar)) == 0
1728 || path.compare(startIndex, (length = UPRV_LENGTHOF(kDayPartsTagUChar)), kDayPartsTagUChar, 0, UPRV_LENGTHOF(kDayPartsTagUChar)) == 0) {
1729 startIndex += length;
1730 length = 0;
1731 if (startIndex == path.length()
1732 || path.compare(startIndex, (length = UPRV_LENGTHOF(kFormatTagUChar)), kFormatTagUChar, 0, UPRV_LENGTHOF(kFormatTagUChar)) == 0) {
1733 startIndex += length;
1734 length = 0;
1735 if (startIndex == path.length()
1736 || path.compare(startIndex, (length = UPRV_LENGTHOF(kAbbrTagUChar)), kAbbrTagUChar, 0, UPRV_LENGTHOF(kAbbrTagUChar)) == 0) {
1737 skip = FALSE;
1738 }
1739 }
1740 }
1741 if (skip) {
1742 // Drop the latest key on the path and continue
1743 path.retainBetween(0, pathLength);
1744 continue;
1745 }
1746 }
1747
1748 // == Handle aliases ==
1749 if (arrays.get(path) != NULL || maps.get(path) != NULL) {
1750 // Drop the latest key on the path and continue
1751 path.retainBetween(0, pathLength);
1752 continue;
1753 }
1754
1755 AliasType aliasType = processAliasFromValue(path, value, errorCode);
1756 if (U_FAILURE(errorCode)) { return; }
1757 if (aliasType == SAME_CALENDAR) {
1758 // Store the alias path and the current path on aliasPathPairs
1759 LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode);
1760 aliasPathPairs.addElement(aliasRelativePathCopy.getAlias(), errorCode);
1761 if (U_FAILURE(errorCode)) { return; }
1762 // Only release ownership after aliasPathPairs takes it (no error happened):
1763 aliasRelativePathCopy.orphan();
1764 LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode);
1765 aliasPathPairs.addElement(pathCopy.getAlias(), errorCode);
1766 if (U_FAILURE(errorCode)) { return; }
1767 // Only release ownership after aliasPathPairs takes it (no error happened):
1768 pathCopy.orphan();
1769
1770 // Drop the latest key on the path and continue
1771 path.retainBetween(0, pathLength);
1772 continue;
1773 }
1774 U_ASSERT(aliasType == NONE);
1775
1776 // == Handle data ==
1777 if (value.getType() == URES_ARRAY) {
1778 // We are on a leaf, store the array
1779 ResourceArray rDataArray = value.getArray(errorCode);
1780 int32_t dataArraySize = rDataArray.getSize();
1781 LocalArray<UnicodeString> dataArray(new UnicodeString[dataArraySize], errorCode);
1782 value.getStringArray(dataArray.getAlias(), dataArraySize, errorCode);
1783 arrays.put(path, dataArray.orphan(), errorCode);
1784 arraySizes.puti(path, dataArraySize, errorCode);
1785 if (U_FAILURE(errorCode)) { return; }
1786 } else if (value.getType() == URES_TABLE) {
1787 // We are not on a leaf, recursively process the subtable.
1788 processResource(path, key, value, errorCode);
1789 if (U_FAILURE(errorCode)) { return; }
1790 }
1791
1792 // Drop the latest key on the path
1793 path.retainBetween(0, pathLength);
1794 }
1795 }
1796
1797 // Populates an AliasIdentifier with the alias information contained on the UResource.Value.
processAliasFromValue__anond3cb33c70111::CalendarDataSink1798 AliasType processAliasFromValue(UnicodeString ¤tRelativePath, ResourceValue &value,
1799 UErrorCode &errorCode) {
1800 if (U_FAILURE(errorCode)) { return NONE; }
1801
1802 if (value.getType() == URES_ALIAS) {
1803 int32_t aliasPathSize;
1804 const UChar* aliasPathUChar = value.getAliasString(aliasPathSize, errorCode);
1805 if (U_FAILURE(errorCode)) { return NONE; }
1806 UnicodeString aliasPath(aliasPathUChar, aliasPathSize);
1807 const int32_t aliasPrefixLength = UPRV_LENGTHOF(kCalendarAliasPrefixUChar);
1808 if (aliasPath.startsWith(kCalendarAliasPrefixUChar, aliasPrefixLength)
1809 && aliasPath.length() > aliasPrefixLength) {
1810 int32_t typeLimit = aliasPath.indexOf(SOLIDUS, aliasPrefixLength);
1811 if (typeLimit > aliasPrefixLength) {
1812 const UnicodeString aliasCalendarType =
1813 aliasPath.tempSubStringBetween(aliasPrefixLength, typeLimit);
1814 aliasRelativePath.setTo(aliasPath, typeLimit + 1, aliasPath.length());
1815
1816 if (currentCalendarType == aliasCalendarType
1817 && currentRelativePath != aliasRelativePath) {
1818 // If we have an alias to the same calendar, the path to the resource must be different
1819 return SAME_CALENDAR;
1820
1821 } else if (currentCalendarType != aliasCalendarType
1822 && currentRelativePath == aliasRelativePath) {
1823 // If we have an alias to a different calendar, the path to the resource must be the same
1824 if (aliasCalendarType.compare(kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar)) == 0) {
1825 return GREGORIAN;
1826 } else if (nextCalendarType.isBogus()) {
1827 nextCalendarType = aliasCalendarType;
1828 return DIFFERENT_CALENDAR;
1829 } else if (nextCalendarType == aliasCalendarType) {
1830 return DIFFERENT_CALENDAR;
1831 }
1832 }
1833 }
1834 }
1835 errorCode = U_INTERNAL_PROGRAM_ERROR;
1836 return NONE;
1837 }
1838 return NONE;
1839 }
1840
1841 // Deleter function to be used by 'arrays'
deleteUnicodeStringArray__anond3cb33c70111::CalendarDataSink1842 static void U_CALLCONV deleteUnicodeStringArray(void *uArray) {
1843 delete[] static_cast<UnicodeString *>(uArray);
1844 }
1845 };
1846 // Virtual destructors have to be defined out of line
~CalendarDataSink()1847 CalendarDataSink::~CalendarDataSink() {
1848 arrays.setValueDeleter(deleteUnicodeStringArray);
1849 }
1850 }
1851
1852 //------------------------------------------------------
1853
1854 static void
initField(UnicodeString ** field,int32_t & length,const UChar * data,LastResortSize numStr,LastResortSize strLen,UErrorCode & status)1855 initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) {
1856 if (U_SUCCESS(status)) {
1857 length = numStr;
1858 *field = newUnicodeStringArray((size_t)numStr);
1859 if (*field) {
1860 for(int32_t i = 0; i<length; i++) {
1861 // readonly aliases - all "data" strings are constant
1862 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty)
1863 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1);
1864 }
1865 }
1866 else {
1867 length = 0;
1868 status = U_MEMORY_ALLOCATION_ERROR;
1869 }
1870 }
1871 }
1872
1873 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,UErrorCode & status)1874 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, UErrorCode &status) {
1875 if (U_SUCCESS(status)) {
1876 UnicodeString keyUString(key.data(), -1, US_INV);
1877 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1878
1879 if (array != NULL) {
1880 length = sink.arraySizes.geti(keyUString);
1881 *field = array;
1882 // DateFormatSymbols takes ownership of the array:
1883 sink.arrays.remove(keyUString);
1884 } else {
1885 length = 0;
1886 status = U_MISSING_RESOURCE_ERROR;
1887 }
1888 }
1889 }
1890
1891 static void
initField(UnicodeString ** field,int32_t & length,CalendarDataSink & sink,CharString & key,int32_t arrayOffset,UErrorCode & status)1892 initField(UnicodeString **field, int32_t& length, CalendarDataSink &sink, CharString &key, int32_t arrayOffset, UErrorCode &status) {
1893 if (U_SUCCESS(status)) {
1894 UnicodeString keyUString(key.data(), -1, US_INV);
1895 UnicodeString* array = static_cast<UnicodeString*>(sink.arrays.get(keyUString));
1896
1897 if (array != NULL) {
1898 int32_t arrayLength = sink.arraySizes.geti(keyUString);
1899 length = arrayLength + arrayOffset;
1900 *field = new UnicodeString[length];
1901 if (*field == NULL) {
1902 status = U_MEMORY_ALLOCATION_ERROR;
1903 return;
1904 }
1905 uprv_arrayCopy(array, 0, *field, arrayOffset, arrayLength);
1906 } else {
1907 length = 0;
1908 status = U_MISSING_RESOURCE_ERROR;
1909 }
1910 }
1911 }
1912
1913 static void
initLeapMonthPattern(UnicodeString * field,int32_t index,CalendarDataSink & sink,CharString & path,UErrorCode & status)1914 initLeapMonthPattern(UnicodeString *field, int32_t index, CalendarDataSink &sink, CharString &path, UErrorCode &status) {
1915 field[index].remove();
1916 if (U_SUCCESS(status)) {
1917 UnicodeString pathUString(path.data(), -1, US_INV);
1918 Hashtable *leapMonthTable = static_cast<Hashtable*>(sink.maps.get(pathUString));
1919 if (leapMonthTable != NULL) {
1920 UnicodeString leapLabel(FALSE, kLeapTagUChar, UPRV_LENGTHOF(kLeapTagUChar));
1921 UnicodeString *leapMonthPattern = static_cast<UnicodeString*>(leapMonthTable->get(leapLabel));
1922 if (leapMonthPattern != NULL) {
1923 field[index].fastCopyFrom(*leapMonthPattern);
1924 } else {
1925 field[index].setToBogus();
1926 }
1927 return;
1928 }
1929 status = U_MISSING_RESOURCE_ERROR;
1930 }
1931 }
1932
1933 static CharString
buildResourcePath(CharString & path,const char * segment1,UErrorCode & errorCode)1934 &buildResourcePath(CharString &path, const char* segment1, UErrorCode &errorCode) {
1935 return path.clear().append(segment1, -1, errorCode);
1936 }
1937
1938 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,UErrorCode & errorCode)1939 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1940 UErrorCode &errorCode) {
1941 return buildResourcePath(path, segment1, errorCode).append('/', errorCode)
1942 .append(segment2, -1, errorCode);
1943 }
1944
1945 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,UErrorCode & errorCode)1946 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1947 const char* segment3, UErrorCode &errorCode) {
1948 return buildResourcePath(path, segment1, segment2, errorCode).append('/', errorCode)
1949 .append(segment3, -1, errorCode);
1950 }
1951
1952 static CharString
buildResourcePath(CharString & path,const char * segment1,const char * segment2,const char * segment3,const char * segment4,UErrorCode & errorCode)1953 &buildResourcePath(CharString &path, const char* segment1, const char* segment2,
1954 const char* segment3, const char* segment4, UErrorCode &errorCode) {
1955 return buildResourcePath(path, segment1, segment2, segment3, errorCode).append('/', errorCode)
1956 .append(segment4, -1, errorCode);
1957 }
1958
1959 typedef struct {
1960 const char * usageTypeName;
1961 DateFormatSymbols::ECapitalizationContextUsageType usageTypeEnumValue;
1962 } ContextUsageTypeNameToEnumValue;
1963
1964 static const ContextUsageTypeNameToEnumValue contextUsageTypeMap[] = {
1965 // Entries must be sorted by usageTypeName; entry with NULL name terminates list.
1966 { "day-format-except-narrow", DateFormatSymbols::kCapContextUsageDayFormat },
1967 { "day-narrow", DateFormatSymbols::kCapContextUsageDayNarrow },
1968 { "day-standalone-except-narrow", DateFormatSymbols::kCapContextUsageDayStandalone },
1969 { "era-abbr", DateFormatSymbols::kCapContextUsageEraAbbrev },
1970 { "era-name", DateFormatSymbols::kCapContextUsageEraWide },
1971 { "era-narrow", DateFormatSymbols::kCapContextUsageEraNarrow },
1972 { "metazone-long", DateFormatSymbols::kCapContextUsageMetazoneLong },
1973 { "metazone-short", DateFormatSymbols::kCapContextUsageMetazoneShort },
1974 { "month-format-except-narrow", DateFormatSymbols::kCapContextUsageMonthFormat },
1975 { "month-narrow", DateFormatSymbols::kCapContextUsageMonthNarrow },
1976 { "month-standalone-except-narrow", DateFormatSymbols::kCapContextUsageMonthStandalone },
1977 { "zone-long", DateFormatSymbols::kCapContextUsageZoneLong },
1978 { "zone-short", DateFormatSymbols::kCapContextUsageZoneShort },
1979 { NULL, (DateFormatSymbols::ECapitalizationContextUsageType)0 },
1980 };
1981
1982 // Resource keys to look up localized strings for day periods.
1983 // The first one must be midnight and the second must be noon, so that their indices coincide
1984 // with the am/pm field. Formatting and parsing code for day periods relies on this coincidence.
1985 static const char *dayPeriodKeys[] = {"midnight", "noon",
1986 "morning1", "afternoon1", "evening1", "night1",
1987 "morning2", "afternoon2", "evening2", "night2"};
1988
loadDayPeriodStrings(CalendarDataSink & sink,CharString & path,int32_t & stringCount,UErrorCode & status)1989 UnicodeString* loadDayPeriodStrings(CalendarDataSink &sink, CharString &path,
1990 int32_t &stringCount, UErrorCode &status) {
1991 if (U_FAILURE(status)) { return NULL; }
1992
1993 UnicodeString pathUString(path.data(), -1, US_INV);
1994 Hashtable* map = static_cast<Hashtable*>(sink.maps.get(pathUString));
1995
1996 stringCount = UPRV_LENGTHOF(dayPeriodKeys);
1997 UnicodeString *strings = new UnicodeString[stringCount];
1998 if (strings == NULL) {
1999 status = U_MEMORY_ALLOCATION_ERROR;
2000 return NULL;
2001 }
2002
2003 if (map != NULL) {
2004 for (int32_t i = 0; i < stringCount; ++i) {
2005 UnicodeString dayPeriodKey(dayPeriodKeys[i], -1, US_INV);
2006 UnicodeString *dayPeriod = static_cast<UnicodeString*>(map->get(dayPeriodKey));
2007 if (dayPeriod != NULL) {
2008 strings[i].fastCopyFrom(*dayPeriod);
2009 } else {
2010 strings[i].setToBogus();
2011 }
2012 }
2013 } else {
2014 for (int32_t i = 0; i < stringCount; i++) {
2015 strings[i].setToBogus();
2016 }
2017 }
2018 return strings;
2019 }
2020
2021
2022 void
initializeData(const Locale & locale,const char * type,UErrorCode & status,UBool useLastResortData)2023 DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData)
2024 {
2025 int32_t len = 0;
2026 /* In case something goes wrong, initialize all of the data to NULL. */
2027 fEras = NULL;
2028 fErasCount = 0;
2029 fEraNames = NULL;
2030 fEraNamesCount = 0;
2031 fNarrowEras = NULL;
2032 fNarrowErasCount = 0;
2033 fMonths = NULL;
2034 fMonthsCount=0;
2035 fShortMonths = NULL;
2036 fShortMonthsCount=0;
2037 fNarrowMonths = NULL;
2038 fNarrowMonthsCount=0;
2039 fStandaloneMonths = NULL;
2040 fStandaloneMonthsCount=0;
2041 fStandaloneShortMonths = NULL;
2042 fStandaloneShortMonthsCount=0;
2043 fStandaloneNarrowMonths = NULL;
2044 fStandaloneNarrowMonthsCount=0;
2045 fWeekdays = NULL;
2046 fWeekdaysCount=0;
2047 fShortWeekdays = NULL;
2048 fShortWeekdaysCount=0;
2049 fShorterWeekdays = NULL;
2050 fShorterWeekdaysCount=0;
2051 fNarrowWeekdays = NULL;
2052 fNarrowWeekdaysCount=0;
2053 fStandaloneWeekdays = NULL;
2054 fStandaloneWeekdaysCount=0;
2055 fStandaloneShortWeekdays = NULL;
2056 fStandaloneShortWeekdaysCount=0;
2057 fStandaloneShorterWeekdays = NULL;
2058 fStandaloneShorterWeekdaysCount=0;
2059 fStandaloneNarrowWeekdays = NULL;
2060 fStandaloneNarrowWeekdaysCount=0;
2061 fAmPms = NULL;
2062 fAmPmsCount=0;
2063 fNarrowAmPms = NULL;
2064 fNarrowAmPmsCount=0;
2065 fTimeSeparator.setToBogus();
2066 fQuarters = NULL;
2067 fQuartersCount = 0;
2068 fShortQuarters = NULL;
2069 fShortQuartersCount = 0;
2070 fStandaloneQuarters = NULL;
2071 fStandaloneQuartersCount = 0;
2072 fStandaloneShortQuarters = NULL;
2073 fStandaloneShortQuartersCount = 0;
2074 fLeapMonthPatterns = NULL;
2075 fLeapMonthPatternsCount = 0;
2076 fShortYearNames = NULL;
2077 fShortYearNamesCount = 0;
2078 fShortZodiacNames = NULL;
2079 fShortZodiacNamesCount = 0;
2080 fZoneStringsRowCount = 0;
2081 fZoneStringsColCount = 0;
2082 fZoneStrings = NULL;
2083 fLocaleZoneStrings = NULL;
2084 fAbbreviatedDayPeriods = NULL;
2085 fAbbreviatedDayPeriodsCount = 0;
2086 fWideDayPeriods = NULL;
2087 fWideDayPeriodsCount = 0;
2088 fNarrowDayPeriods = NULL;
2089 fNarrowDayPeriodsCount = 0;
2090 fStandaloneAbbreviatedDayPeriods = NULL;
2091 fStandaloneAbbreviatedDayPeriodsCount = 0;
2092 fStandaloneWideDayPeriods = NULL;
2093 fStandaloneWideDayPeriodsCount = 0;
2094 fStandaloneNarrowDayPeriods = NULL;
2095 fStandaloneNarrowDayPeriodsCount = 0;
2096 uprv_memset(fCapitalization, 0, sizeof(fCapitalization));
2097
2098 // We need to preserve the requested locale for
2099 // lazy ZoneStringFormat instantiation. ZoneStringFormat
2100 // is region sensitive, thus, bundle locale bundle's locale
2101 // is not sufficient.
2102 fZSFLocale = locale;
2103
2104 if (U_FAILURE(status)) return;
2105
2106 // Create a CalendarDataSink to process this data and the resouce bundles
2107 CalendarDataSink calendarSink(status);
2108 UResourceBundle *rb = ures_open(NULL, locale.getBaseName(), &status);
2109 UResourceBundle *cb = ures_getByKey(rb, gCalendarTag, NULL, &status);
2110
2111 if (U_FAILURE(status)) return;
2112
2113 // Iterate over the resource bundle data following the fallbacks through different calendar types
2114 UnicodeString calendarType((type != NULL && *type != '\0')? type : gGregorianTag, -1, US_INV);
2115 while (!calendarType.isBogus()) {
2116 CharString calendarTypeBuffer;
2117 calendarTypeBuffer.appendInvariantChars(calendarType, status);
2118 if (U_FAILURE(status)) { return; }
2119 const char *calendarTypeCArray = calendarTypeBuffer.data();
2120
2121 // Enumerate this calendar type. If the calendar is not found fallback to gregorian
2122 UErrorCode oldStatus = status;
2123 UResourceBundle *ctb = ures_getByKeyWithFallback(cb, calendarTypeCArray, NULL, &status);
2124 if (status == U_MISSING_RESOURCE_ERROR) {
2125 ures_close(ctb);
2126 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) != 0) {
2127 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2128 calendarSink.visitAllResources();
2129 status = oldStatus;
2130 continue;
2131 }
2132 return;
2133 }
2134
2135 calendarSink.preEnumerate(calendarType);
2136 ures_getAllItemsWithFallback(ctb, "", calendarSink, status);
2137 ures_close(ctb);
2138 if (U_FAILURE(status)) break;
2139
2140 // Stop loading when gregorian was loaded
2141 if (uprv_strcmp(calendarTypeCArray, gGregorianTag) == 0) {
2142 break;
2143 }
2144
2145 // Get the next calendar type to process from the sink
2146 calendarType = calendarSink.nextCalendarType;
2147
2148 // Gregorian is always the last fallback
2149 if (calendarType.isBogus()) {
2150 calendarType.setTo(FALSE, kGregorianTagUChar, UPRV_LENGTHOF(kGregorianTagUChar));
2151 calendarSink.visitAllResources();
2152 }
2153 }
2154
2155 // CharString object to build paths
2156 CharString path;
2157
2158 // Load Leap Month Patterns
2159 UErrorCode tempStatus = status;
2160 fLeapMonthPatterns = newUnicodeStringArray(kMonthPatternsCount);
2161 if (fLeapMonthPatterns) {
2162 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatWide, calendarSink,
2163 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesWideTag, tempStatus), tempStatus);
2164 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatAbbrev, calendarSink,
2165 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2166 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternFormatNarrow, calendarSink,
2167 buildResourcePath(path, gMonthPatternsTag, gNamesFormatTag, gNamesNarrowTag, tempStatus), tempStatus);
2168 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneWide, calendarSink,
2169 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesWideTag, tempStatus), tempStatus);
2170 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneAbbrev, calendarSink,
2171 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesAbbrTag, tempStatus), tempStatus);
2172 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternStandaloneNarrow, calendarSink,
2173 buildResourcePath(path, gMonthPatternsTag, gNamesStandaloneTag, gNamesNarrowTag, tempStatus), tempStatus);
2174 initLeapMonthPattern(fLeapMonthPatterns, kLeapMonthPatternNumeric, calendarSink,
2175 buildResourcePath(path, gMonthPatternsTag, gNamesNumericTag, gNamesAllTag, tempStatus), tempStatus);
2176 if (U_SUCCESS(tempStatus)) {
2177 // Hack to fix bad C inheritance for dangi monthPatterns (OK in J); this should be handled by aliases in root, but isn't.
2178 // The ordering of the following statements is important.
2179 if (fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].isEmpty()) {
2180 fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2181 }
2182 if (fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].isEmpty()) {
2183 fLeapMonthPatterns[kLeapMonthPatternFormatNarrow].setTo(fLeapMonthPatterns[kLeapMonthPatternStandaloneNarrow]);
2184 }
2185 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].isEmpty()) {
2186 fLeapMonthPatterns[kLeapMonthPatternStandaloneWide].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatWide]);
2187 }
2188 if (fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].isEmpty()) {
2189 fLeapMonthPatterns[kLeapMonthPatternStandaloneAbbrev].setTo(fLeapMonthPatterns[kLeapMonthPatternFormatAbbrev]);
2190 }
2191 // end of hack
2192 fLeapMonthPatternsCount = kMonthPatternsCount;
2193 } else {
2194 delete[] fLeapMonthPatterns;
2195 fLeapMonthPatterns = NULL;
2196 }
2197 }
2198
2199 // Load cyclic names sets
2200 tempStatus = status;
2201 initField(&fShortYearNames, fShortYearNamesCount, calendarSink,
2202 buildResourcePath(path, gCyclicNameSetsTag, gNameSetYearsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2203 initField(&fShortZodiacNames, fShortZodiacNamesCount, calendarSink,
2204 buildResourcePath(path, gCyclicNameSetsTag, gNameSetZodiacsTag, gNamesFormatTag, gNamesAbbrTag, tempStatus), tempStatus);
2205
2206 // Load context transforms and capitalization
2207 tempStatus = U_ZERO_ERROR;
2208 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &tempStatus);
2209 if (U_SUCCESS(tempStatus)) {
2210 UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, gContextTransformsTag, NULL, &tempStatus);
2211 if (U_SUCCESS(tempStatus)) {
2212 UResourceBundle *contextTransformUsage;
2213 while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &tempStatus)) != NULL ) {
2214 const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status);
2215 if (U_SUCCESS(tempStatus) && intVector != NULL && len >= 2) {
2216 const char* usageType = ures_getKey(contextTransformUsage);
2217 if (usageType != NULL) {
2218 const ContextUsageTypeNameToEnumValue * typeMapPtr = contextUsageTypeMap;
2219 int32_t compResult = 0;
2220 // linear search; list is short and we cannot be sure that bsearch is available
2221 while ( typeMapPtr->usageTypeName != NULL && (compResult = uprv_strcmp(usageType, typeMapPtr->usageTypeName)) > 0 ) {
2222 ++typeMapPtr;
2223 }
2224 if (typeMapPtr->usageTypeName != NULL && compResult == 0) {
2225 fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast<UBool>(intVector[0]);
2226 fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast<UBool>(intVector[1]);
2227 }
2228 }
2229 }
2230 tempStatus = U_ZERO_ERROR;
2231 ures_close(contextTransformUsage);
2232 }
2233 ures_close(contextTransforms);
2234 }
2235
2236 tempStatus = U_ZERO_ERROR;
2237 const LocalPointer<NumberingSystem> numberingSystem(
2238 NumberingSystem::createInstance(locale, tempStatus), tempStatus);
2239 if (U_SUCCESS(tempStatus)) {
2240 // These functions all fail gracefully if passed NULL pointers and
2241 // do nothing unless U_SUCCESS(tempStatus), so it's only necessary
2242 // to check for errors once after all calls are made.
2243 const LocalUResourceBundlePointer numberElementsData(ures_getByKeyWithFallback(
2244 localeBundle, gNumberElementsTag, NULL, &tempStatus));
2245 const LocalUResourceBundlePointer nsNameData(ures_getByKeyWithFallback(
2246 numberElementsData.getAlias(), numberingSystem->getName(), NULL, &tempStatus));
2247 const LocalUResourceBundlePointer symbolsData(ures_getByKeyWithFallback(
2248 nsNameData.getAlias(), gSymbolsTag, NULL, &tempStatus));
2249 fTimeSeparator = ures_getUnicodeStringByKey(
2250 symbolsData.getAlias(), gTimeSeparatorTag, &tempStatus);
2251 if (U_FAILURE(tempStatus)) {
2252 fTimeSeparator.setToBogus();
2253 }
2254 }
2255
2256 ures_close(localeBundle);
2257 }
2258
2259 if (fTimeSeparator.isBogus()) {
2260 fTimeSeparator.setTo(DateFormatSymbols::DEFAULT_TIME_SEPARATOR);
2261 }
2262
2263 // Load day periods
2264 fWideDayPeriods = loadDayPeriodStrings(calendarSink,
2265 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesWideTag, status),
2266 fWideDayPeriodsCount, status);
2267 fNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2268 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesNarrowTag, status),
2269 fNarrowDayPeriodsCount, status);
2270 fAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2271 buildResourcePath(path, gDayPeriodTag, gNamesFormatTag, gNamesAbbrTag, status),
2272 fAbbreviatedDayPeriodsCount, status);
2273 fStandaloneWideDayPeriods = loadDayPeriodStrings(calendarSink,
2274 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesWideTag, status),
2275 fStandaloneWideDayPeriodsCount, status);
2276 fStandaloneNarrowDayPeriods = loadDayPeriodStrings(calendarSink,
2277 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesNarrowTag, status),
2278 fStandaloneNarrowDayPeriodsCount, status);
2279 fStandaloneAbbreviatedDayPeriods = loadDayPeriodStrings(calendarSink,
2280 buildResourcePath(path, gDayPeriodTag, gNamesStandaloneTag, gNamesAbbrTag, status),
2281 fStandaloneAbbreviatedDayPeriodsCount, status);
2282
2283 U_LOCALE_BASED(locBased, *this);
2284 // if we make it to here, the resource data is cool, and we can get everything out
2285 // of it that we need except for the time-zone and localized-pattern data, which
2286 // are stored in a separate file
2287 locBased.setLocaleIDs(ures_getLocaleByType(cb, ULOC_VALID_LOCALE, &status),
2288 ures_getLocaleByType(cb, ULOC_ACTUAL_LOCALE, &status));
2289
2290 // Load eras
2291 initField(&fEras, fErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesAbbrTag, status), status);
2292 UErrorCode oldStatus = status;
2293 initField(&fEraNames, fEraNamesCount, calendarSink, buildResourcePath(path, gErasTag, gNamesWideTag, status), status);
2294 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2295 status = oldStatus;
2296 assignArray(fEraNames, fEraNamesCount, fEras, fErasCount);
2297 }
2298 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too
2299 oldStatus = status;
2300 initField(&fNarrowEras, fNarrowErasCount, calendarSink, buildResourcePath(path, gErasTag, gNamesNarrowTag, status), status);
2301 if (status == U_MISSING_RESOURCE_ERROR) { // Workaround because eras/wide was omitted from CLDR 1.3
2302 status = oldStatus;
2303 assignArray(fNarrowEras, fNarrowErasCount, fEras, fErasCount);
2304 }
2305
2306 // Load month names
2307 initField(&fMonths, fMonthsCount, calendarSink,
2308 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesWideTag, status), status);
2309 initField(&fShortMonths, fShortMonthsCount, calendarSink,
2310 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2311 initField(&fStandaloneMonths, fStandaloneMonthsCount, calendarSink,
2312 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2313 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide not available, use format/wide */
2314 status = U_ZERO_ERROR;
2315 assignArray(fStandaloneMonths, fStandaloneMonthsCount, fMonths, fMonthsCount);
2316 }
2317 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calendarSink,
2318 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2319 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated not available, use format/abbreviated */
2320 status = U_ZERO_ERROR;
2321 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, fShortMonths, fShortMonthsCount);
2322 }
2323
2324 UErrorCode narrowMonthsEC = status;
2325 UErrorCode standaloneNarrowMonthsEC = status;
2326 initField(&fNarrowMonths, fNarrowMonthsCount, calendarSink,
2327 buildResourcePath(path, gMonthNamesTag, gNamesFormatTag, gNamesNarrowTag, narrowMonthsEC), narrowMonthsEC);
2328 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calendarSink,
2329 buildResourcePath(path, gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, narrowMonthsEC), standaloneNarrowMonthsEC);
2330 if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC != U_MISSING_RESOURCE_ERROR) {
2331 // If format/narrow not available, use standalone/narrow
2332 assignArray(fNarrowMonths, fNarrowMonthsCount, fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount);
2333 } else if (narrowMonthsEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2334 // If standalone/narrow not availabe, use format/narrow
2335 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fNarrowMonths, fNarrowMonthsCount);
2336 } else if (narrowMonthsEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowMonthsEC == U_MISSING_RESOURCE_ERROR) {
2337 // If neither is available, use format/abbreviated
2338 assignArray(fNarrowMonths, fNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2339 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, fShortMonths, fShortMonthsCount);
2340 }
2341
2342 // Load AM/PM markers; if wide or narrow not available, use short
2343 UErrorCode ampmStatus = U_ZERO_ERROR;
2344 initField(&fAmPms, fAmPmsCount, calendarSink,
2345 buildResourcePath(path, gAmPmMarkersTag, ampmStatus), ampmStatus);
2346 if (U_FAILURE(ampmStatus)) {
2347 initField(&fAmPms, fAmPmsCount, calendarSink,
2348 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2349 }
2350 ampmStatus = U_ZERO_ERROR;
2351 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2352 buildResourcePath(path, gAmPmMarkersNarrowTag, ampmStatus), ampmStatus);
2353 if (U_FAILURE(ampmStatus)) {
2354 initField(&fNarrowAmPms, fNarrowAmPmsCount, calendarSink,
2355 buildResourcePath(path, gAmPmMarkersAbbrTag, status), status);
2356 }
2357
2358 // Load quarters
2359 initField(&fQuarters, fQuartersCount, calendarSink,
2360 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesWideTag, status), status);
2361 initField(&fShortQuarters, fShortQuartersCount, calendarSink,
2362 buildResourcePath(path, gQuartersTag, gNamesFormatTag, gNamesAbbrTag, status), status);
2363
2364 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calendarSink,
2365 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status);
2366 if(status == U_MISSING_RESOURCE_ERROR) {
2367 status = U_ZERO_ERROR;
2368 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, fQuarters, fQuartersCount);
2369 }
2370 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calendarSink,
2371 buildResourcePath(path, gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status);
2372 if(status == U_MISSING_RESOURCE_ERROR) {
2373 status = U_ZERO_ERROR;
2374 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, fShortQuarters, fShortQuartersCount);
2375 }
2376
2377 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597)
2378 /*
2379 // fastCopyFrom()/setTo() - see assignArray comments
2380 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status);
2381 fLocalPatternChars.setTo(TRUE, resStr, len);
2382 // If the locale data does not include new pattern chars, use the defaults
2383 // TODO: Consider making this an error, since this may add conflicting characters.
2384 if (len < PATTERN_CHARS_LEN) {
2385 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len));
2386 }
2387 */
2388 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2389
2390 // Format wide weekdays -> fWeekdays
2391 // {sfb} fixed to handle 1-based weekdays
2392 initField(&fWeekdays, fWeekdaysCount, calendarSink,
2393 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesWideTag, status), 1, status);
2394
2395 // Format abbreviated weekdays -> fShortWeekdays
2396 initField(&fShortWeekdays, fShortWeekdaysCount, calendarSink,
2397 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesAbbrTag, status), 1, status);
2398
2399 // Format short weekdays -> fShorterWeekdays (fall back to abbreviated)
2400 initField(&fShorterWeekdays, fShorterWeekdaysCount, calendarSink,
2401 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesShortTag, status), 1, status);
2402 if (status == U_MISSING_RESOURCE_ERROR) {
2403 status = U_ZERO_ERROR;
2404 assignArray(fShorterWeekdays, fShorterWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2405 }
2406
2407 // Stand-alone wide weekdays -> fStandaloneWeekdays
2408 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, calendarSink,
2409 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status), 1, status);
2410 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/wide is not available, use format/wide */
2411 status = U_ZERO_ERROR;
2412 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, fWeekdays, fWeekdaysCount);
2413 }
2414
2415 // Stand-alone abbreviated weekdays -> fStandaloneShortWeekdays
2416 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, calendarSink,
2417 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), 1, status);
2418 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/abbreviated is not available, use format/abbreviated */
2419 status = U_ZERO_ERROR;
2420 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2421 }
2422
2423 // Stand-alone short weekdays -> fStandaloneShorterWeekdays (fall back to format abbreviated)
2424 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, calendarSink,
2425 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesShortTag, status), 1, status);
2426 if (status == U_MISSING_RESOURCE_ERROR) { /* If standalone/short is not available, use format/short */
2427 status = U_ZERO_ERROR;
2428 assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, fShorterWeekdays, fShorterWeekdaysCount);
2429 }
2430
2431 // Format narrow weekdays -> fNarrowWeekdays
2432 UErrorCode narrowWeeksEC = status;
2433 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, calendarSink,
2434 buildResourcePath(path, gDayNamesTag, gNamesFormatTag, gNamesNarrowTag, status), 1, narrowWeeksEC);
2435 // Stand-alone narrow weekdays -> fStandaloneNarrowWeekdays
2436 UErrorCode standaloneNarrowWeeksEC = status;
2437 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, calendarSink,
2438 buildResourcePath(path, gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), 1, standaloneNarrowWeeksEC);
2439
2440 if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC != U_MISSING_RESOURCE_ERROR) {
2441 // If format/narrow not available, use standalone/narrow
2442 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount);
2443 } else if (narrowWeeksEC != U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR) {
2444 // If standalone/narrow not available, use format/narrow
2445 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fNarrowWeekdays, fNarrowWeekdaysCount);
2446 } else if (narrowWeeksEC == U_MISSING_RESOURCE_ERROR && standaloneNarrowWeeksEC == U_MISSING_RESOURCE_ERROR ) {
2447 // If neither is available, use format/abbreviated
2448 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2449 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, fShortWeekdays, fShortWeekdaysCount);
2450 }
2451
2452 // Last resort fallback in case previous data wasn't loaded
2453 if (U_FAILURE(status))
2454 {
2455 if (useLastResortData)
2456 {
2457 // Handle the case in which there is no resource data present.
2458 // We don't have to generate usable patterns in this situation;
2459 // we just need to produce something that will be semi-intelligible
2460 // in most locales.
2461
2462 status = U_USING_FALLBACK_WARNING;
2463 //TODO(fabalbon): make sure we are storing las resort data for all fields in here.
2464 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2465 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2466 initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status);
2467 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2468 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2469 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2470 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2471 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2472 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status);
2473 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2474 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2475 initField(&fShorterWeekdays, fShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2476 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2477 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2478 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2479 initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2480 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status);
2481 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2482 initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status);
2483 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2484 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2485 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2486 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status);
2487 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN);
2488 }
2489 }
2490
2491 // Close resources
2492 ures_close(cb);
2493 ures_close(rb);
2494 }
2495
2496 Locale
getLocale(ULocDataLocaleType type,UErrorCode & status) const2497 DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
2498 U_LOCALE_BASED(locBased, *this);
2499 return locBased.getLocale(type, status);
2500 }
2501
2502 U_NAMESPACE_END
2503
2504 #endif /* #if !UCONFIG_NO_FORMATTING */
2505
2506 //eof
2507