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