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