1/* 2******************************************************************************* 3* Copyright (C) 1997-2008, International Business Machines Corporation and * 4* others. All Rights Reserved. * 5******************************************************************************* 6* 7* File DTFMTSYM.CPP 8* 9* Modification History: 10* 11* Date Name Description 12* 02/19/97 aliu Converted from java. 13* 07/21/98 stephen Added getZoneIndex 14* Changed weekdays/short weekdays to be one-based 15* 06/14/99 stephen Removed SimpleDateFormat::fgTimeZoneDataSuffix 16* 11/16/99 weiv Added 'Y' and 'e' to fgPatternChars 17* 03/27/00 weiv Keeping resource bundle around! 18* 06/30/05 emmons Added eraNames, narrow month/day, standalone context 19* 10/12/05 emmons Added setters for eraNames, month/day by width/context 20******************************************************************************* 21*/ 22#include "unicode/utypes.h" 23 24#if !UCONFIG_NO_FORMATTING 25#include "unicode/ustring.h" 26#include "unicode/dtfmtsym.h" 27#include "unicode/smpdtfmt.h" 28#include "unicode/msgfmt.h" 29#include "cpputils.h" 30#include "ucln_in.h" 31#include "umutex.h" 32#include "cmemory.h" 33#include "cstring.h" 34#include "locbased.h" 35#include "gregoimp.h" 36#include "hash.h" 37#include "uresimp.h" 38#include "zstrfmt.h" 39 40// ***************************************************************************** 41// class DateFormatSymbols 42// ***************************************************************************** 43/** 44 * These are static arrays we use only in the case where we have no 45 * resource data. 46 */ 47 48#define PATTERN_CHARS_LEN 30 49 50/** 51 * Unlocalized date-time pattern characters. For example: 'y', 'd', etc. All 52 * locales use the same these unlocalized pattern characters. 53 */ 54static const UChar gPatternChars[] = { 55 // GyMdkHmsSEDFwWahKzYeugAZvcLQqV 56 0x47, 0x79, 0x4D, 0x64, 0x6B, 0x48, 0x6D, 0x73, 0x53, 0x45, 57 0x44, 0x46, 0x77, 0x57, 0x61, 0x68, 0x4B, 0x7A, 0x59, 0x65, 58 0x75, 0x67, 0x41, 0x5A, 0x76, 0x63, 0x4c, 0x51, 0x71, 0x56, 0 59}; 60 61/* length of an array */ 62#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) 63 64//------------------------------------------------------ 65// Strings of last resort. These are only used if we have no resource 66// files. They aren't designed for actual use, just for backup. 67 68// These are the month names and abbreviations of last resort. 69static const UChar gLastResortMonthNames[13][3] = 70{ 71 {0x0030, 0x0031, 0x0000}, /* "01" */ 72 {0x0030, 0x0032, 0x0000}, /* "02" */ 73 {0x0030, 0x0033, 0x0000}, /* "03" */ 74 {0x0030, 0x0034, 0x0000}, /* "04" */ 75 {0x0030, 0x0035, 0x0000}, /* "05" */ 76 {0x0030, 0x0036, 0x0000}, /* "06" */ 77 {0x0030, 0x0037, 0x0000}, /* "07" */ 78 {0x0030, 0x0038, 0x0000}, /* "08" */ 79 {0x0030, 0x0039, 0x0000}, /* "09" */ 80 {0x0031, 0x0030, 0x0000}, /* "10" */ 81 {0x0031, 0x0031, 0x0000}, /* "11" */ 82 {0x0031, 0x0032, 0x0000}, /* "12" */ 83 {0x0031, 0x0033, 0x0000} /* "13" */ 84}; 85 86// These are the weekday names and abbreviations of last resort. 87static const UChar gLastResortDayNames[8][2] = 88{ 89 {0x0030, 0x0000}, /* "0" */ 90 {0x0031, 0x0000}, /* "1" */ 91 {0x0032, 0x0000}, /* "2" */ 92 {0x0033, 0x0000}, /* "3" */ 93 {0x0034, 0x0000}, /* "4" */ 94 {0x0035, 0x0000}, /* "5" */ 95 {0x0036, 0x0000}, /* "6" */ 96 {0x0037, 0x0000} /* "7" */ 97}; 98 99// These are the quarter names and abbreviations of last resort. 100static const UChar gLastResortQuarters[4][2] = 101{ 102 {0x0031, 0x0000}, /* "1" */ 103 {0x0032, 0x0000}, /* "2" */ 104 {0x0033, 0x0000}, /* "3" */ 105 {0x0034, 0x0000}, /* "4" */ 106}; 107 108// These are the am/pm and BC/AD markers of last resort. 109static const UChar gLastResortAmPmMarkers[2][3] = 110{ 111 {0x0041, 0x004D, 0x0000}, /* "AM" */ 112 {0x0050, 0x004D, 0x0000} /* "PM" */ 113}; 114 115static const UChar gLastResortEras[2][3] = 116{ 117 {0x0042, 0x0043, 0x0000}, /* "BC" */ 118 {0x0041, 0x0044, 0x0000} /* "AD" */ 119}; 120 121 122// These are the zone strings of last resort. 123static const UChar gLastResortZoneStrings[7][4] = 124{ 125 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ 126 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ 127 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ 128 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ 129 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ 130 {0x0047, 0x004D, 0x0054, 0x0000}, /* "GMT" */ 131 {0x0047, 0x004D, 0x0054, 0x0000} /* "GMT" */ 132}; 133 134static const UChar gLastResortGmtFormat[] = 135 {0x0047, 0x004D, 0x0054, 0x007B, 0x0030, 0x007D, 0x0000}; /* GMT{0} */ 136 137static const UChar gLastResortGmtHourFormats[4][10] = 138{ 139 {0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}, /* -HH:mm:ss */ 140 {0x002D, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000, 0x0000, 0x0000, 0x0000}, /* -HH:mm */ 141 {0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x003A, 0x0073, 0x0073, 0x0000}, /* +HH:mm:ss */ 142 {0x002B, 0x0048, 0x0048, 0x003A, 0x006D, 0x006D, 0x0000, 0x0000, 0x0000, 0x0000} /* +HH:mm */ 143}; 144 145/* Sizes for the last resort string arrays */ 146typedef enum LastResortSize { 147 kMonthNum = 13, 148 kMonthLen = 3, 149 150 kDayNum = 8, 151 kDayLen = 2, 152 153 kAmPmNum = 2, 154 kAmPmLen = 3, 155 156 kQuarterNum = 4, 157 kQuarterLen = 2, 158 159 kEraNum = 2, 160 kEraLen = 3, 161 162 kZoneNum = 5, 163 kZoneLen = 4, 164 165 kGmtHourNum = 4, 166 kGmtHourLen = 10 167} LastResortSize; 168 169U_NAMESPACE_BEGIN 170 171UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateFormatSymbols) 172 173#define kSUPPLEMENTAL "supplementalData" 174 175/** 176 * These are the tags we expect to see in normal resource bundle files associated 177 * with a locale and calendar 178 */ 179static const char gErasTag[]="eras"; 180static const char gMonthNamesTag[]="monthNames"; 181static const char gDayNamesTag[]="dayNames"; 182static const char gNamesWideTag[]="wide"; 183static const char gNamesAbbrTag[]="abbreviated"; 184static const char gNamesNarrowTag[]="narrow"; 185static const char gNamesStandaloneTag[]="stand-alone"; 186static const char gAmPmMarkersTag[]="AmPmMarkers"; 187static const char gQuartersTag[]="quarters"; 188 189static const char gZoneStringsTag[]="zoneStrings"; 190static const char gGmtFormatTag[]="gmtFormat"; 191static const char gHourFormatTag[]="hourFormat"; 192 193static const char gLocalPatternCharsTag[]="localPatternChars"; 194 195static UMTX LOCK; 196 197/** 198 * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly. 199 * Work around this. 200 */ 201static inline UnicodeString* newUnicodeStringArray(size_t count) { 202 return new UnicodeString[count ? count : 1]; 203} 204 205//------------------------------------------------------ 206 207DateFormatSymbols::DateFormatSymbols(const Locale& locale, 208 UErrorCode& status) 209 : UObject() 210{ 211 initializeData(locale, NULL, status); 212} 213 214DateFormatSymbols::DateFormatSymbols(UErrorCode& status) 215 : UObject() 216{ 217 initializeData(Locale::getDefault(), NULL, status, TRUE); 218} 219 220 221DateFormatSymbols::DateFormatSymbols(const Locale& locale, 222 const char *type, 223 UErrorCode& status) 224 : UObject() 225{ 226 initializeData(locale, type, status); 227} 228 229DateFormatSymbols::DateFormatSymbols(const char *type, UErrorCode& status) 230 : UObject() 231{ 232 initializeData(Locale::getDefault(), type, status, TRUE); 233} 234 235DateFormatSymbols::DateFormatSymbols(const DateFormatSymbols& other) 236 : UObject(other) 237{ 238 copyData(other); 239} 240 241void 242DateFormatSymbols::assignArray(UnicodeString*& dstArray, 243 int32_t& dstCount, 244 const UnicodeString* srcArray, 245 int32_t srcCount) 246{ 247 // assignArray() is only called by copyData(), which in turn implements the 248 // copy constructor and the assignment operator. 249 // All strings in a DateFormatSymbols object are created in one of the following 250 // three ways that all allow to safely use UnicodeString::fastCopyFrom(): 251 // - readonly-aliases from resource bundles 252 // - readonly-aliases or allocated strings from constants 253 // - safely cloned strings (with owned buffers) from setXYZ() functions 254 // 255 // Note that this is true for as long as DateFormatSymbols can be constructed 256 // only from a locale bundle or set via the cloning API, 257 // *and* for as long as all the strings are in *private* fields, preventing 258 // a subclass from creating these strings in an "unsafe" way (with respect to fastCopyFrom()). 259 dstCount = srcCount; 260 dstArray = newUnicodeStringArray(srcCount); 261 if(dstArray != NULL) { 262 int32_t i; 263 for(i=0; i<srcCount; ++i) { 264 dstArray[i].fastCopyFrom(srcArray[i]); 265 } 266 } 267} 268 269/** 270 * Create a copy, in fZoneStrings, of the given zone strings array. The 271 * member variables fZoneStringsRowCount and fZoneStringsColCount should 272 * be set already by the caller. 273 */ 274void 275DateFormatSymbols::createZoneStrings(const UnicodeString *const * otherStrings) 276{ 277 int32_t row, col; 278 UBool failed = FALSE; 279 280 fZoneStrings = (UnicodeString **)uprv_malloc(fZoneStringsRowCount * sizeof(UnicodeString *)); 281 if (fZoneStrings != NULL) { 282 for (row=0; row<fZoneStringsRowCount; ++row) 283 { 284 fZoneStrings[row] = newUnicodeStringArray(fZoneStringsColCount); 285 if (fZoneStrings[row] == NULL) { 286 failed = TRUE; 287 break; 288 } 289 for (col=0; col<fZoneStringsColCount; ++col) { 290 // fastCopyFrom() - see assignArray comments 291 fZoneStrings[row][col].fastCopyFrom(otherStrings[row][col]); 292 } 293 } 294 } 295 // If memory allocation failed, roll back and delete fZoneStrings 296 if (failed) { 297 for (int i = row; i >= 0; i--) { 298 delete[] fZoneStrings[i]; 299 } 300 uprv_free(fZoneStrings); 301 fZoneStrings = NULL; 302 } 303} 304 305/** 306 * Copy all of the other's data to this. 307 */ 308void 309DateFormatSymbols::copyData(const DateFormatSymbols& other) { 310 assignArray(fEras, fErasCount, other.fEras, other.fErasCount); 311 assignArray(fEraNames, fEraNamesCount, other.fEraNames, other.fEraNamesCount); 312 assignArray(fNarrowEras, fNarrowErasCount, other.fNarrowEras, other.fNarrowErasCount); 313 assignArray(fMonths, fMonthsCount, other.fMonths, other.fMonthsCount); 314 assignArray(fShortMonths, fShortMonthsCount, other.fShortMonths, other.fShortMonthsCount); 315 assignArray(fNarrowMonths, fNarrowMonthsCount, other.fNarrowMonths, other.fNarrowMonthsCount); 316 assignArray(fStandaloneMonths, fStandaloneMonthsCount, other.fStandaloneMonths, other.fStandaloneMonthsCount); 317 assignArray(fStandaloneShortMonths, fStandaloneShortMonthsCount, other.fStandaloneShortMonths, other.fStandaloneShortMonthsCount); 318 assignArray(fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, other.fStandaloneNarrowMonths, other.fStandaloneNarrowMonthsCount); 319 assignArray(fWeekdays, fWeekdaysCount, other.fWeekdays, other.fWeekdaysCount); 320 assignArray(fShortWeekdays, fShortWeekdaysCount, other.fShortWeekdays, other.fShortWeekdaysCount); 321 assignArray(fNarrowWeekdays, fNarrowWeekdaysCount, other.fNarrowWeekdays, other.fNarrowWeekdaysCount); 322 assignArray(fStandaloneWeekdays, fStandaloneWeekdaysCount, other.fStandaloneWeekdays, other.fStandaloneWeekdaysCount); 323 assignArray(fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, other.fStandaloneShortWeekdays, other.fStandaloneShortWeekdaysCount); 324 assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount); 325 assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount); 326 assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount); 327 assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount); 328 assignArray(fStandaloneQuarters, fStandaloneQuartersCount, other.fStandaloneQuarters, other.fStandaloneQuartersCount); 329 assignArray(fStandaloneShortQuarters, fStandaloneShortQuartersCount, other.fStandaloneShortQuarters, other.fStandaloneShortQuartersCount); 330 fGmtFormat = other.fGmtFormat; 331 assignArray(fGmtHourFormats, fGmtHourFormatsCount, other.fGmtHourFormats, other.fGmtHourFormatsCount); 332 333 if (other.fZoneStrings != NULL) { 334 fZoneStringsColCount = other.fZoneStringsColCount; 335 fZoneStringsRowCount = other.fZoneStringsRowCount; 336 createZoneStrings((const UnicodeString**)other.fZoneStrings); 337 338 } else { 339 fZoneStrings = NULL; 340 fZoneStringsColCount = 0; 341 fZoneStringsRowCount = 0; 342 } 343 fZSFLocale = other.fZSFLocale; 344 // Other zone strings data is created on demand 345 fZoneStringFormat = NULL; 346 fLocaleZoneStrings = NULL; 347 fZSFCachePtr = NULL; 348 fZSFLocal = NULL; 349 350 // fastCopyFrom() - see assignArray comments 351 fLocalPatternChars.fastCopyFrom(other.fLocalPatternChars); 352} 353 354/** 355 * Assignment operator. 356 */ 357DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other) 358{ 359 dispose(); 360 copyData(other); 361 362 return *this; 363} 364 365DateFormatSymbols::~DateFormatSymbols() 366{ 367 dispose(); 368} 369 370void DateFormatSymbols::dispose() 371{ 372 if (fEras) delete[] fEras; 373 if (fEraNames) delete[] fEraNames; 374 if (fNarrowEras) delete[] fNarrowEras; 375 if (fMonths) delete[] fMonths; 376 if (fShortMonths) delete[] fShortMonths; 377 if (fNarrowMonths) delete[] fNarrowMonths; 378 if (fStandaloneMonths) delete[] fStandaloneMonths; 379 if (fStandaloneShortMonths) delete[] fStandaloneShortMonths; 380 if (fStandaloneNarrowMonths) delete[] fStandaloneNarrowMonths; 381 if (fWeekdays) delete[] fWeekdays; 382 if (fShortWeekdays) delete[] fShortWeekdays; 383 if (fNarrowWeekdays) delete[] fNarrowWeekdays; 384 if (fStandaloneWeekdays) delete[] fStandaloneWeekdays; 385 if (fStandaloneShortWeekdays) delete[] fStandaloneShortWeekdays; 386 if (fStandaloneNarrowWeekdays) delete[] fStandaloneNarrowWeekdays; 387 if (fAmPms) delete[] fAmPms; 388 if (fQuarters) delete[] fQuarters; 389 if (fShortQuarters) delete[] fShortQuarters; 390 if (fStandaloneQuarters) delete[] fStandaloneQuarters; 391 if (fStandaloneShortQuarters) delete[] fStandaloneShortQuarters; 392 if (fGmtHourFormats) delete[] fGmtHourFormats; 393 394 disposeZoneStrings(); 395} 396 397void DateFormatSymbols::disposeZoneStrings() 398{ 399 if (fZoneStrings) { 400 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) { 401 delete[] fZoneStrings[row]; 402 } 403 uprv_free(fZoneStrings); 404 } 405 if (fLocaleZoneStrings) { 406 for (int32_t row = 0; row < fZoneStringsRowCount; ++row) { 407 delete[] fLocaleZoneStrings[row]; 408 } 409 uprv_free(fLocaleZoneStrings); 410 } 411 if (fZSFLocal) { 412 delete fZSFLocal; 413 } 414 if (fZSFCachePtr) { 415 delete fZSFCachePtr; 416 } 417 418 fZoneStrings = NULL; 419 fLocaleZoneStrings = NULL; 420 fZoneStringsRowCount = 0; 421 fZoneStringsColCount = 0; 422 423 fZoneStringFormat = NULL; 424 fZSFLocal = NULL; 425 fZSFCachePtr = NULL; 426} 427 428UBool 429DateFormatSymbols::arrayCompare(const UnicodeString* array1, 430 const UnicodeString* array2, 431 int32_t count) 432{ 433 if (array1 == array2) return TRUE; 434 while (count>0) 435 { 436 --count; 437 if (array1[count] != array2[count]) return FALSE; 438 } 439 return TRUE; 440} 441 442UBool 443DateFormatSymbols::operator==(const DateFormatSymbols& other) const 444{ 445 // First do cheap comparisons 446 if (this == &other) { 447 return TRUE; 448 } 449 if (fErasCount == other.fErasCount && 450 fEraNamesCount == other.fEraNamesCount && 451 fNarrowErasCount == other.fNarrowErasCount && 452 fMonthsCount == other.fMonthsCount && 453 fShortMonthsCount == other.fShortMonthsCount && 454 fNarrowMonthsCount == other.fNarrowMonthsCount && 455 fStandaloneMonthsCount == other.fStandaloneMonthsCount && 456 fStandaloneShortMonthsCount == other.fStandaloneShortMonthsCount && 457 fStandaloneNarrowMonthsCount == other.fStandaloneNarrowMonthsCount && 458 fWeekdaysCount == other.fWeekdaysCount && 459 fShortWeekdaysCount == other.fShortWeekdaysCount && 460 fNarrowWeekdaysCount == other.fNarrowWeekdaysCount && 461 fStandaloneWeekdaysCount == other.fStandaloneWeekdaysCount && 462 fStandaloneShortWeekdaysCount == other.fStandaloneShortWeekdaysCount && 463 fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount && 464 fAmPmsCount == other.fAmPmsCount && 465 fQuartersCount == other.fQuartersCount && 466 fShortQuartersCount == other.fShortQuartersCount && 467 fStandaloneQuartersCount == other.fStandaloneQuartersCount && 468 fStandaloneShortQuartersCount == other.fStandaloneShortQuartersCount && 469 fGmtHourFormatsCount == other.fGmtHourFormatsCount && 470 fGmtFormat == other.fGmtFormat) 471 { 472 // Now compare the arrays themselves 473 if (arrayCompare(fEras, other.fEras, fErasCount) && 474 arrayCompare(fEraNames, other.fEraNames, fEraNamesCount) && 475 arrayCompare(fNarrowEras, other.fNarrowEras, fNarrowErasCount) && 476 arrayCompare(fMonths, other.fMonths, fMonthsCount) && 477 arrayCompare(fShortMonths, other.fShortMonths, fShortMonthsCount) && 478 arrayCompare(fNarrowMonths, other.fNarrowMonths, fNarrowMonthsCount) && 479 arrayCompare(fStandaloneMonths, other.fStandaloneMonths, fStandaloneMonthsCount) && 480 arrayCompare(fStandaloneShortMonths, other.fStandaloneShortMonths, fStandaloneShortMonthsCount) && 481 arrayCompare(fStandaloneNarrowMonths, other.fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount) && 482 arrayCompare(fWeekdays, other.fWeekdays, fWeekdaysCount) && 483 arrayCompare(fShortWeekdays, other.fShortWeekdays, fShortWeekdaysCount) && 484 arrayCompare(fNarrowWeekdays, other.fNarrowWeekdays, fNarrowWeekdaysCount) && 485 arrayCompare(fStandaloneWeekdays, other.fStandaloneWeekdays, fStandaloneWeekdaysCount) && 486 arrayCompare(fStandaloneShortWeekdays, other.fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount) && 487 arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) && 488 arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) && 489 arrayCompare(fQuarters, other.fQuarters, fQuartersCount) && 490 arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) && 491 arrayCompare(fStandaloneQuarters, other.fStandaloneQuarters, fStandaloneQuartersCount) && 492 arrayCompare(fStandaloneShortQuarters, other.fStandaloneShortQuarters, fStandaloneShortQuartersCount) && 493 arrayCompare(fGmtHourFormats, other.fGmtHourFormats, fGmtHourFormatsCount)) 494 { 495 // Compare the contents of fZoneStrings 496 if (fZoneStrings == NULL && other.fZoneStrings == NULL) { 497 if (fZSFLocale == other.fZSFLocale) { 498 return TRUE; 499 } 500 } else if (fZoneStrings != NULL && other.fZoneStrings != NULL) { 501 if (fZoneStringsRowCount == other.fZoneStringsRowCount 502 && fZoneStringsColCount == other.fZoneStringsColCount) { 503 UBool cmpres = TRUE; 504 for (int32_t i = 0; (i < fZoneStringsRowCount) && cmpres; i++) { 505 cmpres = arrayCompare(fZoneStrings[i], other.fZoneStrings[i], fZoneStringsColCount); 506 } 507 return cmpres; 508 } 509 } 510 return FALSE; 511 } 512 } 513 return FALSE; 514} 515 516//------------------------------------------------------ 517 518const UnicodeString* 519DateFormatSymbols::getEras(int32_t &count) const 520{ 521 count = fErasCount; 522 return fEras; 523} 524 525const UnicodeString* 526DateFormatSymbols::getEraNames(int32_t &count) const 527{ 528 count = fEraNamesCount; 529 return fEraNames; 530} 531 532const UnicodeString* 533DateFormatSymbols::getNarrowEras(int32_t &count) const 534{ 535 count = fNarrowErasCount; 536 return fNarrowEras; 537} 538 539const UnicodeString* 540DateFormatSymbols::getMonths(int32_t &count) const 541{ 542 count = fMonthsCount; 543 return fMonths; 544} 545 546const UnicodeString* 547DateFormatSymbols::getShortMonths(int32_t &count) const 548{ 549 count = fShortMonthsCount; 550 return fShortMonths; 551} 552 553const UnicodeString* 554DateFormatSymbols::getMonths(int32_t &count, DtContextType context, DtWidthType width ) const 555{ 556 UnicodeString *returnValue = NULL; 557 558 switch (context) { 559 case FORMAT : 560 switch(width) { 561 case WIDE : 562 count = fMonthsCount; 563 returnValue = fMonths; 564 break; 565 case ABBREVIATED : 566 count = fShortMonthsCount; 567 returnValue = fShortMonths; 568 break; 569 case NARROW : 570 count = fNarrowMonthsCount; 571 returnValue = fNarrowMonths; 572 break; 573 case DT_WIDTH_COUNT : 574 break; 575 } 576 break; 577 case STANDALONE : 578 switch(width) { 579 case WIDE : 580 count = fStandaloneMonthsCount; 581 returnValue = fStandaloneMonths; 582 break; 583 case ABBREVIATED : 584 count = fStandaloneShortMonthsCount; 585 returnValue = fStandaloneShortMonths; 586 break; 587 case NARROW : 588 count = fStandaloneNarrowMonthsCount; 589 returnValue = fStandaloneNarrowMonths; 590 break; 591 case DT_WIDTH_COUNT : 592 break; 593 } 594 break; 595 case DT_CONTEXT_COUNT : 596 break; 597 } 598 return returnValue; 599} 600 601const UnicodeString* 602DateFormatSymbols::getWeekdays(int32_t &count) const 603{ 604 count = fWeekdaysCount; 605 return fWeekdays; 606} 607 608const UnicodeString* 609DateFormatSymbols::getShortWeekdays(int32_t &count) const 610{ 611 count = fShortWeekdaysCount; 612 return fShortWeekdays; 613} 614 615const UnicodeString* 616DateFormatSymbols::getWeekdays(int32_t &count, DtContextType context, DtWidthType width) const 617{ 618 UnicodeString *returnValue = NULL; 619 switch (context) { 620 case FORMAT : 621 switch(width) { 622 case WIDE : 623 count = fWeekdaysCount; 624 returnValue = fWeekdays; 625 break; 626 case ABBREVIATED : 627 count = fShortWeekdaysCount; 628 returnValue = fShortWeekdays; 629 break; 630 case NARROW : 631 count = fNarrowWeekdaysCount; 632 returnValue = fNarrowWeekdays; 633 break; 634 case DT_WIDTH_COUNT : 635 break; 636 } 637 break; 638 case STANDALONE : 639 switch(width) { 640 case WIDE : 641 count = fStandaloneWeekdaysCount; 642 returnValue = fStandaloneWeekdays; 643 break; 644 case ABBREVIATED : 645 count = fStandaloneShortWeekdaysCount; 646 returnValue = fStandaloneShortWeekdays; 647 break; 648 case NARROW : 649 count = fStandaloneNarrowWeekdaysCount; 650 returnValue = fStandaloneNarrowWeekdays; 651 break; 652 case DT_WIDTH_COUNT : 653 break; 654 } 655 break; 656 case DT_CONTEXT_COUNT : 657 break; 658 } 659 return returnValue; 660} 661 662const UnicodeString* 663DateFormatSymbols::getQuarters(int32_t &count, DtContextType context, DtWidthType width ) const 664{ 665 UnicodeString *returnValue = NULL; 666 667 switch (context) { 668 case FORMAT : 669 switch(width) { 670 case WIDE : 671 count = fQuartersCount; 672 returnValue = fQuarters; 673 break; 674 case ABBREVIATED : 675 count = fShortQuartersCount; 676 returnValue = fShortQuarters; 677 break; 678 case NARROW : 679 count = 0; 680 returnValue = NULL; 681 break; 682 case DT_WIDTH_COUNT : 683 break; 684 } 685 break; 686 case STANDALONE : 687 switch(width) { 688 case WIDE : 689 count = fStandaloneQuartersCount; 690 returnValue = fStandaloneQuarters; 691 break; 692 case ABBREVIATED : 693 count = fStandaloneShortQuartersCount; 694 returnValue = fStandaloneShortQuarters; 695 break; 696 case NARROW : 697 count = 0; 698 returnValue = NULL; 699 break; 700 case DT_WIDTH_COUNT : 701 break; 702 } 703 break; 704 case DT_CONTEXT_COUNT : 705 break; 706 } 707 return returnValue; 708} 709 710const UnicodeString* 711DateFormatSymbols::getAmPmStrings(int32_t &count) const 712{ 713 count = fAmPmsCount; 714 return fAmPms; 715} 716 717//------------------------------------------------------ 718 719void 720DateFormatSymbols::setEras(const UnicodeString* erasArray, int32_t count) 721{ 722 // delete the old list if we own it 723 if (fEras) 724 delete[] fEras; 725 726 // we always own the new list, which we create here (we duplicate rather 727 // than adopting the list passed in) 728 fEras = newUnicodeStringArray(count); 729 uprv_arrayCopy(erasArray,fEras, count); 730 fErasCount = count; 731} 732 733void 734DateFormatSymbols::setEraNames(const UnicodeString* eraNamesArray, int32_t count) 735{ 736 // delete the old list if we own it 737 if (fEraNames) 738 delete[] fEraNames; 739 740 // we always own the new list, which we create here (we duplicate rather 741 // than adopting the list passed in) 742 fEraNames = newUnicodeStringArray(count); 743 uprv_arrayCopy(eraNamesArray,fEraNames, count); 744 fEraNamesCount = count; 745} 746 747void 748DateFormatSymbols::setNarrowEras(const UnicodeString* narrowErasArray, int32_t count) 749{ 750 // delete the old list if we own it 751 if (fNarrowEras) 752 delete[] fNarrowEras; 753 754 // we always own the new list, which we create here (we duplicate rather 755 // than adopting the list passed in) 756 fNarrowEras = newUnicodeStringArray(count); 757 uprv_arrayCopy(narrowErasArray,fNarrowEras, count); 758 fNarrowErasCount = count; 759} 760 761void 762DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count) 763{ 764 // delete the old list if we own it 765 if (fMonths) 766 delete[] fMonths; 767 768 // we always own the new list, which we create here (we duplicate rather 769 // than adopting the list passed in) 770 fMonths = newUnicodeStringArray(count); 771 uprv_arrayCopy( monthsArray,fMonths,count); 772 fMonthsCount = count; 773} 774 775void 776DateFormatSymbols::setShortMonths(const UnicodeString* shortMonthsArray, int32_t count) 777{ 778 // delete the old list if we own it 779 if (fShortMonths) 780 delete[] fShortMonths; 781 782 // we always own the new list, which we create here (we duplicate rather 783 // than adopting the list passed in) 784 fShortMonths = newUnicodeStringArray(count); 785 uprv_arrayCopy(shortMonthsArray,fShortMonths, count); 786 fShortMonthsCount = count; 787} 788 789void 790DateFormatSymbols::setMonths(const UnicodeString* monthsArray, int32_t count, DtContextType context, DtWidthType width) 791{ 792 // delete the old list if we own it 793 // we always own the new list, which we create here (we duplicate rather 794 // than adopting the list passed in) 795 796 switch (context) { 797 case FORMAT : 798 switch (width) { 799 case WIDE : 800 if (fMonths) 801 delete[] fMonths; 802 fMonths = newUnicodeStringArray(count); 803 uprv_arrayCopy( monthsArray,fMonths,count); 804 fMonthsCount = count; 805 break; 806 case ABBREVIATED : 807 if (fShortMonths) 808 delete[] fShortMonths; 809 fShortMonths = newUnicodeStringArray(count); 810 uprv_arrayCopy( monthsArray,fShortMonths,count); 811 fShortMonthsCount = count; 812 break; 813 case NARROW : 814 if (fNarrowMonths) 815 delete[] fNarrowMonths; 816 fNarrowMonths = newUnicodeStringArray(count); 817 uprv_arrayCopy( monthsArray,fNarrowMonths,count); 818 fNarrowMonthsCount = count; 819 break; 820 case DT_WIDTH_COUNT : 821 break; 822 } 823 break; 824 case STANDALONE : 825 switch (width) { 826 case WIDE : 827 if (fStandaloneMonths) 828 delete[] fStandaloneMonths; 829 fStandaloneMonths = newUnicodeStringArray(count); 830 uprv_arrayCopy( monthsArray,fStandaloneMonths,count); 831 fStandaloneMonthsCount = count; 832 break; 833 case ABBREVIATED : 834 if (fStandaloneShortMonths) 835 delete[] fStandaloneShortMonths; 836 fStandaloneShortMonths = newUnicodeStringArray(count); 837 uprv_arrayCopy( monthsArray,fStandaloneShortMonths,count); 838 fStandaloneShortMonthsCount = count; 839 break; 840 case NARROW : 841 if (fStandaloneNarrowMonths) 842 delete[] fStandaloneNarrowMonths; 843 fStandaloneNarrowMonths = newUnicodeStringArray(count); 844 uprv_arrayCopy( monthsArray,fStandaloneNarrowMonths,count); 845 fStandaloneNarrowMonthsCount = count; 846 break; 847 case DT_WIDTH_COUNT : 848 break; 849 } 850 break; 851 case DT_CONTEXT_COUNT : 852 break; 853 } 854} 855 856void DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count) 857{ 858 // delete the old list if we own it 859 if (fWeekdays) 860 delete[] fWeekdays; 861 862 // we always own the new list, which we create here (we duplicate rather 863 // than adopting the list passed in) 864 fWeekdays = newUnicodeStringArray(count); 865 uprv_arrayCopy(weekdaysArray,fWeekdays,count); 866 fWeekdaysCount = count; 867} 868 869void 870DateFormatSymbols::setShortWeekdays(const UnicodeString* shortWeekdaysArray, int32_t count) 871{ 872 // delete the old list if we own it 873 if (fShortWeekdays) 874 delete[] fShortWeekdays; 875 876 // we always own the new list, which we create here (we duplicate rather 877 // than adopting the list passed in) 878 fShortWeekdays = newUnicodeStringArray(count); 879 uprv_arrayCopy(shortWeekdaysArray, fShortWeekdays, count); 880 fShortWeekdaysCount = count; 881} 882 883void 884DateFormatSymbols::setWeekdays(const UnicodeString* weekdaysArray, int32_t count, DtContextType context, DtWidthType width) 885{ 886 // delete the old list if we own it 887 // we always own the new list, which we create here (we duplicate rather 888 // than adopting the list passed in) 889 890 switch (context) { 891 case FORMAT : 892 switch (width) { 893 case WIDE : 894 if (fWeekdays) 895 delete[] fWeekdays; 896 fWeekdays = newUnicodeStringArray(count); 897 uprv_arrayCopy(weekdaysArray, fWeekdays, count); 898 fWeekdaysCount = count; 899 break; 900 case ABBREVIATED : 901 if (fShortWeekdays) 902 delete[] fShortWeekdays; 903 fShortWeekdays = newUnicodeStringArray(count); 904 uprv_arrayCopy(weekdaysArray, fShortWeekdays, count); 905 fShortWeekdaysCount = count; 906 break; 907 case NARROW : 908 if (fNarrowWeekdays) 909 delete[] fNarrowWeekdays; 910 fNarrowWeekdays = newUnicodeStringArray(count); 911 uprv_arrayCopy(weekdaysArray, fNarrowWeekdays, count); 912 fNarrowWeekdaysCount = count; 913 break; 914 case DT_WIDTH_COUNT : 915 break; 916 } 917 break; 918 case STANDALONE : 919 switch (width) { 920 case WIDE : 921 if (fStandaloneWeekdays) 922 delete[] fStandaloneWeekdays; 923 fStandaloneWeekdays = newUnicodeStringArray(count); 924 uprv_arrayCopy(weekdaysArray, fStandaloneWeekdays, count); 925 fStandaloneWeekdaysCount = count; 926 break; 927 case ABBREVIATED : 928 if (fStandaloneShortWeekdays) 929 delete[] fStandaloneShortWeekdays; 930 fStandaloneShortWeekdays = newUnicodeStringArray(count); 931 uprv_arrayCopy(weekdaysArray, fStandaloneShortWeekdays, count); 932 fStandaloneShortWeekdaysCount = count; 933 break; 934 case NARROW : 935 if (fStandaloneNarrowWeekdays) 936 delete[] fStandaloneNarrowWeekdays; 937 fStandaloneNarrowWeekdays = newUnicodeStringArray(count); 938 uprv_arrayCopy(weekdaysArray, fStandaloneNarrowWeekdays, count); 939 fStandaloneNarrowWeekdaysCount = count; 940 break; 941 case DT_WIDTH_COUNT : 942 break; 943 } 944 break; 945 case DT_CONTEXT_COUNT : 946 break; 947 } 948} 949 950void 951DateFormatSymbols::setQuarters(const UnicodeString* quartersArray, int32_t count, DtContextType context, DtWidthType width) 952{ 953 // delete the old list if we own it 954 // we always own the new list, which we create here (we duplicate rather 955 // than adopting the list passed in) 956 957 switch (context) { 958 case FORMAT : 959 switch (width) { 960 case WIDE : 961 if (fQuarters) 962 delete[] fQuarters; 963 fQuarters = newUnicodeStringArray(count); 964 uprv_arrayCopy( quartersArray,fQuarters,count); 965 fQuartersCount = count; 966 break; 967 case ABBREVIATED : 968 if (fShortQuarters) 969 delete[] fShortQuarters; 970 fShortQuarters = newUnicodeStringArray(count); 971 uprv_arrayCopy( quartersArray,fShortQuarters,count); 972 fShortQuartersCount = count; 973 break; 974 case NARROW : 975 /* 976 if (fNarrowQuarters) 977 delete[] fNarrowQuarters; 978 fNarrowQuarters = newUnicodeStringArray(count); 979 uprv_arrayCopy( quartersArray,fNarrowQuarters,count); 980 fNarrowQuartersCount = count; 981 */ 982 break; 983 case DT_WIDTH_COUNT : 984 break; 985 } 986 break; 987 case STANDALONE : 988 switch (width) { 989 case WIDE : 990 if (fStandaloneQuarters) 991 delete[] fStandaloneQuarters; 992 fStandaloneQuarters = newUnicodeStringArray(count); 993 uprv_arrayCopy( quartersArray,fStandaloneQuarters,count); 994 fStandaloneQuartersCount = count; 995 break; 996 case ABBREVIATED : 997 if (fStandaloneShortQuarters) 998 delete[] fStandaloneShortQuarters; 999 fStandaloneShortQuarters = newUnicodeStringArray(count); 1000 uprv_arrayCopy( quartersArray,fStandaloneShortQuarters,count); 1001 fStandaloneShortQuartersCount = count; 1002 break; 1003 case NARROW : 1004 /* 1005 if (fStandaloneNarrowQuarters) 1006 delete[] fStandaloneNarrowQuarters; 1007 fStandaloneNarrowQuarters = newUnicodeStringArray(count); 1008 uprv_arrayCopy( quartersArray,fStandaloneNarrowQuarters,count); 1009 fStandaloneNarrowQuartersCount = count; 1010 */ 1011 break; 1012 case DT_WIDTH_COUNT : 1013 break; 1014 } 1015 break; 1016 case DT_CONTEXT_COUNT : 1017 break; 1018 } 1019} 1020 1021void 1022DateFormatSymbols::setAmPmStrings(const UnicodeString* amPmsArray, int32_t count) 1023{ 1024 // delete the old list if we own it 1025 if (fAmPms) delete[] fAmPms; 1026 1027 // we always own the new list, which we create here (we duplicate rather 1028 // than adopting the list passed in) 1029 fAmPms = newUnicodeStringArray(count); 1030 uprv_arrayCopy(amPmsArray,fAmPms,count); 1031 fAmPmsCount = count; 1032} 1033 1034//------------------------------------------------------ 1035const ZoneStringFormat* 1036DateFormatSymbols::getZoneStringFormat(void) const { 1037 umtx_lock(&LOCK); 1038 if (fZoneStringFormat == NULL) { 1039 ((DateFormatSymbols*)this)->initZoneStringFormat(); 1040 } 1041 umtx_unlock(&LOCK); 1042 return fZoneStringFormat; 1043} 1044 1045void 1046DateFormatSymbols::initZoneStringFormat(void) { 1047 if (fZoneStringFormat == NULL) { 1048 UErrorCode status = U_ZERO_ERROR; 1049 if (fZoneStrings) { 1050 // Create an istance of ZoneStringFormat by the custom zone strings array 1051 fZSFLocal = new ZoneStringFormat(fZoneStrings, fZoneStringsRowCount, 1052 fZoneStringsColCount, status); 1053 if (U_FAILURE(status)) { 1054 delete fZSFLocal; 1055 } else { 1056 fZoneStringFormat = (const ZoneStringFormat*)fZSFLocal; 1057 } 1058 } else { 1059 fZSFCachePtr = ZoneStringFormat::getZoneStringFormat(fZSFLocale, status); 1060 if (U_FAILURE(status)) { 1061 delete fZSFCachePtr; 1062 } else { 1063 fZoneStringFormat = fZSFCachePtr->get(); 1064 } 1065 } 1066 } 1067} 1068 1069const UnicodeString** 1070DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const 1071{ 1072 const UnicodeString **result = NULL; 1073 1074 umtx_lock(&LOCK); 1075 if (fZoneStrings == NULL) { 1076 if (fLocaleZoneStrings == NULL) { 1077 ((DateFormatSymbols*)this)->initZoneStringsArray(); 1078 } 1079 result = (const UnicodeString**)fLocaleZoneStrings; 1080 } else { 1081 result = (const UnicodeString**)fZoneStrings; 1082 } 1083 rowCount = fZoneStringsRowCount; 1084 columnCount = fZoneStringsColCount; 1085 umtx_unlock(&LOCK); 1086 1087 return result; 1088} 1089 1090void 1091DateFormatSymbols::initZoneStringsArray(void) { 1092 if (fZoneStrings == NULL && fLocaleZoneStrings == NULL) { 1093 if (fZoneStringFormat == NULL) { 1094 initZoneStringFormat(); 1095 } 1096 if (fZoneStringFormat) { 1097 UErrorCode status = U_ZERO_ERROR; 1098 fLocaleZoneStrings = fZoneStringFormat->createZoneStringsArray(uprv_getUTCtime() /* use current time */, 1099 fZoneStringsRowCount, fZoneStringsColCount, status); 1100 } 1101 } 1102} 1103 1104void 1105DateFormatSymbols::setZoneStrings(const UnicodeString* const *strings, int32_t rowCount, int32_t columnCount) 1106{ 1107 // since deleting a 2-d array is a pain in the butt, we offload that task to 1108 // a separate function 1109 disposeZoneStrings(); 1110 // we always own the new list, which we create here (we duplicate rather 1111 // than adopting the list passed in) 1112 fZoneStringsRowCount = rowCount; 1113 fZoneStringsColCount = columnCount; 1114 createZoneStrings((const UnicodeString**)strings); 1115} 1116 1117//------------------------------------------------------ 1118 1119const UChar * U_EXPORT2 1120DateFormatSymbols::getPatternUChars(void) 1121{ 1122 return gPatternChars; 1123} 1124 1125//------------------------------------------------------ 1126 1127UnicodeString& 1128DateFormatSymbols::getLocalPatternChars(UnicodeString& result) const 1129{ 1130 // fastCopyFrom() - see assignArray comments 1131 return result.fastCopyFrom(fLocalPatternChars); 1132} 1133 1134//------------------------------------------------------ 1135 1136void 1137DateFormatSymbols::setLocalPatternChars(const UnicodeString& newLocalPatternChars) 1138{ 1139 fLocalPatternChars = newLocalPatternChars; 1140} 1141 1142//------------------------------------------------------ 1143 1144static void 1145initField(UnicodeString **field, int32_t& length, const UResourceBundle *data, UErrorCode &status) { 1146 if (U_SUCCESS(status)) { 1147 int32_t strLen = 0; 1148 length = ures_getSize(data); 1149 *field = newUnicodeStringArray(length); 1150 if (*field) { 1151 for(int32_t i = 0; i<length; i++) { 1152 const UChar *resStr = ures_getStringByIndex(data, i, &strLen, &status); 1153 // setTo() - see assignArray comments 1154 (*(field)+i)->setTo(TRUE, resStr, strLen); 1155 } 1156 } 1157 else { 1158 length = 0; 1159 status = U_MEMORY_ALLOCATION_ERROR; 1160 } 1161 } 1162} 1163 1164static void 1165initField(UnicodeString **field, int32_t& length, const UChar *data, LastResortSize numStr, LastResortSize strLen, UErrorCode &status) { 1166 if (U_SUCCESS(status)) { 1167 length = numStr; 1168 *field = newUnicodeStringArray((size_t)numStr); 1169 if (*field) { 1170 for(int32_t i = 0; i<length; i++) { 1171 // readonly aliases - all "data" strings are constant 1172 // -1 as length for variable-length strings (gLastResortDayNames[0] is empty) 1173 (*(field)+i)->setTo(TRUE, data+(i*((int32_t)strLen)), -1); 1174 } 1175 } 1176 else { 1177 length = 0; 1178 status = U_MEMORY_ALLOCATION_ERROR; 1179 } 1180 } 1181} 1182 1183void 1184DateFormatSymbols::initializeData(const Locale& locale, const char *type, UErrorCode& status, UBool useLastResortData) 1185{ 1186 int32_t i; 1187 int32_t len = 0; 1188 const UChar *resStr; 1189 /* In case something goes wrong, initialize all of the data to NULL. */ 1190 fEras = NULL; 1191 fErasCount = 0; 1192 fEraNames = NULL; 1193 fEraNamesCount = 0; 1194 fNarrowEras = NULL; 1195 fNarrowErasCount = 0; 1196 fMonths = NULL; 1197 fMonthsCount=0; 1198 fShortMonths = NULL; 1199 fShortMonthsCount=0; 1200 fNarrowMonths = NULL; 1201 fNarrowMonthsCount=0; 1202 fStandaloneMonths = NULL; 1203 fStandaloneMonthsCount=0; 1204 fStandaloneShortMonths = NULL; 1205 fStandaloneShortMonthsCount=0; 1206 fStandaloneNarrowMonths = NULL; 1207 fStandaloneNarrowMonthsCount=0; 1208 fWeekdays = NULL; 1209 fWeekdaysCount=0; 1210 fShortWeekdays = NULL; 1211 fShortWeekdaysCount=0; 1212 fNarrowWeekdays = NULL; 1213 fNarrowWeekdaysCount=0; 1214 fStandaloneWeekdays = NULL; 1215 fStandaloneWeekdaysCount=0; 1216 fStandaloneShortWeekdays = NULL; 1217 fStandaloneShortWeekdaysCount=0; 1218 fStandaloneNarrowWeekdays = NULL; 1219 fStandaloneNarrowWeekdaysCount=0; 1220 fAmPms = NULL; 1221 fAmPmsCount=0; 1222 fQuarters = NULL; 1223 fQuartersCount = 0; 1224 fShortQuarters = NULL; 1225 fShortQuartersCount = 0; 1226 fStandaloneQuarters = NULL; 1227 fStandaloneQuartersCount = 0; 1228 fStandaloneShortQuarters = NULL; 1229 fStandaloneShortQuartersCount = 0; 1230 fGmtHourFormats = NULL; 1231 fGmtHourFormatsCount = 0; 1232 fZoneStringsRowCount = 0; 1233 fZoneStringsColCount = 0; 1234 fZoneStrings = NULL; 1235 fLocaleZoneStrings = NULL; 1236 1237 fZoneStringFormat = NULL; 1238 fZSFLocal = NULL; 1239 fZSFCachePtr = NULL; 1240 1241 // We need to preserve the requested locale for 1242 // lazy ZoneStringFormat instantiation. ZoneStringFormat 1243 // is region sensitive, thus, bundle locale bundle's locale 1244 // is not sufficient. 1245 fZSFLocale = locale; 1246 1247 if (U_FAILURE(status)) return; 1248 1249 /** 1250 * Retrieve the string arrays we need from the resource bundle file. 1251 * We cast away const here, but that's okay; we won't delete any of 1252 * these. 1253 */ 1254 CalendarData calData(locale, type, status); 1255 1256 /** 1257 * Use the localeBundle for getting zone GMT formatting patterns 1258 */ 1259 UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status); 1260 UResourceBundle *zoneStringsArray = ures_getByKeyWithFallback(localeBundle, gZoneStringsTag, NULL, &status); 1261 1262 // load the first data item 1263 UResourceBundle *erasMain = calData.getByKey(gErasTag, status); 1264 UResourceBundle *eras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status); 1265 UErrorCode oldStatus = status; 1266 UResourceBundle *eraNames = ures_getByKeyWithFallback(erasMain, gNamesWideTag, NULL, &status); 1267 if ( status == U_MISSING_RESOURCE_ERROR ) { // Workaround because eras/wide was omitted from CLDR 1.3 1268 status = oldStatus; 1269 eraNames = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status); 1270 } 1271 // current ICU4J falls back to abbreviated if narrow eras are missing, so we will too 1272 oldStatus = status; 1273 UResourceBundle *narrowEras = ures_getByKeyWithFallback(erasMain, gNamesNarrowTag, NULL, &status); 1274 if ( status == U_MISSING_RESOURCE_ERROR ) { 1275 status = oldStatus; 1276 narrowEras = ures_getByKeyWithFallback(erasMain, gNamesAbbrTag, NULL, &status); 1277 } 1278 1279 UResourceBundle *lsweekdaysData = NULL; // Data closed by calData 1280 UResourceBundle *weekdaysData = NULL; // Data closed by calData 1281 UResourceBundle *narrowWeekdaysData = NULL; // Data closed by calData 1282 UResourceBundle *standaloneWeekdaysData = NULL; // Data closed by calData 1283 UResourceBundle *standaloneShortWeekdaysData = NULL; // Data closed by calData 1284 UResourceBundle *standaloneNarrowWeekdaysData = NULL; // Data closed by calData 1285 1286 U_LOCALE_BASED(locBased, *this); 1287 if (U_FAILURE(status)) 1288 { 1289 if (useLastResortData) 1290 { 1291 // Handle the case in which there is no resource data present. 1292 // We don't have to generate usable patterns in this situation; 1293 // we just need to produce something that will be semi-intelligible 1294 // in most locales. 1295 1296 status = U_USING_FALLBACK_WARNING; 1297 1298 initField(&fEras, fErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status); 1299 initField(&fEraNames, fEraNamesCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status); 1300 initField(&fNarrowEras, fNarrowErasCount, (const UChar *)gLastResortEras, kEraNum, kEraLen, status); 1301 initField(&fMonths, fMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); 1302 initField(&fShortMonths, fShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); 1303 initField(&fNarrowMonths, fNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); 1304 initField(&fStandaloneMonths, fStandaloneMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); 1305 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); 1306 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, (const UChar *)gLastResortMonthNames, kMonthNum, kMonthLen, status); 1307 initField(&fWeekdays, fWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); 1308 initField(&fShortWeekdays, fShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); 1309 initField(&fNarrowWeekdays, fNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); 1310 initField(&fStandaloneWeekdays, fStandaloneWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); 1311 initField(&fStandaloneShortWeekdays, fStandaloneShortWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); 1312 initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); 1313 initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status); 1314 initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); 1315 initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); 1316 initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); 1317 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); 1318 initField(&fGmtHourFormats, fGmtHourFormatsCount, (const UChar *)gLastResortGmtHourFormats, kGmtHourNum, kGmtHourLen, status); 1319 fGmtFormat.setTo(TRUE, gLastResortGmtFormat, -1); 1320 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN); 1321 } 1322 goto cleanup; 1323 } 1324 1325 // if we make it to here, the resource data is cool, and we can get everything out 1326 // of it that we need except for the time-zone and localized-pattern data, which 1327 // are stored in a separate file 1328 locBased.setLocaleIDs(ures_getLocaleByType(eras, ULOC_VALID_LOCALE, &status), 1329 ures_getLocaleByType(eras, ULOC_ACTUAL_LOCALE, &status)); 1330 1331 initField(&fEras, fErasCount, eras, status); 1332 initField(&fEraNames, fEraNamesCount, eraNames, status); 1333 initField(&fNarrowEras, fNarrowErasCount, narrowEras, status); 1334 1335 initField(&fMonths, fMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status); 1336 initField(&fShortMonths, fShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); 1337 1338 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status); 1339 if(status == U_MISSING_RESOURCE_ERROR) { 1340 status = U_ZERO_ERROR; 1341 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status); 1342 } 1343 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If format/narrow not available, use format/abbreviated */ 1344 status = U_ZERO_ERROR; 1345 initField(&fNarrowMonths, fNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); 1346 } 1347 1348 initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesWideTag, status), status); 1349 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/wide not available, use format/wide */ 1350 status = U_ZERO_ERROR; 1351 initField(&fStandaloneMonths, fStandaloneMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesWideTag, status), status); 1352 } 1353 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status), status); 1354 if ( status == U_MISSING_RESOURCE_ERROR ) { /* If standalone/abbreviated not available, use format/abbreviated */ 1355 status = U_ZERO_ERROR; 1356 initField(&fStandaloneShortMonths, fStandaloneShortMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); 1357 } 1358 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey3(gMonthNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status), status); 1359 if ( status == U_MISSING_RESOURCE_ERROR ) { /* if standalone/narrow not availabe, try format/narrow */ 1360 status = U_ZERO_ERROR; 1361 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesNarrowTag, status), status); 1362 if ( status == U_MISSING_RESOURCE_ERROR ) { /* if still not there, use format/abbreviated */ 1363 status = U_ZERO_ERROR; 1364 initField(&fStandaloneNarrowMonths, fStandaloneNarrowMonthsCount, calData.getByKey2(gMonthNamesTag, gNamesAbbrTag, status), status); 1365 } 1366 } 1367 initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status); 1368 1369 initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status); 1370 initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status); 1371 1372 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesWideTag, status), status); 1373 if(status == U_MISSING_RESOURCE_ERROR) { 1374 status = U_ZERO_ERROR; 1375 initField(&fStandaloneQuarters, fStandaloneQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status); 1376 } 1377 1378 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey3(gQuartersTag, gNamesStandaloneTag, gNamesAbbrTag, status), status); 1379 if(status == U_MISSING_RESOURCE_ERROR) { 1380 status = U_ZERO_ERROR; 1381 initField(&fStandaloneShortQuarters, fStandaloneShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status); 1382 } 1383 1384 // GMT format patterns 1385 resStr = ures_getStringByKeyWithFallback(zoneStringsArray, gGmtFormatTag, &len, &status); 1386 if (len > 0) { 1387 fGmtFormat.setTo(TRUE, resStr, len); 1388 } 1389 1390 resStr = ures_getStringByKeyWithFallback(zoneStringsArray, gHourFormatTag, &len, &status); 1391 if (len > 0) { 1392 UChar *sep = u_strchr(resStr, (UChar)0x003B /* ';' */); 1393 if (sep != NULL) { 1394 fGmtHourFormats = newUnicodeStringArray(GMT_HOUR_COUNT); 1395 if (fGmtHourFormats == NULL) { 1396 status = U_MEMORY_ALLOCATION_ERROR; 1397 } else { 1398 fGmtHourFormatsCount = GMT_HOUR_COUNT; 1399 fGmtHourFormats[GMT_NEGATIVE_HM].setTo(TRUE, sep + 1, -1); 1400 fGmtHourFormats[GMT_POSITIVE_HM].setTo(FALSE, resStr, sep - resStr); 1401 1402 // CLDR 1.5 does not have GMT offset pattern including second field. 1403 // For now, append "ss" to the end. 1404 if (fGmtHourFormats[GMT_NEGATIVE_HM].indexOf((UChar)0x003A /* ':' */) != -1) { 1405 fGmtHourFormats[GMT_NEGATIVE_HMS] = fGmtHourFormats[GMT_NEGATIVE_HM] + UNICODE_STRING_SIMPLE(":ss"); 1406 } else if (fGmtHourFormats[GMT_NEGATIVE_HM].indexOf((UChar)0x002E /* '.' */) != -1) { 1407 fGmtHourFormats[GMT_NEGATIVE_HMS] = fGmtHourFormats[GMT_NEGATIVE_HM] + UNICODE_STRING_SIMPLE(".ss"); 1408 } else { 1409 fGmtHourFormats[GMT_NEGATIVE_HMS] = fGmtHourFormats[GMT_NEGATIVE_HM] + UNICODE_STRING_SIMPLE("ss"); 1410 } 1411 if (fGmtHourFormats[GMT_POSITIVE_HM].indexOf((UChar)0x003A /* ':' */) != -1) { 1412 fGmtHourFormats[GMT_POSITIVE_HMS] = fGmtHourFormats[GMT_POSITIVE_HM] + UNICODE_STRING_SIMPLE(":ss"); 1413 } else if (fGmtHourFormats[GMT_POSITIVE_HM].indexOf((UChar)0x002E /* '.' */) != -1) { 1414 fGmtHourFormats[GMT_POSITIVE_HMS] = fGmtHourFormats[GMT_POSITIVE_HM] + UNICODE_STRING_SIMPLE(".ss"); 1415 } else { 1416 fGmtHourFormats[GMT_POSITIVE_HMS] = fGmtHourFormats[GMT_POSITIVE_HM] + UNICODE_STRING_SIMPLE("ss"); 1417 } 1418 } 1419 } 1420 } 1421 1422 // ICU 3.8 or later version no longer uses localized date-time pattern characters by default (ticket#5597) 1423 /* 1424 // fastCopyFrom()/setTo() - see assignArray comments 1425 resStr = ures_getStringByKey(fResourceBundle, gLocalPatternCharsTag, &len, &status); 1426 fLocalPatternChars.setTo(TRUE, resStr, len); 1427 // If the locale data does not include new pattern chars, use the defaults 1428 // TODO: Consider making this an error, since this may add conflicting characters. 1429 if (len < PATTERN_CHARS_LEN) { 1430 fLocalPatternChars.append(UnicodeString(TRUE, &gPatternChars[len], PATTERN_CHARS_LEN-len)); 1431 } 1432 */ 1433 fLocalPatternChars.setTo(TRUE, gPatternChars, PATTERN_CHARS_LEN); 1434 1435 // {sfb} fixed to handle 1-based weekdays 1436 weekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status); 1437 fWeekdaysCount = ures_getSize(weekdaysData); 1438 fWeekdays = new UnicodeString[fWeekdaysCount+1]; 1439 /* pin the blame on system. If we cannot get a chunk of memory .. the system is dying!*/ 1440 if (fWeekdays == NULL) { 1441 status = U_MEMORY_ALLOCATION_ERROR; 1442 goto cleanup; 1443 } 1444 // leave fWeekdays[0] empty 1445 for(i = 0; i<fWeekdaysCount; i++) { 1446 resStr = ures_getStringByIndex(weekdaysData, i, &len, &status); 1447 // setTo() - see assignArray comments 1448 fWeekdays[i+1].setTo(TRUE, resStr, len); 1449 } 1450 fWeekdaysCount++; 1451 1452 lsweekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status); 1453 fShortWeekdaysCount = ures_getSize(lsweekdaysData); 1454 fShortWeekdays = new UnicodeString[fShortWeekdaysCount+1]; 1455 /* test for NULL */ 1456 if (fShortWeekdays == 0) { 1457 status = U_MEMORY_ALLOCATION_ERROR; 1458 goto cleanup; 1459 } 1460 // leave fShortWeekdays[0] empty 1461 for(i = 0; i<fShortWeekdaysCount; i++) { 1462 resStr = ures_getStringByIndex(lsweekdaysData, i, &len, &status); 1463 // setTo() - see assignArray comments 1464 fShortWeekdays[i+1].setTo(TRUE, resStr, len); 1465 } 1466 fShortWeekdaysCount++; 1467 1468 narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status); 1469 if(status == U_MISSING_RESOURCE_ERROR) { 1470 status = U_ZERO_ERROR; 1471 narrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status); 1472 } 1473 if ( status == U_MISSING_RESOURCE_ERROR ) { 1474 status = U_ZERO_ERROR; 1475 narrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status); 1476 } 1477 fNarrowWeekdaysCount = ures_getSize(narrowWeekdaysData); 1478 fNarrowWeekdays = new UnicodeString[fNarrowWeekdaysCount+1]; 1479 /* test for NULL */ 1480 if (fNarrowWeekdays == 0) { 1481 status = U_MEMORY_ALLOCATION_ERROR; 1482 goto cleanup; 1483 } 1484 // leave fNarrowWeekdays[0] empty 1485 for(i = 0; i<fNarrowWeekdaysCount; i++) { 1486 resStr = ures_getStringByIndex(narrowWeekdaysData, i, &len, &status); 1487 // setTo() - see assignArray comments 1488 fNarrowWeekdays[i+1].setTo(TRUE, resStr, len); 1489 } 1490 fNarrowWeekdaysCount++; 1491 1492 standaloneWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesWideTag, status); 1493 if ( status == U_MISSING_RESOURCE_ERROR ) { 1494 status = U_ZERO_ERROR; 1495 standaloneWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesWideTag, status); 1496 } 1497 fStandaloneWeekdaysCount = ures_getSize(standaloneWeekdaysData); 1498 fStandaloneWeekdays = new UnicodeString[fStandaloneWeekdaysCount+1]; 1499 /* test for NULL */ 1500 if (fStandaloneWeekdays == 0) { 1501 status = U_MEMORY_ALLOCATION_ERROR; 1502 goto cleanup; 1503 } 1504 // leave fStandaloneWeekdays[0] empty 1505 for(i = 0; i<fStandaloneWeekdaysCount; i++) { 1506 resStr = ures_getStringByIndex(standaloneWeekdaysData, i, &len, &status); 1507 // setTo() - see assignArray comments 1508 fStandaloneWeekdays[i+1].setTo(TRUE, resStr, len); 1509 } 1510 fStandaloneWeekdaysCount++; 1511 1512 standaloneShortWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesAbbrTag, status); 1513 if ( status == U_MISSING_RESOURCE_ERROR ) { 1514 status = U_ZERO_ERROR; 1515 standaloneShortWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status); 1516 } 1517 fStandaloneShortWeekdaysCount = ures_getSize(standaloneShortWeekdaysData); 1518 fStandaloneShortWeekdays = new UnicodeString[fStandaloneShortWeekdaysCount+1]; 1519 /* test for NULL */ 1520 if (fStandaloneShortWeekdays == 0) { 1521 status = U_MEMORY_ALLOCATION_ERROR; 1522 goto cleanup; 1523 } 1524 // leave fStandaloneShortWeekdays[0] empty 1525 for(i = 0; i<fStandaloneShortWeekdaysCount; i++) { 1526 resStr = ures_getStringByIndex(standaloneShortWeekdaysData, i, &len, &status); 1527 // setTo() - see assignArray comments 1528 fStandaloneShortWeekdays[i+1].setTo(TRUE, resStr, len); 1529 } 1530 fStandaloneShortWeekdaysCount++; 1531 1532 standaloneNarrowWeekdaysData = calData.getByKey3(gDayNamesTag, gNamesStandaloneTag, gNamesNarrowTag, status); 1533 if ( status == U_MISSING_RESOURCE_ERROR ) { 1534 status = U_ZERO_ERROR; 1535 standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesNarrowTag, status); 1536 if ( status == U_MISSING_RESOURCE_ERROR ) { 1537 status = U_ZERO_ERROR; 1538 standaloneNarrowWeekdaysData = calData.getByKey2(gDayNamesTag, gNamesAbbrTag, status); 1539 } 1540 } 1541 fStandaloneNarrowWeekdaysCount = ures_getSize(standaloneNarrowWeekdaysData); 1542 fStandaloneNarrowWeekdays = new UnicodeString[fStandaloneNarrowWeekdaysCount+1]; 1543 /* test for NULL */ 1544 if (fStandaloneNarrowWeekdays == 0) { 1545 status = U_MEMORY_ALLOCATION_ERROR; 1546 goto cleanup; 1547 } 1548 // leave fStandaloneNarrowWeekdays[0] empty 1549 for(i = 0; i<fStandaloneNarrowWeekdaysCount; i++) { 1550 resStr = ures_getStringByIndex(standaloneNarrowWeekdaysData, i, &len, &status); 1551 // setTo() - see assignArray comments 1552 fStandaloneNarrowWeekdays[i+1].setTo(TRUE, resStr, len); 1553 } 1554 fStandaloneNarrowWeekdaysCount++; 1555 1556cleanup: 1557 ures_close(eras); 1558 ures_close(eraNames); 1559 ures_close(narrowEras); 1560 ures_close(zoneStringsArray); 1561 ures_close(localeBundle); 1562} 1563 1564Locale 1565DateFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const { 1566 U_LOCALE_BASED(locBased, *this); 1567 return locBased.getLocale(type, status); 1568} 1569 1570U_NAMESPACE_END 1571 1572#endif /* #if !UCONFIG_NO_FORMATTING */ 1573 1574//eof 1575