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