1 /* 2 ******************************************************************************* 3 * Copyright (C) 1997-2010, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 * 7 * File NUMFMT.CPP 8 * 9 * Modification History: 10 * 11 * Date Name Description 12 * 02/19/97 aliu Converted from java. 13 * 03/18/97 clhuang Implemented with C++ APIs. 14 * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accomodate the 15 * largest double, by default. 16 * Changed DigitCount to int per code review. 17 * 07/20/98 stephen Changed operator== to check for grouping 18 * Changed setMaxIntegerDigits per Java implementation. 19 * Changed setMinIntegerDigits per Java implementation. 20 * Changed setMinFractionDigits per Java implementation. 21 * Changed setMaxFractionDigits per Java implementation. 22 ******************************************************************************** 23 */ 24 25 #include "unicode/utypes.h" 26 27 #if !UCONFIG_NO_FORMATTING 28 29 #include "unicode/numfmt.h" 30 #include "unicode/locid.h" 31 #include "unicode/dcfmtsym.h" 32 #include "unicode/decimfmt.h" 33 #include "unicode/ustring.h" 34 #include "unicode/ucurr.h" 35 #include "unicode/curramt.h" 36 #include "unicode/numsys.h" 37 #include "unicode/rbnf.h" 38 #include "winnmfmt.h" 39 #include "uresimp.h" 40 #include "uhash.h" 41 #include "cmemory.h" 42 #include "servloc.h" 43 #include "ucln_in.h" 44 #include "cstring.h" 45 #include "putilimp.h" 46 #include "umutex.h" 47 #include "digitlst.h" 48 #include <float.h> 49 50 //#define FMT_DEBUG 51 52 #ifdef FMT_DEBUG 53 #include <stdio.h> 54 static void debugout(UnicodeString s) { 55 char buf[2000]; 56 s.extract((int32_t) 0, s.length(), buf); 57 printf("%s", buf); 58 } 59 #define debug(x) printf("%s", x); 60 #else 61 #define debugout(x) 62 #define debug(x) 63 #endif 64 65 // If no number pattern can be located for a locale, this is the last 66 // resort. 67 static const UChar gLastResortDecimalPat[] = { 68 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */ 69 }; 70 static const UChar gLastResortCurrencyPat[] = { 71 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */ 72 }; 73 static const UChar gLastResortPercentPat[] = { 74 0x23, 0x30, 0x25, 0 /* "#0%" */ 75 }; 76 static const UChar gLastResortScientificPat[] = { 77 0x23, 0x45, 0x30, 0 /* "#E0" */ 78 }; 79 static const UChar gLastResortIsoCurrencyPat[] = { 80 0xA4, 0xA4, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0xA4, 0xA4, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "\u00A4\u00A4#0.00;(\u00A4\u00A4#0.00)" */ 81 }; 82 static const UChar gLastResortPluralCurrencyPat[] = { 83 0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/ 84 }; 85 86 static const UChar gSingleCurrencySign[] = {0xA4, 0}; 87 static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0}; 88 89 static const UChar gSlash = 0x2f; 90 91 // If the maximum base 10 exponent were 4, then the largest number would 92 // be 99,999 which has 5 digits. 93 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit 94 static const int32_t gMaxIntegerDigits = DBL_MAX_10_EXP + DBL_DIG + 1; 95 static const int32_t gMinIntegerDigits = 127; 96 97 static const UChar * const gLastResortNumberPatterns[] = 98 { 99 gLastResortDecimalPat, 100 gLastResortCurrencyPat, 101 gLastResortPercentPat, 102 gLastResortScientificPat, 103 gLastResortIsoCurrencyPat, 104 gLastResortPluralCurrencyPat, 105 }; 106 107 // Keys used for accessing resource bundles 108 109 static const char *gNumberElements = "NumberElements"; 110 static const char *gLatn = "latn"; 111 static const char *gPatterns = "patterns"; 112 static const char *gFormatKeys[] = { "decimalFormat", "currencyFormat", "percentFormat", "scientificFormat" }; 113 114 // Static hashtable cache of NumberingSystem objects used by NumberFormat 115 static UHashtable * NumberingSystem_cache = NULL; 116 117 static UMTX nscacheMutex = NULL; 118 119 #if !UCONFIG_NO_SERVICE 120 static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL; 121 #endif 122 123 /** 124 * Release all static memory held by Number Format. 125 */ 126 U_CDECL_BEGIN 127 static void U_CALLCONV 128 deleteNumberingSystem(void *obj) { 129 delete (U_NAMESPACE_QUALIFIER NumberingSystem *)obj; 130 } 131 132 static UBool U_CALLCONV numfmt_cleanup(void) { 133 #if !UCONFIG_NO_SERVICE 134 if (gService) { 135 delete gService; 136 gService = NULL; 137 } 138 #endif 139 if (NumberingSystem_cache) { 140 // delete NumberingSystem_cache; 141 uhash_close(NumberingSystem_cache); 142 NumberingSystem_cache = NULL; 143 } 144 145 return TRUE; 146 } 147 U_CDECL_END 148 149 // ***************************************************************************** 150 // class NumberFormat 151 // ***************************************************************************** 152 153 U_NAMESPACE_BEGIN 154 155 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat) 156 157 #if !UCONFIG_NO_SERVICE 158 // ------------------------------------- 159 // SimpleNumberFormatFactory implementation 160 NumberFormatFactory::~NumberFormatFactory() {} 161 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible) 162 : _visible(visible) 163 { 164 LocaleUtility::initNameFromLocale(locale, _id); 165 } 166 167 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {} 168 169 UBool SimpleNumberFormatFactory::visible(void) const { 170 return _visible; 171 } 172 173 const UnicodeString * 174 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const 175 { 176 if (U_SUCCESS(status)) { 177 count = 1; 178 return &_id; 179 } 180 count = 0; 181 return NULL; 182 } 183 #endif /* #if !UCONFIG_NO_SERVICE */ 184 185 // ------------------------------------- 186 // default constructor 187 NumberFormat::NumberFormat() 188 : fGroupingUsed(TRUE), 189 fMaxIntegerDigits(gMaxIntegerDigits), 190 fMinIntegerDigits(1), 191 fMaxFractionDigits(3), // invariant, >= minFractionDigits 192 fMinFractionDigits(0), 193 fParseIntegerOnly(FALSE) 194 { 195 fCurrency[0] = 0; 196 } 197 198 // ------------------------------------- 199 200 NumberFormat::~NumberFormat() 201 { 202 } 203 204 // ------------------------------------- 205 // copy constructor 206 207 NumberFormat::NumberFormat(const NumberFormat &source) 208 : Format(source) 209 { 210 *this = source; 211 } 212 213 // ------------------------------------- 214 // assignment operator 215 216 NumberFormat& 217 NumberFormat::operator=(const NumberFormat& rhs) 218 { 219 if (this != &rhs) 220 { 221 Format::operator=(rhs); 222 fGroupingUsed = rhs.fGroupingUsed; 223 fMaxIntegerDigits = rhs.fMaxIntegerDigits; 224 fMinIntegerDigits = rhs.fMinIntegerDigits; 225 fMaxFractionDigits = rhs.fMaxFractionDigits; 226 fMinFractionDigits = rhs.fMinFractionDigits; 227 fParseIntegerOnly = rhs.fParseIntegerOnly; 228 u_strncpy(fCurrency, rhs.fCurrency, 4); 229 } 230 return *this; 231 } 232 233 // ------------------------------------- 234 235 UBool 236 NumberFormat::operator==(const Format& that) const 237 { 238 // Format::operator== guarantees this cast is safe 239 NumberFormat* other = (NumberFormat*)&that; 240 241 #ifdef FMT_DEBUG 242 // This code makes it easy to determine why two format objects that should 243 // be equal aren't. 244 UBool first = TRUE; 245 if (!Format::operator==(that)) { 246 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 247 debug("Format::!="); 248 } 249 if (!(fMaxIntegerDigits == other->fMaxIntegerDigits && 250 fMinIntegerDigits == other->fMinIntegerDigits)) { 251 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 252 debug("Integer digits !="); 253 } 254 if (!(fMaxFractionDigits == other->fMaxFractionDigits && 255 fMinFractionDigits == other->fMinFractionDigits)) { 256 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 257 debug("Fraction digits !="); 258 } 259 if (!(fGroupingUsed == other->fGroupingUsed)) { 260 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 261 debug("fGroupingUsed != "); 262 } 263 if (!(fParseIntegerOnly == other->fParseIntegerOnly)) { 264 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 265 debug("fParseIntegerOnly != "); 266 } 267 if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) { 268 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 269 debug("fCurrency !="); 270 } 271 if (!first) { printf(" ]"); } 272 #endif 273 274 return ((this == &that) || 275 ((Format::operator==(that) && 276 fMaxIntegerDigits == other->fMaxIntegerDigits && 277 fMinIntegerDigits == other->fMinIntegerDigits && 278 fMaxFractionDigits == other->fMaxFractionDigits && 279 fMinFractionDigits == other->fMinFractionDigits && 280 fGroupingUsed == other->fGroupingUsed && 281 fParseIntegerOnly == other->fParseIntegerOnly && 282 u_strcmp(fCurrency, other->fCurrency) == 0))); 283 } 284 285 // ------------------------------------- 286 // Default implementation sets unsupported error; subclasses should 287 // override. 288 289 UnicodeString& 290 NumberFormat::format(double /* unused number */, 291 UnicodeString& toAppendTo, 292 FieldPositionIterator* /* unused posIter */, 293 UErrorCode& status) const 294 { 295 if (!U_FAILURE(status)) { 296 status = U_UNSUPPORTED_ERROR; 297 } 298 return toAppendTo; 299 } 300 301 // ------------------------------------- 302 // Default implementation sets unsupported error; subclasses should 303 // override. 304 305 UnicodeString& 306 NumberFormat::format(int32_t /* unused number */, 307 UnicodeString& toAppendTo, 308 FieldPositionIterator* /* unused posIter */, 309 UErrorCode& status) const 310 { 311 if (!U_FAILURE(status)) { 312 status = U_UNSUPPORTED_ERROR; 313 } 314 return toAppendTo; 315 } 316 317 // ------------------------------------- 318 // Default implementation sets unsupported error; subclasses should 319 // override. 320 321 UnicodeString& 322 NumberFormat::format(int64_t /* unused number */, 323 UnicodeString& toAppendTo, 324 FieldPositionIterator* /* unused posIter */, 325 UErrorCode& status) const 326 { 327 if (!U_FAILURE(status)) { 328 status = U_UNSUPPORTED_ERROR; 329 } 330 return toAppendTo; 331 } 332 333 // ------------------------------------- 334 // Decimal Number format() default implementation 335 // Subclasses do not normally override this function, but rather the DigitList 336 // formatting functions.. 337 // The expected call chain from here is 338 // this function -> 339 // NumberFormat::format(Formattable -> 340 // DecimalFormat::format(DigitList 341 // 342 // Or, for subclasses of Formattable that do not know about DigitList, 343 // this Function -> 344 // NumberFormat::format(Formattable -> 345 // NumberFormat::format(DigitList -> 346 // XXXFormat::format(double 347 348 UnicodeString& 349 NumberFormat::format(const StringPiece &decimalNum, 350 UnicodeString& toAppendTo, 351 FieldPositionIterator* fpi, 352 UErrorCode& status) const 353 { 354 Formattable f; 355 f.setDecimalNumber(decimalNum, status); 356 format(f, toAppendTo, fpi, status); 357 return toAppendTo; 358 } 359 360 // ------------------------------------- 361 // Formats the number object and save the format 362 // result in the toAppendTo string buffer. 363 364 // utility to save/restore state, used in two overloads 365 // of format(const Formattable&...) below. 366 367 class ArgExtractor { 368 NumberFormat *ncnf; 369 const Formattable* num; 370 UBool setCurr; 371 UChar save[4]; 372 373 public: 374 ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status); 375 ~ArgExtractor(); 376 377 const Formattable* number(void) const; 378 }; 379 380 inline const Formattable* 381 ArgExtractor::number(void) const { 382 return num; 383 } 384 385 ArgExtractor::ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status) 386 : ncnf((NumberFormat*) &nf), num(&obj), setCurr(FALSE) { 387 388 const UObject* o = obj.getObject(); // most commonly o==NULL 389 const CurrencyAmount* amt; 390 if (o != NULL && (amt = dynamic_cast<const CurrencyAmount*>(o)) != NULL) { 391 // getISOCurrency() returns a pointer to internal storage, so we 392 // copy it to retain it across the call to setCurrency(). 393 const UChar* curr = amt->getISOCurrency(); 394 u_strcpy(save, nf.getCurrency()); 395 setCurr = (u_strcmp(curr, save) != 0); 396 if (setCurr) { 397 ncnf->setCurrency(curr, status); 398 } 399 num = &amt->getNumber(); 400 } 401 } 402 403 ArgExtractor::~ArgExtractor() { 404 if (setCurr) { 405 UErrorCode ok = U_ZERO_ERROR; 406 ncnf->setCurrency(save, ok); // always restore currency 407 } 408 } 409 410 UnicodeString& NumberFormat::format(const DigitList &number, 411 UnicodeString& appendTo, 412 FieldPositionIterator* posIter, 413 UErrorCode& status) const { 414 // DecimalFormat overrides this function, and handles DigitList based big decimals. 415 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists, 416 // so this default implementation falls back to formatting decimal numbers as doubles. 417 if (U_FAILURE(status)) { 418 return appendTo; 419 } 420 double dnum = number.getDouble(); 421 format(dnum, appendTo, posIter, status); 422 return appendTo; 423 } 424 425 426 427 UnicodeString& 428 NumberFormat::format(const DigitList &number, 429 UnicodeString& appendTo, 430 FieldPosition& pos, 431 UErrorCode &status) const { 432 // DecimalFormat overrides this function, and handles DigitList based big decimals. 433 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists, 434 // so this default implementation falls back to formatting decimal numbers as doubles. 435 if (U_FAILURE(status)) { 436 return appendTo; 437 } 438 double dnum = number.getDouble(); 439 format(dnum, appendTo, pos, status); 440 return appendTo; 441 } 442 443 UnicodeString& 444 NumberFormat::format(const Formattable& obj, 445 UnicodeString& appendTo, 446 FieldPosition& pos, 447 UErrorCode& status) const 448 { 449 if (U_FAILURE(status)) return appendTo; 450 451 ArgExtractor arg(*this, obj, status); 452 const Formattable *n = arg.number(); 453 454 if (n->isNumeric() && n->getDigitList() != NULL) { 455 // Decimal Number. We will have a DigitList available if the value was 456 // set to a decimal number, or if the value originated with a parse. 457 // 458 // The default implementation for formatting a DigitList converts it 459 // to a double, and formats that, allowing formatting classes that don't 460 // know about DigitList to continue to operate as they had. 461 // 462 // DecimalFormat overrides the DigitList formatting functions. 463 format(*n->getDigitList(), appendTo, pos, status); 464 } else { 465 switch (n->getType()) { 466 case Formattable::kDouble: 467 format(n->getDouble(), appendTo, pos); 468 break; 469 case Formattable::kLong: 470 format(n->getLong(), appendTo, pos); 471 break; 472 case Formattable::kInt64: 473 format(n->getInt64(), appendTo, pos); 474 break; 475 default: 476 status = U_INVALID_FORMAT_ERROR; 477 break; 478 } 479 } 480 481 return appendTo; 482 } 483 484 // -------------------------------------x 485 // Formats the number object and save the format 486 // result in the toAppendTo string buffer. 487 488 UnicodeString& 489 NumberFormat::format(const Formattable& obj, 490 UnicodeString& appendTo, 491 FieldPositionIterator* posIter, 492 UErrorCode& status) const 493 { 494 if (U_FAILURE(status)) return appendTo; 495 496 ArgExtractor arg(*this, obj, status); 497 const Formattable *n = arg.number(); 498 499 if (n->isNumeric() && n->getDigitList() != NULL) { 500 // Decimal Number 501 format(*n->getDigitList(), appendTo, posIter, status); 502 } else { 503 switch (n->getType()) { 504 case Formattable::kDouble: 505 format(n->getDouble(), appendTo, posIter, status); 506 break; 507 case Formattable::kLong: 508 format(n->getLong(), appendTo, posIter, status); 509 break; 510 case Formattable::kInt64: 511 format(n->getInt64(), appendTo, posIter, status); 512 break; 513 default: 514 status = U_INVALID_FORMAT_ERROR; 515 break; 516 } 517 } 518 519 return appendTo; 520 } 521 522 // ------------------------------------- 523 524 UnicodeString& 525 NumberFormat::format(int64_t number, 526 UnicodeString& appendTo, 527 FieldPosition& pos) const 528 { 529 // default so we don't introduce a new abstract method 530 return format((int32_t)number, appendTo, pos); 531 } 532 533 // ------------------------------------- 534 // Parses the string and save the result object as well 535 // as the final parsed position. 536 537 void 538 NumberFormat::parseObject(const UnicodeString& source, 539 Formattable& result, 540 ParsePosition& parse_pos) const 541 { 542 parse(source, result, parse_pos); 543 } 544 545 // ------------------------------------- 546 // Formats a double number and save the result in a string. 547 548 UnicodeString& 549 NumberFormat::format(double number, UnicodeString& appendTo) const 550 { 551 FieldPosition pos(0); 552 return format(number, appendTo, pos); 553 } 554 555 // ------------------------------------- 556 // Formats a long number and save the result in a string. 557 558 UnicodeString& 559 NumberFormat::format(int32_t number, UnicodeString& appendTo) const 560 { 561 FieldPosition pos(0); 562 return format(number, appendTo, pos); 563 } 564 565 // ------------------------------------- 566 // Formats a long number and save the result in a string. 567 568 UnicodeString& 569 NumberFormat::format(int64_t number, UnicodeString& appendTo) const 570 { 571 FieldPosition pos(0); 572 return format(number, appendTo, pos); 573 } 574 575 // ------------------------------------- 576 // Parses the text and save the result object. If the returned 577 // parse position is 0, that means the parsing failed, the status 578 // code needs to be set to failure. Ignores the returned parse 579 // position, otherwise. 580 581 void 582 NumberFormat::parse(const UnicodeString& text, 583 Formattable& result, 584 UErrorCode& status) const 585 { 586 if (U_FAILURE(status)) return; 587 588 ParsePosition parsePosition(0); 589 parse(text, result, parsePosition); 590 if (parsePosition.getIndex() == 0) { 591 status = U_INVALID_FORMAT_ERROR; 592 } 593 } 594 595 Formattable& NumberFormat::parseCurrency(const UnicodeString& text, 596 Formattable& result, 597 ParsePosition& pos) const { 598 // Default implementation only -- subclasses should override 599 int32_t start = pos.getIndex(); 600 parse(text, result, pos); 601 if (pos.getIndex() != start) { 602 UChar curr[4]; 603 UErrorCode ec = U_ZERO_ERROR; 604 getEffectiveCurrency(curr, ec); 605 if (U_SUCCESS(ec)) { 606 Formattable n(result); 607 CurrencyAmount *tempCurAmnt = new CurrencyAmount(n, curr, ec); // Use for null testing. 608 if (U_FAILURE(ec) || tempCurAmnt == NULL) { 609 pos.setIndex(start); // indicate failure 610 } else { 611 result.adoptObject(tempCurAmnt); 612 } 613 } 614 } 615 return result; 616 } 617 618 // ------------------------------------- 619 // Sets to only parse integers. 620 621 void 622 NumberFormat::setParseIntegerOnly(UBool value) 623 { 624 fParseIntegerOnly = value; 625 } 626 627 // ------------------------------------- 628 // Create a number style NumberFormat instance with the default locale. 629 630 NumberFormat* U_EXPORT2 631 NumberFormat::createInstance(UErrorCode& status) 632 { 633 return createInstance(Locale::getDefault(), kNumberStyle, status); 634 } 635 636 // ------------------------------------- 637 // Create a number style NumberFormat instance with the inLocale locale. 638 639 NumberFormat* U_EXPORT2 640 NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status) 641 { 642 return createInstance(inLocale, kNumberStyle, status); 643 } 644 645 // ------------------------------------- 646 // Create a currency style NumberFormat instance with the default locale. 647 648 NumberFormat* U_EXPORT2 649 NumberFormat::createCurrencyInstance(UErrorCode& status) 650 { 651 return createCurrencyInstance(Locale::getDefault(), status); 652 } 653 654 // ------------------------------------- 655 // Create a currency style NumberFormat instance with the inLocale locale. 656 657 NumberFormat* U_EXPORT2 658 NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status) 659 { 660 return createInstance(inLocale, kCurrencyStyle, status); 661 } 662 663 // ------------------------------------- 664 // Create a percent style NumberFormat instance with the default locale. 665 666 NumberFormat* U_EXPORT2 667 NumberFormat::createPercentInstance(UErrorCode& status) 668 { 669 return createInstance(Locale::getDefault(), kPercentStyle, status); 670 } 671 672 // ------------------------------------- 673 // Create a percent style NumberFormat instance with the inLocale locale. 674 675 NumberFormat* U_EXPORT2 676 NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status) 677 { 678 return createInstance(inLocale, kPercentStyle, status); 679 } 680 681 // ------------------------------------- 682 // Create a scientific style NumberFormat instance with the default locale. 683 684 NumberFormat* U_EXPORT2 685 NumberFormat::createScientificInstance(UErrorCode& status) 686 { 687 return createInstance(Locale::getDefault(), kScientificStyle, status); 688 } 689 690 // ------------------------------------- 691 // Create a scientific style NumberFormat instance with the inLocale locale. 692 693 NumberFormat* U_EXPORT2 694 NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status) 695 { 696 return createInstance(inLocale, kScientificStyle, status); 697 } 698 699 // ------------------------------------- 700 701 const Locale* U_EXPORT2 702 NumberFormat::getAvailableLocales(int32_t& count) 703 { 704 return Locale::getAvailableLocales(count); 705 } 706 707 // ------------------------------------------ 708 // 709 // Registration 710 // 711 //------------------------------------------- 712 713 #if !UCONFIG_NO_SERVICE 714 715 // ------------------------------------- 716 717 class ICUNumberFormatFactory : public ICUResourceBundleFactory { 718 protected: 719 virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const { 720 // !!! kind is not an EStyles, need to determine how to handle this 721 return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status); 722 } 723 }; 724 725 // ------------------------------------- 726 727 class NFFactory : public LocaleKeyFactory { 728 private: 729 NumberFormatFactory* _delegate; 730 Hashtable* _ids; 731 732 public: 733 NFFactory(NumberFormatFactory* delegate) 734 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE) 735 , _delegate(delegate) 736 , _ids(NULL) 737 { 738 } 739 740 virtual ~NFFactory() 741 { 742 delete _delegate; 743 delete _ids; 744 } 745 746 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const 747 { 748 if (handlesKey(key, status)) { 749 const LocaleKey& lkey = (const LocaleKey&)key; 750 Locale loc; 751 lkey.canonicalLocale(loc); 752 int32_t kind = lkey.kind(); 753 754 UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)(kind+1)); 755 if (result == NULL) { 756 result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status); 757 } 758 return result; 759 } 760 return NULL; 761 } 762 763 protected: 764 /** 765 * Return the set of ids that this factory supports (visible or 766 * otherwise). This can be called often and might need to be 767 * cached if it is expensive to create. 768 */ 769 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const 770 { 771 if (U_SUCCESS(status)) { 772 if (!_ids) { 773 int32_t count = 0; 774 const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status); 775 ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */ 776 if (_ids) { 777 for (int i = 0; i < count; ++i) { 778 _ids->put(idlist[i], (void*)this, status); 779 } 780 } 781 } 782 return _ids; 783 } 784 return NULL; 785 } 786 }; 787 788 class ICUNumberFormatService : public ICULocaleService { 789 public: 790 ICUNumberFormatService() 791 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format")) 792 { 793 UErrorCode status = U_ZERO_ERROR; 794 registerFactory(new ICUNumberFormatFactory(), status); 795 } 796 797 virtual UObject* cloneInstance(UObject* instance) const { 798 return ((NumberFormat*)instance)->clone(); 799 } 800 801 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const { 802 LocaleKey& lkey = (LocaleKey&)key; 803 int32_t kind = lkey.kind(); 804 Locale loc; 805 lkey.currentLocale(loc); 806 return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status); 807 } 808 809 virtual UBool isDefault() const { 810 return countFactories() == 1; 811 } 812 }; 813 814 // ------------------------------------- 815 816 static ICULocaleService* 817 getNumberFormatService(void) 818 { 819 UBool needInit; 820 UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit); 821 if (needInit) { 822 ICULocaleService * newservice = new ICUNumberFormatService(); 823 if (newservice) { 824 umtx_lock(NULL); 825 if (gService == NULL) { 826 gService = newservice; 827 newservice = NULL; 828 } 829 umtx_unlock(NULL); 830 } 831 if (newservice) { 832 delete newservice; 833 } else { 834 // we won the contention, this thread can register cleanup. 835 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup); 836 } 837 } 838 return gService; 839 } 840 841 // ------------------------------------- 842 843 URegistryKey U_EXPORT2 844 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status) 845 { 846 ICULocaleService *service = getNumberFormatService(); 847 if (service) { 848 NFFactory *tempnnf = new NFFactory(toAdopt); 849 if (tempnnf != NULL) { 850 return service->registerFactory(tempnnf, status); 851 } 852 } 853 status = U_MEMORY_ALLOCATION_ERROR; 854 return NULL; 855 } 856 857 // ------------------------------------- 858 859 UBool U_EXPORT2 860 NumberFormat::unregister(URegistryKey key, UErrorCode& status) 861 { 862 if (U_SUCCESS(status)) { 863 UBool haveService; 864 UMTX_CHECK(NULL, gService != NULL, haveService); 865 if (haveService) { 866 return gService->unregister(key, status); 867 } 868 status = U_ILLEGAL_ARGUMENT_ERROR; 869 } 870 return FALSE; 871 } 872 873 // ------------------------------------- 874 StringEnumeration* U_EXPORT2 875 NumberFormat::getAvailableLocales(void) 876 { 877 ICULocaleService *service = getNumberFormatService(); 878 if (service) { 879 return service->getAvailableLocales(); 880 } 881 return NULL; // no way to return error condition 882 } 883 #endif /* UCONFIG_NO_SERVICE */ 884 // ------------------------------------- 885 886 NumberFormat* U_EXPORT2 887 NumberFormat::createInstance(const Locale& loc, EStyles kind, UErrorCode& status) 888 { 889 #if !UCONFIG_NO_SERVICE 890 UBool haveService; 891 UMTX_CHECK(NULL, gService != NULL, haveService); 892 if (haveService) { 893 return (NumberFormat*)gService->get(loc, kind, status); 894 } 895 else 896 #endif 897 { 898 return makeInstance(loc, kind, status); 899 } 900 } 901 902 903 // ------------------------------------- 904 // Checks if the thousand/10 thousand grouping is used in the 905 // NumberFormat instance. 906 907 UBool 908 NumberFormat::isGroupingUsed() const 909 { 910 return fGroupingUsed; 911 } 912 913 // ------------------------------------- 914 // Sets to use the thousand/10 thousand grouping in the 915 // NumberFormat instance. 916 917 void 918 NumberFormat::setGroupingUsed(UBool newValue) 919 { 920 fGroupingUsed = newValue; 921 } 922 923 // ------------------------------------- 924 // Gets the maximum number of digits for the integral part for 925 // this NumberFormat instance. 926 927 int32_t NumberFormat::getMaximumIntegerDigits() const 928 { 929 return fMaxIntegerDigits; 930 } 931 932 // ------------------------------------- 933 // Sets the maximum number of digits for the integral part for 934 // this NumberFormat instance. 935 936 void 937 NumberFormat::setMaximumIntegerDigits(int32_t newValue) 938 { 939 fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits)); 940 if(fMinIntegerDigits > fMaxIntegerDigits) 941 fMinIntegerDigits = fMaxIntegerDigits; 942 } 943 944 // ------------------------------------- 945 // Gets the minimum number of digits for the integral part for 946 // this NumberFormat instance. 947 948 int32_t 949 NumberFormat::getMinimumIntegerDigits() const 950 { 951 return fMinIntegerDigits; 952 } 953 954 // ------------------------------------- 955 // Sets the minimum number of digits for the integral part for 956 // this NumberFormat instance. 957 958 void 959 NumberFormat::setMinimumIntegerDigits(int32_t newValue) 960 { 961 fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits)); 962 if(fMinIntegerDigits > fMaxIntegerDigits) 963 fMaxIntegerDigits = fMinIntegerDigits; 964 } 965 966 // ------------------------------------- 967 // Gets the maximum number of digits for the fractional part for 968 // this NumberFormat instance. 969 970 int32_t 971 NumberFormat::getMaximumFractionDigits() const 972 { 973 return fMaxFractionDigits; 974 } 975 976 // ------------------------------------- 977 // Sets the maximum number of digits for the fractional part for 978 // this NumberFormat instance. 979 980 void 981 NumberFormat::setMaximumFractionDigits(int32_t newValue) 982 { 983 fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits)); 984 if(fMaxFractionDigits < fMinFractionDigits) 985 fMinFractionDigits = fMaxFractionDigits; 986 } 987 988 // ------------------------------------- 989 // Gets the minimum number of digits for the fractional part for 990 // this NumberFormat instance. 991 992 int32_t 993 NumberFormat::getMinimumFractionDigits() const 994 { 995 return fMinFractionDigits; 996 } 997 998 // ------------------------------------- 999 // Sets the minimum number of digits for the fractional part for 1000 // this NumberFormat instance. 1001 1002 void 1003 NumberFormat::setMinimumFractionDigits(int32_t newValue) 1004 { 1005 fMinFractionDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits)); 1006 if (fMaxFractionDigits < fMinFractionDigits) 1007 fMaxFractionDigits = fMinFractionDigits; 1008 } 1009 1010 // ------------------------------------- 1011 1012 void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { 1013 if (U_FAILURE(ec)) { 1014 return; 1015 } 1016 if (theCurrency) { 1017 u_strncpy(fCurrency, theCurrency, 3); 1018 fCurrency[3] = 0; 1019 } else { 1020 fCurrency[0] = 0; 1021 } 1022 } 1023 1024 const UChar* NumberFormat::getCurrency() const { 1025 return fCurrency; 1026 } 1027 1028 void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { 1029 const UChar* c = getCurrency(); 1030 if (*c != 0) { 1031 u_strncpy(result, c, 3); 1032 result[3] = 0; 1033 } else { 1034 const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec); 1035 if (loc == NULL) { 1036 loc = uloc_getDefault(); 1037 } 1038 ucurr_forLocale(loc, result, 4, &ec); 1039 } 1040 } 1041 1042 // ------------------------------------- 1043 // Creates the NumberFormat instance of the specified style (number, currency, 1044 // or percent) for the desired locale. 1045 1046 NumberFormat* 1047 NumberFormat::makeInstance(const Locale& desiredLocale, 1048 EStyles style, 1049 UErrorCode& status) 1050 { 1051 if (U_FAILURE(status)) return NULL; 1052 1053 if (style < 0 || style >= kStyleCount) { 1054 status = U_ILLEGAL_ARGUMENT_ERROR; 1055 return NULL; 1056 } 1057 1058 #ifdef U_WINDOWS 1059 char buffer[8]; 1060 int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status); 1061 1062 // if the locale has "@compat=host", create a host-specific NumberFormat 1063 if (count > 0 && uprv_strcmp(buffer, "host") == 0) { 1064 Win32NumberFormat *f = NULL; 1065 UBool curr = TRUE; 1066 1067 switch (style) { 1068 case kNumberStyle: 1069 curr = FALSE; 1070 // fall-through 1071 1072 case kCurrencyStyle: 1073 case kIsoCurrencyStyle: // do not support plural formatting here 1074 case kPluralCurrencyStyle: 1075 f = new Win32NumberFormat(desiredLocale, curr, status); 1076 1077 if (U_SUCCESS(status)) { 1078 return f; 1079 } 1080 1081 delete f; 1082 break; 1083 1084 default: 1085 break; 1086 } 1087 } 1088 #endif 1089 1090 NumberFormat* f = NULL; 1091 DecimalFormatSymbols* symbolsToAdopt = NULL; 1092 UnicodeString pattern; 1093 UResourceBundle *resource = ures_open(NULL, desiredLocale.getName(), &status); 1094 NumberingSystem *ns = NULL; 1095 UBool deleteSymbols = TRUE; 1096 UHashtable * cache = NULL; 1097 int32_t hashKey; 1098 UBool getCache = FALSE; 1099 UBool deleteNS = FALSE; 1100 1101 if (U_FAILURE(status)) { 1102 // We don't appear to have resource data available -- use the last-resort data 1103 status = U_USING_FALLBACK_WARNING; 1104 // When the data is unavailable, and locale isn't passed in, last resort data is used. 1105 symbolsToAdopt = new DecimalFormatSymbols(status); 1106 1107 // Creates a DecimalFormat instance with the last resort number patterns. 1108 pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1); 1109 } 1110 else { 1111 // Loads the decimal symbols of the desired locale. 1112 symbolsToAdopt = new DecimalFormatSymbols(desiredLocale, status); 1113 1114 int32_t patLen = 0; 1115 1116 /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE, 1117 * the pattern is the same as the pattern of CURRENCYSTYLE 1118 * but by replacing the single currency sign with 1119 * double currency sign or triple currency sign. 1120 */ 1121 int styleInNumberPattern = ((style == kIsoCurrencyStyle || 1122 style == kPluralCurrencyStyle) ? 1123 kCurrencyStyle : style); 1124 1125 resource = ures_getByKeyWithFallback(resource, gNumberElements, resource, &status); 1126 // TODO : Get patterns on a per numbering system basis, for right now assumes "latn" for patterns 1127 resource = ures_getByKeyWithFallback(resource, gLatn, resource, &status); 1128 resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); 1129 1130 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[styleInNumberPattern], &patLen, &status); 1131 1132 // Creates the specified decimal format style of the desired locale. 1133 pattern.setTo(TRUE, patResStr, patLen); 1134 } 1135 if (U_FAILURE(status) || symbolsToAdopt == NULL) { 1136 goto cleanup; 1137 } 1138 if(style==kCurrencyStyle || style == kIsoCurrencyStyle){ 1139 const UChar* currPattern = symbolsToAdopt->getCurrencyPattern(); 1140 if(currPattern!=NULL){ 1141 pattern.setTo(currPattern, u_strlen(currPattern)); 1142 } 1143 } 1144 1145 // Use numbering system cache hashtable 1146 UMTX_CHECK(&nscacheMutex, (UBool)(cache != NumberingSystem_cache), getCache); 1147 if (getCache) { 1148 umtx_lock(&nscacheMutex); 1149 cache = NumberingSystem_cache; 1150 umtx_unlock(&nscacheMutex); 1151 } 1152 1153 // Check cache we got, create if non-existant 1154 status = U_ZERO_ERROR; 1155 if (cache == NULL) { 1156 cache = uhash_open(uhash_hashLong, 1157 uhash_compareLong, 1158 NULL, 1159 &status); 1160 1161 if (cache == NULL || U_FAILURE(status)) { 1162 // cache not created - out of memory 1163 cache = NULL; 1164 } 1165 else { 1166 // cache created 1167 uhash_setValueDeleter(cache, deleteNumberingSystem); 1168 1169 // set final NumberingSystem_cache value 1170 UHashtable* h = NULL; 1171 1172 UMTX_CHECK(&nscacheMutex, (UBool)(h != NumberingSystem_cache), getCache); 1173 if (getCache) { 1174 umtx_lock(&nscacheMutex); 1175 h = NumberingSystem_cache; 1176 umtx_unlock(&nscacheMutex); 1177 } 1178 if (h == NULL) { 1179 umtx_lock(&nscacheMutex); 1180 NumberingSystem_cache = h = cache; 1181 cache = NULL; 1182 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup); 1183 umtx_unlock(&nscacheMutex); 1184 } 1185 1186 if(cache != NULL) { 1187 uhash_close(cache); 1188 } 1189 cache = h; 1190 } 1191 } 1192 1193 // Get cached numbering system 1194 if (cache != NULL) { 1195 hashKey = desiredLocale.hashCode(); 1196 1197 umtx_lock(&nscacheMutex); 1198 ns = (NumberingSystem *)uhash_iget(cache, hashKey); 1199 if (ns == NULL) { 1200 ns = NumberingSystem::createInstance(desiredLocale,status); 1201 uhash_iput(cache, hashKey, (void*)ns, &status); 1202 } 1203 umtx_unlock(&nscacheMutex); 1204 } 1205 else { 1206 ns = NumberingSystem::createInstance(desiredLocale,status); 1207 deleteNS = TRUE; 1208 } 1209 1210 // check results of getting a numbering system 1211 if ((ns == NULL) || (U_FAILURE(status))) { 1212 goto cleanup; 1213 } 1214 1215 if (ns->isAlgorithmic()) { 1216 UnicodeString nsDesc; 1217 UnicodeString nsRuleSetGroup; 1218 UnicodeString nsRuleSetName; 1219 Locale nsLoc; 1220 URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM; 1221 1222 nsDesc.setTo(ns->getDescription()); 1223 int32_t firstSlash = nsDesc.indexOf(gSlash); 1224 int32_t lastSlash = nsDesc.lastIndexOf(gSlash); 1225 if ( lastSlash > firstSlash ) { 1226 char nsLocID[ULOC_FULLNAME_CAPACITY]; 1227 1228 nsDesc.extract(0,firstSlash,nsLocID,ULOC_FULLNAME_CAPACITY,US_INV); 1229 nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1); 1230 nsRuleSetName.setTo(nsDesc,lastSlash+1); 1231 1232 nsLoc = Locale::createFromName(nsLocID); 1233 1234 UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules"); 1235 if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) { 1236 desiredRulesType = URBNF_SPELLOUT; 1237 } 1238 } else { 1239 nsLoc = desiredLocale; 1240 nsRuleSetName.setTo(nsDesc); 1241 } 1242 1243 RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status); 1244 1245 if (U_FAILURE(status) || r == NULL) { 1246 goto cleanup; 1247 } 1248 r->setDefaultRuleSet(nsRuleSetName,status); 1249 f = (NumberFormat *) r; 1250 1251 } else { 1252 // replace single currency sign in the pattern with double currency sign 1253 // if the style is kIsoCurrencyStyle 1254 if (style == kIsoCurrencyStyle) { 1255 pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign); 1256 } 1257 1258 f = new DecimalFormat(pattern, symbolsToAdopt, style, status); 1259 if (U_FAILURE(status) || f == NULL) { 1260 goto cleanup; 1261 } 1262 deleteSymbols = FALSE; 1263 } 1264 1265 f->setLocaleIDs(ures_getLocaleByType(resource, ULOC_VALID_LOCALE, &status), 1266 ures_getLocaleByType(resource, ULOC_ACTUAL_LOCALE, &status)); 1267 1268 cleanup: 1269 ures_close(resource); 1270 1271 if (deleteNS && ns) { 1272 delete ns; 1273 } 1274 1275 if (U_FAILURE(status)) { 1276 /* If f exists, then it will delete the symbols */ 1277 if (f==NULL) { 1278 delete symbolsToAdopt; 1279 } 1280 else { 1281 delete f; 1282 } 1283 return NULL; 1284 } 1285 if (f == NULL || symbolsToAdopt == NULL) { 1286 status = U_MEMORY_ALLOCATION_ERROR; 1287 f = NULL; 1288 } 1289 if (deleteSymbols && symbolsToAdopt != NULL) { 1290 delete symbolsToAdopt; 1291 } 1292 return f; 1293 } 1294 1295 U_NAMESPACE_END 1296 1297 #endif /* #if !UCONFIG_NO_FORMATTING */ 1298 1299 //eof 1300