1 /* 2 ******************************************************************************* 3 * Copyright (C) 1996-2012, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ******************************************************************************* 6 */ 7 8 #include "unicode/utypes.h" 9 10 #if !UCONFIG_NO_FORMATTING 11 12 #include "unicode/udat.h" 13 14 #include "unicode/uloc.h" 15 #include "unicode/datefmt.h" 16 #include "unicode/timezone.h" 17 #include "unicode/smpdtfmt.h" 18 #include "unicode/fieldpos.h" 19 #include "unicode/parsepos.h" 20 #include "unicode/calendar.h" 21 #include "unicode/numfmt.h" 22 #include "unicode/dtfmtsym.h" 23 #include "unicode/ustring.h" 24 #include "unicode/udisplaycontext.h" 25 #include "cpputils.h" 26 #include "reldtfmt.h" 27 #include "umutex.h" 28 29 U_NAMESPACE_USE 30 31 /** 32 * Verify that fmt is a SimpleDateFormat. Invalid error if not. 33 * @param fmt the UDateFormat, definitely a DateFormat, maybe something else 34 * @param status error code, will be set to failure if there is a familure or the fmt is NULL. 35 */ 36 static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) { 37 if(U_SUCCESS(*status) && 38 dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) { 39 *status = U_ILLEGAL_ARGUMENT_ERROR; 40 } 41 } 42 43 // This mirrors the correspondence between the 44 // SimpleDateFormat::fgPatternIndexToDateFormatField and 45 // SimpleDateFormat::fgPatternIndexToCalendarField arrays. 46 static UCalendarDateFields gDateFieldMapping[] = { 47 UCAL_ERA, // UDAT_ERA_FIELD = 0 48 UCAL_YEAR, // UDAT_YEAR_FIELD = 1 49 UCAL_MONTH, // UDAT_MONTH_FIELD = 2 50 UCAL_DATE, // UDAT_DATE_FIELD = 3 51 UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY1_FIELD = 4 52 UCAL_HOUR_OF_DAY, // UDAT_HOUR_OF_DAY0_FIELD = 5 53 UCAL_MINUTE, // UDAT_MINUTE_FIELD = 6 54 UCAL_SECOND, // UDAT_SECOND_FIELD = 7 55 UCAL_MILLISECOND, // UDAT_FRACTIONAL_SECOND_FIELD = 8 56 UCAL_DAY_OF_WEEK, // UDAT_DAY_OF_WEEK_FIELD = 9 57 UCAL_DAY_OF_YEAR, // UDAT_DAY_OF_YEAR_FIELD = 10 58 UCAL_DAY_OF_WEEK_IN_MONTH, // UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11 59 UCAL_WEEK_OF_YEAR, // UDAT_WEEK_OF_YEAR_FIELD = 12 60 UCAL_WEEK_OF_MONTH, // UDAT_WEEK_OF_MONTH_FIELD = 13 61 UCAL_AM_PM, // UDAT_AM_PM_FIELD = 14 62 UCAL_HOUR, // UDAT_HOUR1_FIELD = 15 63 UCAL_HOUR, // UDAT_HOUR0_FIELD = 16 64 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_FIELD = 17 65 UCAL_YEAR_WOY, // UDAT_YEAR_WOY_FIELD = 18 66 UCAL_DOW_LOCAL, // UDAT_DOW_LOCAL_FIELD = 19 67 UCAL_EXTENDED_YEAR, // UDAT_EXTENDED_YEAR_FIELD = 20 68 UCAL_JULIAN_DAY, // UDAT_JULIAN_DAY_FIELD = 21 69 UCAL_MILLISECONDS_IN_DAY, // UDAT_MILLISECONDS_IN_DAY_FIELD = 22 70 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_RFC_FIELD = 23 71 // UCAL_DST_OFFSET also 72 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_GENERIC_FIELD = 24 73 UCAL_DOW_LOCAL, // UDAT_STANDALONE_DAY_FIELD = 25 74 UCAL_MONTH, // UDAT_STANDALONE_MONTH_FIELD = 26 75 UCAL_MONTH, // UDAT_QUARTER_FIELD = 27 76 UCAL_MONTH, // UDAT_STANDALONE_QUARTER_FIELD = 28 77 UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_SPECIAL_FIELD = 29 78 UCAL_YEAR, // UDAT_YEAR_NAME_FIELD = 30 79 UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 31 80 // UCAL_IS_LEAP_MONTH is not the target of a mapping 81 }; 82 83 U_CAPI UCalendarDateFields U_EXPORT2 84 udat_toCalendarDateField(UDateFormatField field) { 85 return gDateFieldMapping[field]; 86 } 87 88 /* For now- one opener. */ 89 static UDateFormatOpener gOpener = NULL; 90 91 U_INTERNAL void U_EXPORT2 92 udat_registerOpener(UDateFormatOpener opener, UErrorCode *status) 93 { 94 if(U_FAILURE(*status)) return; 95 umtx_lock(NULL); 96 if(gOpener==NULL) { 97 gOpener = opener; 98 } else { 99 *status = U_ILLEGAL_ARGUMENT_ERROR; 100 } 101 umtx_unlock(NULL); 102 } 103 104 U_INTERNAL UDateFormatOpener U_EXPORT2 105 udat_unregisterOpener(UDateFormatOpener opener, UErrorCode *status) 106 { 107 if(U_FAILURE(*status)) return NULL; 108 UDateFormatOpener oldOpener = NULL; 109 umtx_lock(NULL); 110 if(gOpener==NULL || gOpener!=opener) { 111 *status = U_ILLEGAL_ARGUMENT_ERROR; 112 } else { 113 oldOpener=gOpener; 114 gOpener=NULL; 115 } 116 umtx_unlock(NULL); 117 return oldOpener; 118 } 119 120 121 122 U_CAPI UDateFormat* U_EXPORT2 123 udat_open(UDateFormatStyle timeStyle, 124 UDateFormatStyle dateStyle, 125 const char *locale, 126 const UChar *tzID, 127 int32_t tzIDLength, 128 const UChar *pattern, 129 int32_t patternLength, 130 UErrorCode *status) 131 { 132 DateFormat *fmt; 133 if(U_FAILURE(*status)) { 134 return 0; 135 } 136 if(gOpener!=NULL) { // if it's registered 137 fmt = (DateFormat*) (*gOpener)(timeStyle,dateStyle,locale,tzID,tzIDLength,pattern,patternLength,status); 138 if(fmt!=NULL) { 139 return (UDateFormat*)fmt; 140 } // else fall through. 141 } 142 if(timeStyle != UDAT_PATTERN) { 143 if(locale == 0) { 144 fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, 145 (DateFormat::EStyle)timeStyle); 146 } 147 else { 148 fmt = DateFormat::createDateTimeInstance((DateFormat::EStyle)dateStyle, 149 (DateFormat::EStyle)timeStyle, 150 Locale(locale)); 151 } 152 } 153 else { 154 UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); 155 156 if(locale == 0) { 157 fmt = new SimpleDateFormat(pat, *status); 158 } 159 else { 160 fmt = new SimpleDateFormat(pat, Locale(locale), *status); 161 } 162 } 163 164 if(fmt == 0) { 165 *status = U_MEMORY_ALLOCATION_ERROR; 166 return 0; 167 } 168 169 if(tzID != 0) { 170 TimeZone *zone = TimeZone::createTimeZone(UnicodeString((UBool)(tzIDLength == -1), tzID, tzIDLength)); 171 if(zone == 0) { 172 *status = U_MEMORY_ALLOCATION_ERROR; 173 delete fmt; 174 return 0; 175 } 176 fmt->adoptTimeZone(zone); 177 } 178 179 return (UDateFormat*)fmt; 180 } 181 182 183 U_CAPI void U_EXPORT2 184 udat_close(UDateFormat* format) 185 { 186 delete (DateFormat*)format; 187 } 188 189 U_CAPI UDateFormat* U_EXPORT2 190 udat_clone(const UDateFormat *fmt, 191 UErrorCode *status) 192 { 193 if(U_FAILURE(*status)) return 0; 194 195 Format *res = ((DateFormat*)fmt)->clone(); 196 197 if(res == 0) { 198 *status = U_MEMORY_ALLOCATION_ERROR; 199 return 0; 200 } 201 202 return (UDateFormat*) res; 203 } 204 205 U_CAPI int32_t U_EXPORT2 206 udat_format( const UDateFormat* format, 207 UDate dateToFormat, 208 UChar* result, 209 int32_t resultLength, 210 UFieldPosition* position, 211 UErrorCode* status) 212 { 213 if(U_FAILURE(*status)) return -1; 214 215 UnicodeString res; 216 if(!(result==NULL && resultLength==0)) { 217 // NULL destination for pure preflighting: empty dummy string 218 // otherwise, alias the destination buffer 219 res.setTo(result, 0, resultLength); 220 } 221 222 FieldPosition fp; 223 224 if(position != 0) 225 fp.setField(position->field); 226 227 ((DateFormat*)format)->format(dateToFormat, res, fp); 228 229 if(position != 0) { 230 position->beginIndex = fp.getBeginIndex(); 231 position->endIndex = fp.getEndIndex(); 232 } 233 234 return res.extract(result, resultLength, *status); 235 } 236 237 U_CAPI UDate U_EXPORT2 238 udat_parse( const UDateFormat* format, 239 const UChar* text, 240 int32_t textLength, 241 int32_t *parsePos, 242 UErrorCode *status) 243 { 244 if(U_FAILURE(*status)) return (UDate)0; 245 246 const UnicodeString src((UBool)(textLength == -1), text, textLength); 247 ParsePosition pp; 248 int32_t stackParsePos = 0; 249 UDate res; 250 251 if(parsePos == NULL) { 252 parsePos = &stackParsePos; 253 } 254 255 pp.setIndex(*parsePos); 256 257 res = ((DateFormat*)format)->parse(src, pp); 258 259 if(pp.getErrorIndex() == -1) 260 *parsePos = pp.getIndex(); 261 else { 262 *parsePos = pp.getErrorIndex(); 263 *status = U_PARSE_ERROR; 264 } 265 266 return res; 267 } 268 269 U_CAPI void U_EXPORT2 270 udat_parseCalendar(const UDateFormat* format, 271 UCalendar* calendar, 272 const UChar* text, 273 int32_t textLength, 274 int32_t *parsePos, 275 UErrorCode *status) 276 { 277 if(U_FAILURE(*status)) return; 278 279 const UnicodeString src((UBool)(textLength == -1), text, textLength); 280 ParsePosition pp; 281 282 if(parsePos != 0) 283 pp.setIndex(*parsePos); 284 285 ((DateFormat*)format)->parse(src, *(Calendar*)calendar, pp); 286 287 if(parsePos != 0) { 288 if(pp.getErrorIndex() == -1) 289 *parsePos = pp.getIndex(); 290 else { 291 *parsePos = pp.getErrorIndex(); 292 *status = U_PARSE_ERROR; 293 } 294 } 295 } 296 297 U_CAPI UBool U_EXPORT2 298 udat_isLenient(const UDateFormat* fmt) 299 { 300 return ((DateFormat*)fmt)->isLenient(); 301 } 302 303 U_CAPI void U_EXPORT2 304 udat_setLenient( UDateFormat* fmt, 305 UBool isLenient) 306 { 307 ((DateFormat*)fmt)->setLenient(isLenient); 308 } 309 310 U_CAPI const UCalendar* U_EXPORT2 311 udat_getCalendar(const UDateFormat* fmt) 312 { 313 return (const UCalendar*) ((DateFormat*)fmt)->getCalendar(); 314 } 315 316 U_CAPI void U_EXPORT2 317 udat_setCalendar(UDateFormat* fmt, 318 const UCalendar* calendarToSet) 319 { 320 ((DateFormat*)fmt)->setCalendar(*((Calendar*)calendarToSet)); 321 } 322 323 U_CAPI const UNumberFormat* U_EXPORT2 324 udat_getNumberFormat(const UDateFormat* fmt) 325 { 326 return (const UNumberFormat*) ((DateFormat*)fmt)->getNumberFormat(); 327 } 328 329 U_CAPI void U_EXPORT2 330 udat_setNumberFormat(UDateFormat* fmt, 331 const UNumberFormat* numberFormatToSet) 332 { 333 ((DateFormat*)fmt)->setNumberFormat(*((NumberFormat*)numberFormatToSet)); 334 } 335 336 U_CAPI const char* U_EXPORT2 337 udat_getAvailable(int32_t index) 338 { 339 return uloc_getAvailable(index); 340 } 341 342 U_CAPI int32_t U_EXPORT2 343 udat_countAvailable() 344 { 345 return uloc_countAvailable(); 346 } 347 348 U_CAPI UDate U_EXPORT2 349 udat_get2DigitYearStart( const UDateFormat *fmt, 350 UErrorCode *status) 351 { 352 verifyIsSimpleDateFormat(fmt, status); 353 if(U_FAILURE(*status)) return (UDate)0; 354 return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status); 355 } 356 357 U_CAPI void U_EXPORT2 358 udat_set2DigitYearStart( UDateFormat *fmt, 359 UDate d, 360 UErrorCode *status) 361 { 362 verifyIsSimpleDateFormat(fmt, status); 363 if(U_FAILURE(*status)) return; 364 ((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status); 365 } 366 367 U_CAPI int32_t U_EXPORT2 368 udat_toPattern( const UDateFormat *fmt, 369 UBool localized, 370 UChar *result, 371 int32_t resultLength, 372 UErrorCode *status) 373 { 374 if(U_FAILURE(*status)) return -1; 375 376 UnicodeString res; 377 if(!(result==NULL && resultLength==0)) { 378 // NULL destination for pure preflighting: empty dummy string 379 // otherwise, alias the destination buffer 380 res.setTo(result, 0, resultLength); 381 } 382 383 const DateFormat *df=reinterpret_cast<const DateFormat *>(fmt); 384 const SimpleDateFormat *sdtfmt=dynamic_cast<const SimpleDateFormat *>(df); 385 const RelativeDateFormat *reldtfmt; 386 if (sdtfmt!=NULL) { 387 if(localized) 388 sdtfmt->toLocalizedPattern(res, *status); 389 else 390 sdtfmt->toPattern(res); 391 } else if (!localized && (reldtfmt=dynamic_cast<const RelativeDateFormat *>(df))!=NULL) { 392 reldtfmt->toPattern(res, *status); 393 } else { 394 *status = U_ILLEGAL_ARGUMENT_ERROR; 395 return -1; 396 } 397 398 return res.extract(result, resultLength, *status); 399 } 400 401 // TODO: should this take an UErrorCode? 402 // A: Yes. Of course. 403 U_CAPI void U_EXPORT2 404 udat_applyPattern( UDateFormat *format, 405 UBool localized, 406 const UChar *pattern, 407 int32_t patternLength) 408 { 409 const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength); 410 UErrorCode status = U_ZERO_ERROR; 411 412 verifyIsSimpleDateFormat(format, &status); 413 if(U_FAILURE(status)) { 414 return; 415 } 416 417 if(localized) 418 ((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status); 419 else 420 ((SimpleDateFormat*)format)->applyPattern(pat); 421 } 422 423 U_CAPI int32_t U_EXPORT2 424 udat_getSymbols(const UDateFormat *fmt, 425 UDateFormatSymbolType type, 426 int32_t index, 427 UChar *result, 428 int32_t resultLength, 429 UErrorCode *status) 430 { 431 const DateFormatSymbols *syms; 432 const SimpleDateFormat* sdtfmt; 433 const RelativeDateFormat* rdtfmt; 434 if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { 435 syms = sdtfmt->getDateFormatSymbols(); 436 } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { 437 syms = rdtfmt->getDateFormatSymbols(); 438 } else { 439 return -1; 440 } 441 int32_t count; 442 const UnicodeString *res = NULL; 443 444 switch(type) { 445 case UDAT_ERAS: 446 res = syms->getEras(count); 447 break; 448 449 case UDAT_ERA_NAMES: 450 res = syms->getEraNames(count); 451 break; 452 453 case UDAT_MONTHS: 454 res = syms->getMonths(count); 455 break; 456 457 case UDAT_SHORT_MONTHS: 458 res = syms->getShortMonths(count); 459 break; 460 461 case UDAT_WEEKDAYS: 462 res = syms->getWeekdays(count); 463 break; 464 465 case UDAT_SHORT_WEEKDAYS: 466 res = syms->getShortWeekdays(count); 467 break; 468 469 case UDAT_AM_PMS: 470 res = syms->getAmPmStrings(count); 471 break; 472 473 case UDAT_LOCALIZED_CHARS: 474 { 475 UnicodeString res1; 476 if(!(result==NULL && resultLength==0)) { 477 // NULL destination for pure preflighting: empty dummy string 478 // otherwise, alias the destination buffer 479 res1.setTo(result, 0, resultLength); 480 } 481 syms->getLocalPatternChars(res1); 482 return res1.extract(result, resultLength, *status); 483 } 484 485 case UDAT_NARROW_MONTHS: 486 res = syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); 487 break; 488 489 case UDAT_NARROW_WEEKDAYS: 490 res = syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); 491 break; 492 493 case UDAT_STANDALONE_MONTHS: 494 res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); 495 break; 496 497 case UDAT_STANDALONE_SHORT_MONTHS: 498 res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); 499 break; 500 501 case UDAT_STANDALONE_NARROW_MONTHS: 502 res = syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); 503 break; 504 505 case UDAT_STANDALONE_WEEKDAYS: 506 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); 507 break; 508 509 case UDAT_STANDALONE_SHORT_WEEKDAYS: 510 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); 511 break; 512 513 case UDAT_STANDALONE_NARROW_WEEKDAYS: 514 res = syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); 515 break; 516 517 case UDAT_QUARTERS: 518 res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); 519 break; 520 521 case UDAT_SHORT_QUARTERS: 522 res = syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); 523 break; 524 525 case UDAT_STANDALONE_QUARTERS: 526 res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); 527 break; 528 529 case UDAT_STANDALONE_SHORT_QUARTERS: 530 res = syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); 531 break; 532 533 } 534 535 if(index < count) { 536 return res[index].extract(result, resultLength, *status); 537 } 538 return 0; 539 } 540 541 // TODO: also needs an errorCode. 542 U_CAPI int32_t U_EXPORT2 543 udat_countSymbols( const UDateFormat *fmt, 544 UDateFormatSymbolType type) 545 { 546 const DateFormatSymbols *syms; 547 const SimpleDateFormat* sdtfmt; 548 const RelativeDateFormat* rdtfmt; 549 if ((sdtfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { 550 syms = sdtfmt->getDateFormatSymbols(); 551 } else if ((rdtfmt = dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))) != NULL) { 552 syms = rdtfmt->getDateFormatSymbols(); 553 } else { 554 return 0; 555 } 556 int32_t count = 0; 557 558 switch(type) { 559 case UDAT_ERAS: 560 syms->getEras(count); 561 break; 562 563 case UDAT_MONTHS: 564 syms->getMonths(count); 565 break; 566 567 case UDAT_SHORT_MONTHS: 568 syms->getShortMonths(count); 569 break; 570 571 case UDAT_WEEKDAYS: 572 syms->getWeekdays(count); 573 break; 574 575 case UDAT_SHORT_WEEKDAYS: 576 syms->getShortWeekdays(count); 577 break; 578 579 case UDAT_AM_PMS: 580 syms->getAmPmStrings(count); 581 break; 582 583 case UDAT_LOCALIZED_CHARS: 584 count = 1; 585 break; 586 587 case UDAT_ERA_NAMES: 588 syms->getEraNames(count); 589 break; 590 591 case UDAT_NARROW_MONTHS: 592 syms->getMonths(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); 593 break; 594 595 case UDAT_NARROW_WEEKDAYS: 596 syms->getWeekdays(count, DateFormatSymbols::FORMAT, DateFormatSymbols::NARROW); 597 break; 598 599 case UDAT_STANDALONE_MONTHS: 600 syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); 601 break; 602 603 case UDAT_STANDALONE_SHORT_MONTHS: 604 syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); 605 break; 606 607 case UDAT_STANDALONE_NARROW_MONTHS: 608 syms->getMonths(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); 609 break; 610 611 case UDAT_STANDALONE_WEEKDAYS: 612 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); 613 break; 614 615 case UDAT_STANDALONE_SHORT_WEEKDAYS: 616 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); 617 break; 618 619 case UDAT_STANDALONE_NARROW_WEEKDAYS: 620 syms->getWeekdays(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::NARROW); 621 break; 622 623 case UDAT_QUARTERS: 624 syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::WIDE); 625 break; 626 627 case UDAT_SHORT_QUARTERS: 628 syms->getQuarters(count, DateFormatSymbols::FORMAT, DateFormatSymbols::ABBREVIATED); 629 break; 630 631 case UDAT_STANDALONE_QUARTERS: 632 syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::WIDE); 633 break; 634 635 case UDAT_STANDALONE_SHORT_QUARTERS: 636 syms->getQuarters(count, DateFormatSymbols::STANDALONE, DateFormatSymbols::ABBREVIATED); 637 break; 638 639 } 640 641 return count; 642 } 643 644 U_NAMESPACE_BEGIN 645 646 /* 647 * This DateFormatSymbolsSingleSetter class is a friend of DateFormatSymbols 648 * solely for the purpose of avoiding to clone the array of strings 649 * just to modify one of them and then setting all of them back. 650 * For example, the old code looked like this: 651 * case UDAT_MONTHS: 652 * res = syms->getMonths(count); 653 * array = new UnicodeString[count]; 654 * if(array == 0) { 655 * *status = U_MEMORY_ALLOCATION_ERROR; 656 * return; 657 * } 658 * uprv_arrayCopy(res, array, count); 659 * if(index < count) 660 * array[index] = val; 661 * syms->setMonths(array, count); 662 * break; 663 * 664 * Even worse, the old code actually cloned the entire DateFormatSymbols object, 665 * cloned one value array, changed one value, and then made the SimpleDateFormat 666 * replace its DateFormatSymbols object with the new one. 667 * 668 * markus 2002-oct-14 669 */ 670 class DateFormatSymbolsSingleSetter /* not : public UObject because all methods are static */ { 671 public: 672 static void 673 setSymbol(UnicodeString *array, int32_t count, int32_t index, 674 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 675 { 676 if(array!=NULL) { 677 if(index>=count) { 678 errorCode=U_INDEX_OUTOFBOUNDS_ERROR; 679 } else if(value==NULL) { 680 errorCode=U_ILLEGAL_ARGUMENT_ERROR; 681 } else { 682 array[index].setTo(value, valueLength); 683 } 684 } 685 } 686 687 static void 688 setEra(DateFormatSymbols *syms, int32_t index, 689 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 690 { 691 setSymbol(syms->fEras, syms->fErasCount, index, value, valueLength, errorCode); 692 } 693 694 static void 695 setEraName(DateFormatSymbols *syms, int32_t index, 696 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 697 { 698 setSymbol(syms->fEraNames, syms->fEraNamesCount, index, value, valueLength, errorCode); 699 } 700 701 static void 702 setMonth(DateFormatSymbols *syms, int32_t index, 703 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 704 { 705 setSymbol(syms->fMonths, syms->fMonthsCount, index, value, valueLength, errorCode); 706 } 707 708 static void 709 setShortMonth(DateFormatSymbols *syms, int32_t index, 710 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 711 { 712 setSymbol(syms->fShortMonths, syms->fShortMonthsCount, index, value, valueLength, errorCode); 713 } 714 715 static void 716 setNarrowMonth(DateFormatSymbols *syms, int32_t index, 717 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 718 { 719 setSymbol(syms->fNarrowMonths, syms->fNarrowMonthsCount, index, value, valueLength, errorCode); 720 } 721 722 static void 723 setStandaloneMonth(DateFormatSymbols *syms, int32_t index, 724 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 725 { 726 setSymbol(syms->fStandaloneMonths, syms->fStandaloneMonthsCount, index, value, valueLength, errorCode); 727 } 728 729 static void 730 setStandaloneShortMonth(DateFormatSymbols *syms, int32_t index, 731 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 732 { 733 setSymbol(syms->fStandaloneShortMonths, syms->fStandaloneShortMonthsCount, index, value, valueLength, errorCode); 734 } 735 736 static void 737 setStandaloneNarrowMonth(DateFormatSymbols *syms, int32_t index, 738 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 739 { 740 setSymbol(syms->fStandaloneNarrowMonths, syms->fStandaloneNarrowMonthsCount, index, value, valueLength, errorCode); 741 } 742 743 static void 744 setWeekday(DateFormatSymbols *syms, int32_t index, 745 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 746 { 747 setSymbol(syms->fWeekdays, syms->fWeekdaysCount, index, value, valueLength, errorCode); 748 } 749 750 static void 751 setShortWeekday(DateFormatSymbols *syms, int32_t index, 752 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 753 { 754 setSymbol(syms->fShortWeekdays, syms->fShortWeekdaysCount, index, value, valueLength, errorCode); 755 } 756 757 static void 758 setNarrowWeekday(DateFormatSymbols *syms, int32_t index, 759 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 760 { 761 setSymbol(syms->fNarrowWeekdays, syms->fNarrowWeekdaysCount, index, value, valueLength, errorCode); 762 } 763 764 static void 765 setStandaloneWeekday(DateFormatSymbols *syms, int32_t index, 766 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 767 { 768 setSymbol(syms->fStandaloneWeekdays, syms->fStandaloneWeekdaysCount, index, value, valueLength, errorCode); 769 } 770 771 static void 772 setStandaloneShortWeekday(DateFormatSymbols *syms, int32_t index, 773 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 774 { 775 setSymbol(syms->fStandaloneShortWeekdays, syms->fStandaloneShortWeekdaysCount, index, value, valueLength, errorCode); 776 } 777 778 static void 779 setStandaloneNarrowWeekday(DateFormatSymbols *syms, int32_t index, 780 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 781 { 782 setSymbol(syms->fStandaloneNarrowWeekdays, syms->fStandaloneNarrowWeekdaysCount, index, value, valueLength, errorCode); 783 } 784 785 static void 786 setQuarter(DateFormatSymbols *syms, int32_t index, 787 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 788 { 789 setSymbol(syms->fQuarters, syms->fQuartersCount, index, value, valueLength, errorCode); 790 } 791 792 static void 793 setShortQuarter(DateFormatSymbols *syms, int32_t index, 794 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 795 { 796 setSymbol(syms->fShortQuarters, syms->fShortQuartersCount, index, value, valueLength, errorCode); 797 } 798 799 static void 800 setStandaloneQuarter(DateFormatSymbols *syms, int32_t index, 801 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 802 { 803 setSymbol(syms->fStandaloneQuarters, syms->fStandaloneQuartersCount, index, value, valueLength, errorCode); 804 } 805 806 static void 807 setStandaloneShortQuarter(DateFormatSymbols *syms, int32_t index, 808 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 809 { 810 setSymbol(syms->fStandaloneShortQuarters, syms->fStandaloneShortQuartersCount, index, value, valueLength, errorCode); 811 } 812 813 static void 814 setAmPm(DateFormatSymbols *syms, int32_t index, 815 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 816 { 817 setSymbol(syms->fAmPms, syms->fAmPmsCount, index, value, valueLength, errorCode); 818 } 819 820 static void 821 setLocalPatternChars(DateFormatSymbols *syms, 822 const UChar *value, int32_t valueLength, UErrorCode &errorCode) 823 { 824 setSymbol(&syms->fLocalPatternChars, 1, 0, value, valueLength, errorCode); 825 } 826 }; 827 828 U_NAMESPACE_END 829 830 U_CAPI void U_EXPORT2 831 udat_setSymbols( UDateFormat *format, 832 UDateFormatSymbolType type, 833 int32_t index, 834 UChar *value, 835 int32_t valueLength, 836 UErrorCode *status) 837 { 838 verifyIsSimpleDateFormat(format, status); 839 if(U_FAILURE(*status)) return; 840 841 DateFormatSymbols *syms = (DateFormatSymbols *)((SimpleDateFormat *)format)->getDateFormatSymbols(); 842 843 switch(type) { 844 case UDAT_ERAS: 845 DateFormatSymbolsSingleSetter::setEra(syms, index, value, valueLength, *status); 846 break; 847 848 case UDAT_ERA_NAMES: 849 DateFormatSymbolsSingleSetter::setEraName(syms, index, value, valueLength, *status); 850 break; 851 852 case UDAT_MONTHS: 853 DateFormatSymbolsSingleSetter::setMonth(syms, index, value, valueLength, *status); 854 break; 855 856 case UDAT_SHORT_MONTHS: 857 DateFormatSymbolsSingleSetter::setShortMonth(syms, index, value, valueLength, *status); 858 break; 859 860 case UDAT_NARROW_MONTHS: 861 DateFormatSymbolsSingleSetter::setNarrowMonth(syms, index, value, valueLength, *status); 862 break; 863 864 case UDAT_STANDALONE_MONTHS: 865 DateFormatSymbolsSingleSetter::setStandaloneMonth(syms, index, value, valueLength, *status); 866 break; 867 868 case UDAT_STANDALONE_SHORT_MONTHS: 869 DateFormatSymbolsSingleSetter::setStandaloneShortMonth(syms, index, value, valueLength, *status); 870 break; 871 872 case UDAT_STANDALONE_NARROW_MONTHS: 873 DateFormatSymbolsSingleSetter::setStandaloneNarrowMonth(syms, index, value, valueLength, *status); 874 break; 875 876 case UDAT_WEEKDAYS: 877 DateFormatSymbolsSingleSetter::setWeekday(syms, index, value, valueLength, *status); 878 break; 879 880 case UDAT_SHORT_WEEKDAYS: 881 DateFormatSymbolsSingleSetter::setShortWeekday(syms, index, value, valueLength, *status); 882 break; 883 884 case UDAT_NARROW_WEEKDAYS: 885 DateFormatSymbolsSingleSetter::setNarrowWeekday(syms, index, value, valueLength, *status); 886 break; 887 888 case UDAT_STANDALONE_WEEKDAYS: 889 DateFormatSymbolsSingleSetter::setStandaloneWeekday(syms, index, value, valueLength, *status); 890 break; 891 892 case UDAT_STANDALONE_SHORT_WEEKDAYS: 893 DateFormatSymbolsSingleSetter::setStandaloneShortWeekday(syms, index, value, valueLength, *status); 894 break; 895 896 case UDAT_STANDALONE_NARROW_WEEKDAYS: 897 DateFormatSymbolsSingleSetter::setStandaloneNarrowWeekday(syms, index, value, valueLength, *status); 898 break; 899 900 case UDAT_QUARTERS: 901 DateFormatSymbolsSingleSetter::setQuarter(syms, index, value, valueLength, *status); 902 break; 903 904 case UDAT_SHORT_QUARTERS: 905 DateFormatSymbolsSingleSetter::setShortQuarter(syms, index, value, valueLength, *status); 906 break; 907 908 case UDAT_STANDALONE_QUARTERS: 909 DateFormatSymbolsSingleSetter::setStandaloneQuarter(syms, index, value, valueLength, *status); 910 break; 911 912 case UDAT_STANDALONE_SHORT_QUARTERS: 913 DateFormatSymbolsSingleSetter::setStandaloneShortQuarter(syms, index, value, valueLength, *status); 914 break; 915 916 case UDAT_AM_PMS: 917 DateFormatSymbolsSingleSetter::setAmPm(syms, index, value, valueLength, *status); 918 break; 919 920 case UDAT_LOCALIZED_CHARS: 921 DateFormatSymbolsSingleSetter::setLocalPatternChars(syms, value, valueLength, *status); 922 break; 923 924 default: 925 *status = U_UNSUPPORTED_ERROR; 926 break; 927 928 } 929 } 930 931 U_CAPI const char* U_EXPORT2 932 udat_getLocaleByType(const UDateFormat *fmt, 933 ULocDataLocaleType type, 934 UErrorCode* status) 935 { 936 if (fmt == NULL) { 937 if (U_SUCCESS(*status)) { 938 *status = U_ILLEGAL_ARGUMENT_ERROR; 939 } 940 return NULL; 941 } 942 return ((Format*)fmt)->getLocaleID(type, *status); 943 } 944 945 946 U_CAPI void U_EXPORT2 947 udat_setContext(UDateFormat* fmt, UDisplayContext value, UErrorCode* status) 948 { 949 verifyIsSimpleDateFormat(fmt, status); 950 if (U_FAILURE(*status)) { 951 return; 952 } 953 ((SimpleDateFormat*)fmt)->setContext(value, *status); 954 } 955 956 U_CAPI UDisplayContext U_EXPORT2 957 udat_getContext(UDateFormat* fmt, UDisplayContextType type, UErrorCode* status) 958 { 959 verifyIsSimpleDateFormat(fmt, status); 960 if (U_FAILURE(*status)) { 961 return (UDisplayContext)0; 962 } 963 return ((SimpleDateFormat*)fmt)->getContext(type, *status); 964 } 965 966 967 /** 968 * Verify that fmt is a RelativeDateFormat. Invalid error if not. 969 * @param fmt the UDateFormat, definitely a DateFormat, maybe something else 970 * @param status error code, will be set to failure if there is a familure or the fmt is NULL. 971 */ 972 static void verifyIsRelativeDateFormat(const UDateFormat* fmt, UErrorCode *status) { 973 if(U_SUCCESS(*status) && 974 dynamic_cast<const RelativeDateFormat*>(reinterpret_cast<const DateFormat*>(fmt))==NULL) { 975 *status = U_ILLEGAL_ARGUMENT_ERROR; 976 } 977 } 978 979 980 U_CAPI int32_t U_EXPORT2 981 udat_toPatternRelativeDate(const UDateFormat *fmt, 982 UChar *result, 983 int32_t resultLength, 984 UErrorCode *status) 985 { 986 verifyIsRelativeDateFormat(fmt, status); 987 if(U_FAILURE(*status)) return -1; 988 989 UnicodeString datePattern; 990 if(!(result==NULL && resultLength==0)) { 991 // NULL destination for pure preflighting: empty dummy string 992 // otherwise, alias the destination buffer 993 datePattern.setTo(result, 0, resultLength); 994 } 995 ((RelativeDateFormat*)fmt)->toPatternDate(datePattern, *status); 996 return datePattern.extract(result, resultLength, *status); 997 } 998 999 U_CAPI int32_t U_EXPORT2 1000 udat_toPatternRelativeTime(const UDateFormat *fmt, 1001 UChar *result, 1002 int32_t resultLength, 1003 UErrorCode *status) 1004 { 1005 verifyIsRelativeDateFormat(fmt, status); 1006 if(U_FAILURE(*status)) return -1; 1007 1008 UnicodeString timePattern; 1009 if(!(result==NULL && resultLength==0)) { 1010 // NULL destination for pure preflighting: empty dummy string 1011 // otherwise, alias the destination buffer 1012 timePattern.setTo(result, 0, resultLength); 1013 } 1014 ((RelativeDateFormat*)fmt)->toPatternTime(timePattern, *status); 1015 return timePattern.extract(result, resultLength, *status); 1016 } 1017 1018 U_CAPI void U_EXPORT2 1019 udat_applyPatternRelative(UDateFormat *format, 1020 const UChar *datePattern, 1021 int32_t datePatternLength, 1022 const UChar *timePattern, 1023 int32_t timePatternLength, 1024 UErrorCode *status) 1025 { 1026 verifyIsRelativeDateFormat(format, status); 1027 if(U_FAILURE(*status)) return; 1028 const UnicodeString datePat((UBool)(datePatternLength == -1), datePattern, datePatternLength); 1029 const UnicodeString timePat((UBool)(timePatternLength == -1), timePattern, timePatternLength); 1030 ((RelativeDateFormat*)format)->applyPatterns(datePat, timePat, *status); 1031 } 1032 1033 #endif /* #if !UCONFIG_NO_FORMATTING */ 1034