1 /* 2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 ** Distributed under the terms of the OpenBeOS License. 4 */ 5 6 7 #include <AutoDeleter.h> 8 #include <Autolock.h> 9 #include <CalendarView.h> 10 #include <Catalog.h> 11 #include <Locale.h> 12 #include <LocaleRoster.h> 13 #include <MutableLocaleRoster.h> 14 #include <TimeZone.h> 15 16 #include <unicode/datefmt.h> 17 #include <unicode/dcfmtsym.h> 18 #include <unicode/decimfmt.h> 19 #include <unicode/dtfmtsym.h> 20 #include <unicode/numfmt.h> 21 #include <unicode/smpdtfmt.h> 22 #include <unicode/ustring.h> 23 #include <ICUWrapper.h> 24 25 #include <vector> 26 27 28 #define ICU_VERSION icu_44 29 30 31 using BPrivate::ObjectDeleter; 32 using BPrivate::B_WEEK_START_MONDAY; 33 using BPrivate::B_WEEK_START_SUNDAY; 34 35 36 static DateFormat* CreateDateFormat(bool longFormat, const Locale& locale, 37 const BString& format); 38 static DateFormat* CreateTimeFormat(bool longFormat, const Locale& locale, 39 const BString& format); 40 41 42 BLocale::BLocale(const char* languageAndCountryCode) 43 : 44 fCountry(languageAndCountryCode), 45 fLanguage(languageAndCountryCode), 46 fICULocale(new ICU_VERSION::Locale(languageAndCountryCode)) 47 { 48 } 49 50 51 BLocale::BLocale(const BLocale& other) 52 : 53 fCountry(other.fCountry), 54 fLanguage(other.fLanguage), 55 fICULocale(new ICU_VERSION::Locale(*other.fICULocale)), 56 fLongDateFormat(other.fLongDateFormat), 57 fShortDateFormat(other.fShortDateFormat), 58 fLongTimeFormat(other.fLongTimeFormat), 59 fShortTimeFormat(other.fShortTimeFormat) 60 { 61 } 62 63 64 BLocale& 65 BLocale::operator=(const BLocale& other) 66 { 67 if (this == &other) 68 return *this; 69 70 *fICULocale = *other.fICULocale; 71 72 fLongDateFormat = other.fLongDateFormat; 73 fShortDateFormat = other.fShortDateFormat; 74 fLongTimeFormat = other.fLongTimeFormat; 75 fShortTimeFormat = other.fShortTimeFormat; 76 77 fCountry = other.fCountry; 78 fLanguage = other.fLanguage; 79 80 return *this; 81 } 82 83 84 BLocale::~BLocale() 85 { 86 delete fICULocale; 87 } 88 89 90 status_t 91 BLocale::GetCollator(BCollator* collator) const 92 { 93 if (!collator) 94 return B_BAD_VALUE; 95 96 BAutolock lock(fLock); 97 if (!lock.IsLocked()) 98 return B_ERROR; 99 100 *collator = fCollator; 101 102 return B_OK; 103 } 104 105 106 status_t 107 BLocale::GetLanguage(BLanguage* language) const 108 { 109 if (!language) 110 return B_BAD_VALUE; 111 112 BAutolock lock(fLock); 113 if (!lock.IsLocked()) 114 return B_ERROR; 115 116 *language = fLanguage; 117 118 return B_OK; 119 } 120 121 122 status_t 123 BLocale::GetCountry(BCountry* country) const 124 { 125 if (!country) 126 return B_BAD_VALUE; 127 128 BAutolock lock(fLock); 129 if (!lock.IsLocked()) 130 return B_ERROR; 131 132 *country = fCountry; 133 134 return B_OK; 135 } 136 137 138 const char * 139 BLocale::GetString(uint32 id) const 140 { 141 // Note: this code assumes a certain order of the string bases 142 143 if (id >= B_OTHER_STRINGS_BASE) { 144 if (id == B_CODESET) 145 return "UTF-8"; 146 147 return ""; 148 } 149 return fLanguage.GetString(id); 150 } 151 152 153 void 154 BLocale::SetCountry(const BCountry& newCountry) 155 { 156 fCountry = newCountry; 157 } 158 159 160 void 161 BLocale::SetCollator(const BCollator& newCollator) 162 { 163 fCollator = newCollator; 164 } 165 166 167 void 168 BLocale::SetLanguage(const char* languageCode) 169 { 170 fLanguage.SetTo(languageCode); 171 } 172 173 174 const char* 175 BLocale::Code() const 176 { 177 return fICULocale->getName(); 178 } 179 180 181 bool 182 BLocale::GetName(BString& name) const 183 { 184 UnicodeString uString; 185 fICULocale->getDisplayName(uString); 186 BStringByteSink stringConverter(&name); 187 uString.toUTF8(stringConverter); 188 return true; 189 } 190 191 // #pragma mark - Date 192 193 194 status_t 195 BLocale::FormatDate(char* string, size_t maxSize, time_t time, 196 bool longFormat) const 197 { 198 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 199 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 200 if (dateFormatter.Get() == NULL) 201 return B_NO_MEMORY; 202 203 UnicodeString ICUString; 204 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 205 206 CheckedArrayByteSink stringConverter(string, maxSize); 207 208 ICUString.toUTF8(stringConverter); 209 210 if (stringConverter.Overflowed()) 211 return B_BAD_VALUE; 212 213 return B_OK; 214 } 215 216 217 status_t 218 BLocale::FormatDate(BString *string, time_t time, bool longFormat, 219 const BTimeZone* timeZone) const 220 { 221 string->Truncate(0); 222 // We make the string empty, this way even in cases where ICU fail we at 223 // least return something sane 224 Locale locale(fLanguage.Code()); 225 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 226 locale, longFormat ? fLongDateFormat : fShortDateFormat); 227 if (dateFormatter.Get() == NULL) 228 return B_NO_MEMORY; 229 230 if (timeZone != NULL) { 231 ObjectDeleter<TimeZone> icuTimeZone 232 = TimeZone::createTimeZone(timeZone->ID().String()); 233 if (icuTimeZone.Get() == NULL) 234 return B_NO_MEMORY; 235 dateFormatter->setTimeZone(*icuTimeZone.Get()); 236 } 237 238 UnicodeString ICUString; 239 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 240 241 BStringByteSink stringConverter(string); 242 ICUString.toUTF8(stringConverter); 243 244 return B_OK; 245 } 246 247 248 status_t 249 BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, 250 time_t time, bool longFormat) const 251 { 252 string->Truncate(0); 253 254 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 255 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 256 if (dateFormatter.Get() == NULL) 257 return B_NO_MEMORY; 258 259 fieldPositions = NULL; 260 UErrorCode error = U_ZERO_ERROR; 261 ICU_VERSION::FieldPositionIterator positionIterator; 262 UnicodeString ICUString; 263 ICUString = dateFormatter->format((UDate)time * 1000, ICUString, 264 &positionIterator, error); 265 266 if (error != U_ZERO_ERROR) 267 return B_ERROR; 268 269 ICU_VERSION::FieldPosition field; 270 std::vector<int> fieldPosStorage; 271 fieldCount = 0; 272 while (positionIterator.next(field)) { 273 fieldPosStorage.push_back(field.getBeginIndex()); 274 fieldPosStorage.push_back(field.getEndIndex()); 275 fieldCount += 2; 276 } 277 278 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 279 280 for (int i = 0 ; i < fieldCount ; i++ ) 281 fieldPositions[i] = fieldPosStorage[i]; 282 283 BStringByteSink stringConverter(string); 284 285 ICUString.toUTF8(stringConverter); 286 287 return B_OK; 288 } 289 290 291 status_t 292 BLocale::GetDateFormat(BString& format, bool longFormat) const 293 { 294 if (longFormat && fLongDateFormat.Length() > 0) 295 format = fLongDateFormat; 296 else if (!longFormat && fShortDateFormat.Length() > 0) 297 format = fShortDateFormat; 298 else { 299 format.Truncate(0); 300 301 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 302 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 303 if (dateFormatter.Get() == NULL) 304 return B_NO_MEMORY; 305 306 SimpleDateFormat* dateFormatterImpl 307 = static_cast<SimpleDateFormat*>(dateFormatter.Get()); 308 309 UnicodeString ICUString; 310 ICUString = dateFormatterImpl->toPattern(ICUString); 311 312 BStringByteSink stringConverter(&format); 313 314 ICUString.toUTF8(stringConverter); 315 } 316 317 return B_OK; 318 } 319 320 321 status_t 322 BLocale::SetDateFormat(const char* formatString, bool longFormat) 323 { 324 if (longFormat) 325 fLongDateFormat = formatString; 326 else 327 fShortDateFormat = formatString; 328 329 return B_OK; 330 } 331 332 333 status_t 334 BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, 335 bool longFormat) const 336 { 337 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 338 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 339 if (dateFormatter.Get() == NULL) 340 return B_NO_MEMORY; 341 342 fields = NULL; 343 UErrorCode error = U_ZERO_ERROR; 344 ICU_VERSION::FieldPositionIterator positionIterator; 345 UnicodeString ICUString; 346 time_t now; 347 ICUString = dateFormatter->format((UDate)time(&now) * 1000, ICUString, 348 &positionIterator, error); 349 350 if (U_FAILURE(error)) 351 return B_ERROR; 352 353 ICU_VERSION::FieldPosition field; 354 std::vector<int> fieldPosStorage; 355 fieldCount = 0; 356 while (positionIterator.next(field)) { 357 fieldPosStorage.push_back(field.getField()); 358 fieldCount ++; 359 } 360 361 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); 362 363 for (int i = 0 ; i < fieldCount ; i++ ) { 364 switch (fieldPosStorage[i]) { 365 case UDAT_YEAR_FIELD: 366 fields[i] = B_DATE_ELEMENT_YEAR; 367 break; 368 case UDAT_MONTH_FIELD: 369 fields[i] = B_DATE_ELEMENT_MONTH; 370 break; 371 case UDAT_DATE_FIELD: 372 fields[i] = B_DATE_ELEMENT_DAY; 373 break; 374 default: 375 fields[i] = B_DATE_ELEMENT_INVALID; 376 break; 377 } 378 } 379 380 return B_OK; 381 } 382 383 384 int 385 BLocale::StartOfWeek() const 386 { 387 UErrorCode err = U_ZERO_ERROR; 388 Calendar* c = Calendar::createInstance(*fICULocale, err); 389 390 if (err == U_ZERO_ERROR && c->getFirstDayOfWeek(err) == UCAL_SUNDAY) { 391 delete c; 392 return B_WEEK_START_SUNDAY; 393 } else { 394 delete c; 395 // Might be another day, but BeAPI will not handle it 396 return B_WEEK_START_MONDAY; 397 } 398 } 399 400 401 status_t 402 BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, 403 bool longFormat) const 404 { 405 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 406 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 407 if (dateFormatter.Get() == NULL) 408 return B_NO_MEMORY; 409 410 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 411 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 412 if (timeFormatter.Get() == NULL) 413 return B_NO_MEMORY; 414 415 UnicodeString ICUString; 416 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 417 418 ICUString.append(UnicodeString::fromUTF8(", ")); 419 420 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 421 422 CheckedArrayByteSink stringConverter(target, maxSize); 423 ICUString.toUTF8(stringConverter); 424 425 if (stringConverter.Overflowed()) 426 return B_BAD_VALUE; 427 428 return B_OK; 429 } 430 431 432 status_t 433 BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, 434 const BTimeZone* timeZone) const 435 { 436 ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, 437 *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); 438 if (dateFormatter.Get() == NULL) 439 return B_NO_MEMORY; 440 441 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 442 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 443 if (timeFormatter.Get() == NULL) 444 return B_NO_MEMORY; 445 446 if (timeZone != NULL) { 447 ObjectDeleter<TimeZone> icuTimeZone 448 = TimeZone::createTimeZone(timeZone->ID().String()); 449 if (icuTimeZone.Get() == NULL) 450 return B_NO_MEMORY; 451 timeFormatter->setTimeZone(*icuTimeZone.Get()); 452 } 453 454 UnicodeString ICUString; 455 ICUString = dateFormatter->format((UDate)time * 1000, ICUString); 456 457 ICUString.append(UnicodeString::fromUTF8(", ")); 458 459 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 460 461 BStringByteSink stringConverter(target); 462 ICUString.toUTF8(stringConverter); 463 464 return B_OK; 465 } 466 467 468 // #pragma mark - Time 469 470 471 status_t 472 BLocale::FormatTime(char* string, size_t maxSize, time_t time, 473 bool longFormat) const 474 { 475 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 476 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 477 if (timeFormatter.Get() == NULL) 478 return B_NO_MEMORY; 479 480 UnicodeString ICUString; 481 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 482 483 CheckedArrayByteSink stringConverter(string, maxSize); 484 485 ICUString.toUTF8(stringConverter); 486 487 if (stringConverter.Overflowed()) 488 return B_BAD_VALUE; 489 490 return B_OK; 491 } 492 493 494 status_t 495 BLocale::FormatTime(BString* string, time_t time, bool longFormat, 496 const BTimeZone* timeZone) const 497 { 498 string->Truncate(0); 499 500 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 501 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 502 if (timeFormatter.Get() == NULL) 503 return B_NO_MEMORY; 504 505 if (timeZone != NULL) { 506 ObjectDeleter<TimeZone> icuTimeZone 507 = TimeZone::createTimeZone(timeZone->ID().String()); 508 if (icuTimeZone.Get() == NULL) 509 return B_NO_MEMORY; 510 timeFormatter->setTimeZone(*icuTimeZone.Get()); 511 } 512 513 UnicodeString ICUString; 514 ICUString = timeFormatter->format((UDate)time * 1000, ICUString); 515 516 BStringByteSink stringConverter(string); 517 518 ICUString.toUTF8(stringConverter); 519 520 return B_OK; 521 } 522 523 524 status_t 525 BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, 526 time_t time, bool longFormat) const 527 { 528 string->Truncate(0); 529 530 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 531 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 532 if (timeFormatter.Get() == NULL) 533 return B_NO_MEMORY; 534 535 fieldPositions = NULL; 536 UErrorCode error = U_ZERO_ERROR; 537 ICU_VERSION::FieldPositionIterator positionIterator; 538 UnicodeString ICUString; 539 ICUString = timeFormatter->format((UDate)time * 1000, ICUString, 540 &positionIterator, error); 541 542 if (error != U_ZERO_ERROR) 543 return B_ERROR; 544 545 ICU_VERSION::FieldPosition field; 546 std::vector<int> fieldPosStorage; 547 fieldCount = 0; 548 while (positionIterator.next(field)) { 549 fieldPosStorage.push_back(field.getBeginIndex()); 550 fieldPosStorage.push_back(field.getEndIndex()); 551 fieldCount += 2; 552 } 553 554 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 555 556 for (int i = 0 ; i < fieldCount ; i++ ) 557 fieldPositions[i] = fieldPosStorage[i]; 558 559 BStringByteSink stringConverter(string); 560 561 ICUString.toUTF8(stringConverter); 562 563 return B_OK; 564 } 565 566 567 status_t 568 BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, 569 bool longFormat) const 570 { 571 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 572 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 573 if (timeFormatter.Get() == NULL) 574 return B_NO_MEMORY; 575 576 fields = NULL; 577 UErrorCode error = U_ZERO_ERROR; 578 ICU_VERSION::FieldPositionIterator positionIterator; 579 UnicodeString ICUString; 580 time_t now; 581 ICUString = timeFormatter->format((UDate)time(&now) * 1000, ICUString, 582 &positionIterator, error); 583 584 if (error != U_ZERO_ERROR) 585 return B_ERROR; 586 587 ICU_VERSION::FieldPosition field; 588 std::vector<int> fieldPosStorage; 589 fieldCount = 0; 590 while (positionIterator.next(field)) { 591 fieldPosStorage.push_back(field.getField()); 592 fieldCount ++; 593 } 594 595 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); 596 597 for (int i = 0 ; i < fieldCount ; i++ ) { 598 switch (fieldPosStorage[i]) { 599 case UDAT_HOUR_OF_DAY1_FIELD: 600 case UDAT_HOUR_OF_DAY0_FIELD: 601 case UDAT_HOUR1_FIELD: 602 case UDAT_HOUR0_FIELD: 603 fields[i] = B_DATE_ELEMENT_HOUR; 604 break; 605 case UDAT_MINUTE_FIELD: 606 fields[i] = B_DATE_ELEMENT_MINUTE; 607 break; 608 case UDAT_SECOND_FIELD: 609 fields[i] = B_DATE_ELEMENT_SECOND; 610 break; 611 case UDAT_AM_PM_FIELD: 612 fields[i] = B_DATE_ELEMENT_AM_PM; 613 break; 614 default: 615 fields[i] = B_DATE_ELEMENT_INVALID; 616 break; 617 } 618 } 619 620 return B_OK; 621 } 622 623 624 status_t 625 BLocale::SetTimeFormat(const char* formatString, bool longFormat) 626 { 627 if (longFormat) 628 fLongTimeFormat = formatString; 629 else 630 fShortTimeFormat = formatString; 631 632 return B_OK; 633 } 634 635 636 status_t 637 BLocale::GetTimeFormat(BString& format, bool longFormat) const 638 { 639 if (longFormat && fLongTimeFormat.Length() > 0) 640 format = fLongTimeFormat; 641 else if (!longFormat && fShortTimeFormat.Length() > 0) 642 format = fShortTimeFormat; 643 else { 644 format.Truncate(0); 645 646 ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, 647 *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); 648 if (timeFormatter.Get() == NULL) 649 return B_NO_MEMORY; 650 651 SimpleDateFormat* timeFormatterImpl 652 = static_cast<SimpleDateFormat*>(timeFormatter.Get()); 653 654 UnicodeString ICUString; 655 ICUString = timeFormatterImpl->toPattern(ICUString); 656 657 BStringByteSink stringConverter(&format); 658 ICUString.toUTF8(stringConverter); 659 } 660 661 return B_OK; 662 } 663 664 665 // #pragma mark - Numbers 666 667 668 status_t 669 BLocale::FormatNumber(char* string, size_t maxSize, double value) const 670 { 671 BString fullString; 672 status_t status = FormatNumber(&fullString, value); 673 if (status == B_OK) 674 strlcpy(string, fullString.String(), maxSize); 675 676 return status; 677 } 678 679 680 status_t 681 BLocale::FormatNumber(BString* string, double value) const 682 { 683 UErrorCode err = U_ZERO_ERROR; 684 ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance( 685 *fICULocale, NumberFormat::kNumberStyle, err); 686 687 if (numberFormatter.Get() == NULL) 688 return B_NO_MEMORY; 689 if (U_FAILURE(err)) 690 return B_ERROR; 691 692 UnicodeString ICUString; 693 ICUString = numberFormatter->format(value, ICUString); 694 695 string->Truncate(0); 696 BStringByteSink stringConverter(string); 697 ICUString.toUTF8(stringConverter); 698 699 return B_OK; 700 } 701 702 703 status_t 704 BLocale::FormatNumber(char* string, size_t maxSize, int32 value) const 705 { 706 BString fullString; 707 status_t status = FormatNumber(&fullString, value); 708 if (status == B_OK) 709 strlcpy(string, fullString.String(), maxSize); 710 711 return status; 712 } 713 714 715 status_t 716 BLocale::FormatNumber(BString* string, int32 value) const 717 { 718 UErrorCode err = U_ZERO_ERROR; 719 ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance( 720 *fICULocale, NumberFormat::kNumberStyle, err); 721 722 if (numberFormatter.Get() == NULL) 723 return B_NO_MEMORY; 724 if (U_FAILURE(err)) 725 return B_ERROR; 726 727 UnicodeString ICUString; 728 ICUString = numberFormatter->format((int32_t)value, ICUString); 729 730 string->Truncate(0); 731 BStringByteSink stringConverter(string); 732 ICUString.toUTF8(stringConverter); 733 734 return B_OK; 735 } 736 737 738 ssize_t 739 BLocale::FormatMonetary(char* string, size_t maxSize, double value) const 740 { 741 BString fullString; 742 ssize_t written = FormatMonetary(&fullString, value); 743 if (written < 0) 744 return written; 745 746 return strlcpy(string, fullString.String(), maxSize); 747 } 748 749 750 ssize_t 751 BLocale::FormatMonetary(BString* string, double value) const 752 { 753 if (string == NULL) 754 return B_BAD_VALUE; 755 756 UErrorCode err; 757 ObjectDeleter<NumberFormat> numberFormatter 758 = NumberFormat::createCurrencyInstance(*fICULocale, err); 759 760 if (numberFormatter.Get() == NULL) 761 return B_NO_MEMORY; 762 if (U_FAILURE(err)) 763 return B_ERROR; 764 765 UnicodeString ICUString; 766 ICUString = numberFormatter->format(value, ICUString); 767 768 string->Truncate(0); 769 BStringByteSink stringConverter(string); 770 ICUString.toUTF8(stringConverter); 771 772 return string->Length(); 773 } 774 775 776 status_t 777 BLocale::FormatMonetary(BString* string, int*& fieldPositions, 778 BNumberElement*& fieldTypes, int& fieldCount, double value) const 779 { 780 UErrorCode err = U_ZERO_ERROR; 781 ObjectDeleter<NumberFormat> numberFormatter 782 = NumberFormat::createCurrencyInstance(*fICULocale, err); 783 if (U_FAILURE(err)) 784 return B_NO_MEMORY; 785 786 string->Truncate(0); 787 788 fieldPositions = NULL; 789 fieldTypes = NULL; 790 ICU_VERSION::FieldPositionIterator positionIterator; 791 UnicodeString ICUString; 792 ICUString = numberFormatter->format(value, ICUString, &positionIterator, 793 err); 794 795 if (err != U_ZERO_ERROR) 796 return B_ERROR; 797 798 ICU_VERSION::FieldPosition field; 799 std::vector<int> fieldPosStorage; 800 std::vector<int> fieldTypeStorage; 801 fieldCount = 0; 802 while (positionIterator.next(field)) { 803 fieldTypeStorage.push_back(field.getField()); 804 fieldPosStorage.push_back(field.getBeginIndex() | (field.getEndIndex() << 16)); 805 fieldCount ++; 806 807 } 808 809 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 810 fieldTypes = (BNumberElement*) malloc(fieldCount * sizeof(BNumberElement)); 811 812 for (int i = 0 ; i < fieldCount ; i++ ) { 813 fieldPositions[i] = fieldPosStorage[i]; 814 switch (fieldTypeStorage[i]) { 815 case NumberFormat::kCurrencyField: 816 fieldTypes[i] = B_NUMBER_ELEMENT_CURRENCY; 817 break; 818 case NumberFormat::kIntegerField: 819 fieldTypes[i] = B_NUMBER_ELEMENT_INTEGER; 820 break; 821 case NumberFormat::kFractionField: 822 fieldTypes[i] = B_NUMBER_ELEMENT_FRACTIONAL; 823 break; 824 default: 825 fieldTypes[i] = B_NUMBER_ELEMENT_INVALID; 826 break; 827 } 828 } 829 830 BStringByteSink stringConverter(string); 831 832 ICUString.toUTF8(stringConverter); 833 834 return B_OK; 835 } 836 837 838 status_t 839 BLocale::GetCurrencySymbol(BString& result) const 840 { 841 UErrorCode error = U_ZERO_ERROR; 842 NumberFormat* format = NumberFormat::createCurrencyInstance(*fICULocale, 843 error); 844 845 if (U_FAILURE(error)) 846 return B_ERROR; 847 848 char* symbol = (char*)malloc(20); 849 u_strToUTF8(symbol, 20, NULL, format->getCurrency(), -1, &error); 850 if (U_FAILURE(error)) 851 return B_BAD_DATA; 852 result.Append(symbol); 853 delete format; 854 delete symbol; 855 return B_OK; 856 } 857 858 859 // #pragma mark - Helpers 860 861 862 static DateFormat* 863 CreateDateFormat(bool longFormat, const Locale& locale, 864 const BString& format) 865 { 866 DateFormat* dateFormatter = DateFormat::createDateInstance( 867 longFormat ? DateFormat::FULL : DateFormat::SHORT, locale); 868 869 if (format.Length() > 0) { 870 SimpleDateFormat* dateFormatterImpl 871 = static_cast<SimpleDateFormat*>(dateFormatter); 872 873 UnicodeString pattern(format.String()); 874 dateFormatterImpl->applyPattern(pattern); 875 } 876 877 return dateFormatter; 878 } 879 880 881 static DateFormat* 882 CreateTimeFormat(bool longFormat, const Locale& locale, 883 const BString& format) 884 { 885 DateFormat* timeFormatter = DateFormat::createTimeInstance( 886 longFormat ? DateFormat::MEDIUM : DateFormat::SHORT, locale); 887 888 if (format.Length() > 0) { 889 SimpleDateFormat* timeFormatterImpl 890 = static_cast<SimpleDateFormat*>(timeFormatter); 891 892 UnicodeString pattern(format.String()); 893 timeFormatterImpl->applyPattern(pattern); 894 } 895 896 return timeFormatter; 897 } 898