1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 1997-2015, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************************* 8 * 9 * File NUMFMT.CPP 10 * 11 * Modification History: 12 * 13 * Date Name Description 14 * 02/19/97 aliu Converted from java. 15 * 03/18/97 clhuang Implemented with C++ APIs. 16 * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accomodate the 17 * largest double, by default. 18 * Changed DigitCount to int per code review. 19 * 07/20/98 stephen Changed operator== to check for grouping 20 * Changed setMaxIntegerDigits per Java implementation. 21 * Changed setMinIntegerDigits per Java implementation. 22 * Changed setMinFractionDigits per Java implementation. 23 * Changed setMaxFractionDigits per Java implementation. 24 ******************************************************************************** 25 */ 26 27 #include "unicode/utypes.h" 28 29 #if !UCONFIG_NO_FORMATTING 30 31 #include "unicode/numfmt.h" 32 #include "unicode/locid.h" 33 #include "unicode/dcfmtsym.h" 34 #include "unicode/decimfmt.h" 35 #include "unicode/ustring.h" 36 #include "unicode/ucurr.h" 37 #include "unicode/curramt.h" 38 #include "unicode/numsys.h" 39 #include "unicode/rbnf.h" 40 #include "unicode/localpointer.h" 41 #include "unicode/udisplaycontext.h" 42 #include "charstr.h" 43 #include "winnmfmt.h" 44 #include "uresimp.h" 45 #include "uhash.h" 46 #include "cmemory.h" 47 #include "servloc.h" 48 #include "ucln_in.h" 49 #include "cstring.h" 50 #include "putilimp.h" 51 #include "uassert.h" 52 #include "umutex.h" 53 #include "mutex.h" 54 #include "digitlst.h" 55 #include <float.h> 56 #include "sharednumberformat.h" 57 #include "unifiedcache.h" 58 59 //#define FMT_DEBUG 60 61 #ifdef FMT_DEBUG 62 #include <stdio.h> 63 static inline void debugout(UnicodeString s) { 64 char buf[2000]; 65 s.extract((int32_t) 0, s.length(), buf); 66 printf("%s", buf); 67 } 68 #define debug(x) printf("%s", x); 69 #else 70 #define debugout(x) 71 #define debug(x) 72 #endif 73 74 // If no number pattern can be located for a locale, this is the last 75 // resort. The patterns are same as the ones in root locale. 76 static const UChar gLastResortDecimalPat[] = { 77 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */ 78 }; 79 static const UChar gLastResortCurrencyPat[] = { 80 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */ 81 }; 82 static const UChar gLastResortPercentPat[] = { 83 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */ 84 }; 85 static const UChar gLastResortScientificPat[] = { 86 0x23, 0x45, 0x30, 0 /* "#E0" */ 87 }; 88 static const UChar gLastResortIsoCurrencyPat[] = { 89 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */ 90 }; 91 static const UChar gLastResortPluralCurrencyPat[] = { 92 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/ 93 }; 94 static const UChar gLastResortAccountingCurrencyPat[] = { 95 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */ 96 }; 97 98 static const UChar gSingleCurrencySign[] = {0xA4, 0}; 99 static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0}; 100 101 static const UChar gSlash = 0x2f; 102 103 // If the maximum base 10 exponent were 4, then the largest number would 104 // be 99,999 which has 5 digits. 105 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit 106 // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999 107 const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits = 2000000000; 108 const int32_t icu::NumberFormat::gDefaultMinIntegerDigits = 127; 109 110 static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = { 111 NULL, // UNUM_PATTERN_DECIMAL 112 gLastResortDecimalPat, // UNUM_DECIMAL 113 gLastResortCurrencyPat, // UNUM_CURRENCY 114 gLastResortPercentPat, // UNUM_PERCENT 115 gLastResortScientificPat, // UNUM_SCIENTIFIC 116 NULL, // UNUM_SPELLOUT 117 NULL, // UNUM_ORDINAL 118 NULL, // UNUM_DURATION 119 NULL, // UNUM_NUMBERING_SYSTEM 120 NULL, // UNUM_PATTERN_RULEBASED 121 gLastResortIsoCurrencyPat, // UNUM_CURRENCY_ISO 122 gLastResortPluralCurrencyPat, // UNUM_CURRENCY_PLURAL 123 gLastResortAccountingCurrencyPat, // UNUM_CURRENCY_ACCOUNTING 124 gLastResortCurrencyPat, // UNUM_CASH_CURRENCY 125 NULL, // UNUM_DECIMAL_COMPACT_SHORT 126 NULL, // UNUM_DECIMAL_COMPACT_LONG 127 gLastResortCurrencyPat, // UNUM_CURRENCY_STANDARD 128 }; 129 130 // Keys used for accessing resource bundles 131 132 static const char *gNumberElements = "NumberElements"; 133 static const char *gLatn = "latn"; 134 static const char *gPatterns = "patterns"; 135 static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = { 136 NULL, // UNUM_PATTERN_DECIMAL 137 "decimalFormat", // UNUM_DECIMAL 138 "currencyFormat", // UNUM_CURRENCY 139 "percentFormat", // UNUM_PERCENT 140 "scientificFormat", // UNUM_SCIENTIFIC 141 NULL, // UNUM_SPELLOUT 142 NULL, // UNUM_ORDINAL 143 NULL, // UNUM_DURATION 144 NULL, // UNUM_NUMBERING_SYSTEM 145 NULL, // UNUM_PATTERN_RULEBASED 146 // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL, 147 // the pattern is the same as the pattern of UNUM_CURRENCY 148 // except for replacing the single currency sign with 149 // double currency sign or triple currency sign. 150 "currencyFormat", // UNUM_CURRENCY_ISO 151 "currencyFormat", // UNUM_CURRENCY_PLURAL 152 "accountingFormat", // UNUM_CURRENCY_ACCOUNTING 153 "currencyFormat", // UNUM_CASH_CURRENCY 154 NULL, // UNUM_DECIMAL_COMPACT_SHORT 155 NULL, // UNUM_DECIMAL_COMPACT_LONG 156 "currencyFormat", // UNUM_CURRENCY_STANDARD 157 }; 158 159 // Static hashtable cache of NumberingSystem objects used by NumberFormat 160 static UHashtable * NumberingSystem_cache = NULL; 161 static UMutex nscacheMutex = U_MUTEX_INITIALIZER; 162 static icu::UInitOnce gNSCacheInitOnce = U_INITONCE_INITIALIZER; 163 164 #if !UCONFIG_NO_SERVICE 165 static icu::ICULocaleService* gService = NULL; 166 static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER; 167 #endif 168 169 /** 170 * Release all static memory held by Number Format. 171 */ 172 U_CDECL_BEGIN 173 static void U_CALLCONV 174 deleteNumberingSystem(void *obj) { 175 delete (icu::NumberingSystem *)obj; 176 } 177 178 static UBool U_CALLCONV numfmt_cleanup(void) { 179 #if !UCONFIG_NO_SERVICE 180 gServiceInitOnce.reset(); 181 if (gService) { 182 delete gService; 183 gService = NULL; 184 } 185 #endif 186 gNSCacheInitOnce.reset(); 187 if (NumberingSystem_cache) { 188 // delete NumberingSystem_cache; 189 uhash_close(NumberingSystem_cache); 190 NumberingSystem_cache = NULL; 191 } 192 return TRUE; 193 } 194 U_CDECL_END 195 196 // ***************************************************************************** 197 // class NumberFormat 198 // ***************************************************************************** 199 200 U_NAMESPACE_BEGIN 201 202 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat) 203 204 #if !UCONFIG_NO_SERVICE 205 // ------------------------------------- 206 // SimpleNumberFormatFactory implementation 207 NumberFormatFactory::~NumberFormatFactory() {} 208 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible) 209 : _visible(visible) 210 { 211 LocaleUtility::initNameFromLocale(locale, _id); 212 } 213 214 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {} 215 216 UBool SimpleNumberFormatFactory::visible(void) const { 217 return _visible; 218 } 219 220 const UnicodeString * 221 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const 222 { 223 if (U_SUCCESS(status)) { 224 count = 1; 225 return &_id; 226 } 227 count = 0; 228 return NULL; 229 } 230 #endif /* #if !UCONFIG_NO_SERVICE */ 231 232 // ------------------------------------- 233 // default constructor 234 NumberFormat::NumberFormat() 235 : fGroupingUsed(TRUE), 236 fMaxIntegerDigits(gDefaultMaxIntegerDigits), 237 fMinIntegerDigits(1), 238 fMaxFractionDigits(3), // invariant, >= minFractionDigits 239 fMinFractionDigits(0), 240 fParseIntegerOnly(FALSE), 241 fLenient(FALSE), 242 fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE) 243 { 244 fCurrency[0] = 0; 245 } 246 247 // ------------------------------------- 248 249 NumberFormat::~NumberFormat() 250 { 251 } 252 253 SharedNumberFormat::~SharedNumberFormat() { 254 delete ptr; 255 } 256 257 // ------------------------------------- 258 // copy constructor 259 260 NumberFormat::NumberFormat(const NumberFormat &source) 261 : Format(source) 262 { 263 *this = source; 264 } 265 266 // ------------------------------------- 267 // assignment operator 268 269 NumberFormat& 270 NumberFormat::operator=(const NumberFormat& rhs) 271 { 272 if (this != &rhs) 273 { 274 Format::operator=(rhs); 275 fGroupingUsed = rhs.fGroupingUsed; 276 fMaxIntegerDigits = rhs.fMaxIntegerDigits; 277 fMinIntegerDigits = rhs.fMinIntegerDigits; 278 fMaxFractionDigits = rhs.fMaxFractionDigits; 279 fMinFractionDigits = rhs.fMinFractionDigits; 280 fParseIntegerOnly = rhs.fParseIntegerOnly; 281 u_strncpy(fCurrency, rhs.fCurrency, 3); 282 fCurrency[3] = 0; 283 fLenient = rhs.fLenient; 284 fCapitalizationContext = rhs.fCapitalizationContext; 285 } 286 return *this; 287 } 288 289 // ------------------------------------- 290 291 UBool 292 NumberFormat::operator==(const Format& that) const 293 { 294 // Format::operator== guarantees this cast is safe 295 NumberFormat* other = (NumberFormat*)&that; 296 297 #ifdef FMT_DEBUG 298 // This code makes it easy to determine why two format objects that should 299 // be equal aren't. 300 UBool first = TRUE; 301 if (!Format::operator==(that)) { 302 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 303 debug("Format::!="); 304 } 305 if (!(fMaxIntegerDigits == other->fMaxIntegerDigits && 306 fMinIntegerDigits == other->fMinIntegerDigits)) { 307 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 308 debug("Integer digits !="); 309 } 310 if (!(fMaxFractionDigits == other->fMaxFractionDigits && 311 fMinFractionDigits == other->fMinFractionDigits)) { 312 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 313 debug("Fraction digits !="); 314 } 315 if (!(fGroupingUsed == other->fGroupingUsed)) { 316 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 317 debug("fGroupingUsed != "); 318 } 319 if (!(fParseIntegerOnly == other->fParseIntegerOnly)) { 320 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 321 debug("fParseIntegerOnly != "); 322 } 323 if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) { 324 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 325 debug("fCurrency !="); 326 } 327 if (!(fLenient == other->fLenient)) { 328 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 329 debug("fLenient != "); 330 } 331 if (!(fCapitalizationContext == other->fCapitalizationContext)) { 332 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 333 debug("fCapitalizationContext != "); 334 } 335 if (!first) { printf(" ]"); } 336 #endif 337 338 return ((this == &that) || 339 ((Format::operator==(that) && 340 fMaxIntegerDigits == other->fMaxIntegerDigits && 341 fMinIntegerDigits == other->fMinIntegerDigits && 342 fMaxFractionDigits == other->fMaxFractionDigits && 343 fMinFractionDigits == other->fMinFractionDigits && 344 fGroupingUsed == other->fGroupingUsed && 345 fParseIntegerOnly == other->fParseIntegerOnly && 346 u_strcmp(fCurrency, other->fCurrency) == 0 && 347 fLenient == other->fLenient && 348 fCapitalizationContext == other->fCapitalizationContext))); 349 } 350 351 // ------------------------------------- 352 // Default implementation sets unsupported error; subclasses should 353 // override. 354 355 UnicodeString& 356 NumberFormat::format(double /* unused number */, 357 UnicodeString& toAppendTo, 358 FieldPositionIterator* /* unused posIter */, 359 UErrorCode& status) const 360 { 361 if (!U_FAILURE(status)) { 362 status = U_UNSUPPORTED_ERROR; 363 } 364 return toAppendTo; 365 } 366 367 // ------------------------------------- 368 // Default implementation sets unsupported error; subclasses should 369 // override. 370 371 UnicodeString& 372 NumberFormat::format(int32_t /* unused number */, 373 UnicodeString& toAppendTo, 374 FieldPositionIterator* /* unused posIter */, 375 UErrorCode& status) const 376 { 377 if (!U_FAILURE(status)) { 378 status = U_UNSUPPORTED_ERROR; 379 } 380 return toAppendTo; 381 } 382 383 // ------------------------------------- 384 // Default implementation sets unsupported error; subclasses should 385 // override. 386 387 UnicodeString& 388 NumberFormat::format(int64_t /* unused number */, 389 UnicodeString& toAppendTo, 390 FieldPositionIterator* /* unused posIter */, 391 UErrorCode& status) const 392 { 393 if (!U_FAILURE(status)) { 394 status = U_UNSUPPORTED_ERROR; 395 } 396 return toAppendTo; 397 } 398 399 // ------------------------------------------ 400 // These functions add the status code, just fall back to the non-status versions 401 UnicodeString& 402 NumberFormat::format(double number, 403 UnicodeString& appendTo, 404 FieldPosition& pos, 405 UErrorCode &status) const { 406 if(U_SUCCESS(status)) { 407 return format(number,appendTo,pos); 408 } else { 409 return appendTo; 410 } 411 } 412 413 UnicodeString& 414 NumberFormat::format(int32_t number, 415 UnicodeString& appendTo, 416 FieldPosition& pos, 417 UErrorCode &status) const { 418 if(U_SUCCESS(status)) { 419 return format(number,appendTo,pos); 420 } else { 421 return appendTo; 422 } 423 } 424 425 UnicodeString& 426 NumberFormat::format(int64_t number, 427 UnicodeString& appendTo, 428 FieldPosition& pos, 429 UErrorCode &status) const { 430 if(U_SUCCESS(status)) { 431 return format(number,appendTo,pos); 432 } else { 433 return appendTo; 434 } 435 } 436 437 438 439 // ------------------------------------- 440 // Decimal Number format() default implementation 441 // Subclasses do not normally override this function, but rather the DigitList 442 // formatting functions.. 443 // The expected call chain from here is 444 // this function -> 445 // NumberFormat::format(Formattable -> 446 // DecimalFormat::format(DigitList 447 // 448 // Or, for subclasses of Formattable that do not know about DigitList, 449 // this Function -> 450 // NumberFormat::format(Formattable -> 451 // NumberFormat::format(DigitList -> 452 // XXXFormat::format(double 453 454 UnicodeString& 455 NumberFormat::format(StringPiece decimalNum, 456 UnicodeString& toAppendTo, 457 FieldPositionIterator* fpi, 458 UErrorCode& status) const 459 { 460 Formattable f; 461 f.setDecimalNumber(decimalNum, status); 462 format(f, toAppendTo, fpi, status); 463 return toAppendTo; 464 } 465 466 /** 467 * 468 // Formats the number object and save the format 469 // result in the toAppendTo string buffer. 470 471 // utility to save/restore state, used in two overloads 472 // of format(const Formattable&...) below. 473 * 474 * Old purpose of ArgExtractor was to avoid const. Not thread safe! 475 * 476 * keeping it around as a shim. 477 */ 478 class ArgExtractor { 479 const Formattable* num; 480 UChar save[4]; 481 UBool fWasCurrency; 482 483 public: 484 ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status); 485 ~ArgExtractor(); 486 487 const Formattable* number(void) const; 488 const UChar *iso(void) const; 489 UBool wasCurrency(void) const; 490 }; 491 492 inline const Formattable* 493 ArgExtractor::number(void) const { 494 return num; 495 } 496 497 inline UBool 498 ArgExtractor::wasCurrency(void) const { 499 return fWasCurrency; 500 } 501 502 inline const UChar * 503 ArgExtractor::iso(void) const { 504 return save; 505 } 506 507 ArgExtractor::ArgExtractor(const NumberFormat& /*nf*/, const Formattable& obj, UErrorCode& /*status*/) 508 : num(&obj), fWasCurrency(FALSE) { 509 510 const UObject* o = obj.getObject(); // most commonly o==NULL 511 const CurrencyAmount* amt; 512 if (o != NULL && (amt = dynamic_cast<const CurrencyAmount*>(o)) != NULL) { 513 // getISOCurrency() returns a pointer to internal storage, so we 514 // copy it to retain it across the call to setCurrency(). 515 //const UChar* curr = amt->getISOCurrency(); 516 u_strcpy(save, amt->getISOCurrency()); 517 num = &amt->getNumber(); 518 fWasCurrency=TRUE; 519 } else { 520 save[0]=0; 521 } 522 } 523 524 ArgExtractor::~ArgExtractor() { 525 } 526 527 UnicodeString& NumberFormat::format(const DigitList &number, 528 UnicodeString& appendTo, 529 FieldPositionIterator* posIter, 530 UErrorCode& status) const { 531 // DecimalFormat overrides this function, and handles DigitList based big decimals. 532 // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists, 533 // so this default implementation falls back to formatting decimal numbers as doubles. 534 if (U_FAILURE(status)) { 535 return appendTo; 536 } 537 double dnum = number.getDouble(); 538 format(dnum, appendTo, posIter, status); 539 return appendTo; 540 } 541 542 543 544 UnicodeString& 545 NumberFormat::format(const DigitList &number, 546 UnicodeString& appendTo, 547 FieldPosition& pos, 548 UErrorCode &status) const { 549 // DecimalFormat overrides this function, and handles DigitList based big decimals. 550 // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists, 551 // so this default implementation falls back to formatting decimal numbers as doubles. 552 if (U_FAILURE(status)) { 553 return appendTo; 554 } 555 double dnum = number.getDouble(); 556 format(dnum, appendTo, pos, status); 557 return appendTo; 558 } 559 560 UnicodeString& 561 NumberFormat::format(const Formattable& obj, 562 UnicodeString& appendTo, 563 FieldPosition& pos, 564 UErrorCode& status) const 565 { 566 if (U_FAILURE(status)) return appendTo; 567 568 ArgExtractor arg(*this, obj, status); 569 const Formattable *n = arg.number(); 570 const UChar *iso = arg.iso(); 571 572 if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) { 573 // trying to format a different currency. 574 // Right now, we clone. 575 LocalPointer<NumberFormat> cloneFmt((NumberFormat*)this->clone()); 576 cloneFmt->setCurrency(iso, status); 577 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount. 578 return cloneFmt->format(*n, appendTo, pos, status); 579 } 580 581 if (n->isNumeric() && n->getDigitList() != NULL) { 582 // Decimal Number. We will have a DigitList available if the value was 583 // set to a decimal number, or if the value originated with a parse. 584 // 585 // The default implementation for formatting a DigitList converts it 586 // to a double, and formats that, allowing formatting classes that don't 587 // know about DigitList to continue to operate as they had. 588 // 589 // DecimalFormat overrides the DigitList formatting functions. 590 format(*n->getDigitList(), appendTo, pos, status); 591 } else { 592 switch (n->getType()) { 593 case Formattable::kDouble: 594 format(n->getDouble(), appendTo, pos); 595 break; 596 case Formattable::kLong: 597 format(n->getLong(), appendTo, pos); 598 break; 599 case Formattable::kInt64: 600 format(n->getInt64(), appendTo, pos); 601 break; 602 default: 603 status = U_INVALID_FORMAT_ERROR; 604 break; 605 } 606 } 607 608 return appendTo; 609 } 610 611 // -------------------------------------x 612 // Formats the number object and save the format 613 // result in the toAppendTo string buffer. 614 615 UnicodeString& 616 NumberFormat::format(const Formattable& obj, 617 UnicodeString& appendTo, 618 FieldPositionIterator* posIter, 619 UErrorCode& status) const 620 { 621 if (U_FAILURE(status)) return appendTo; 622 623 ArgExtractor arg(*this, obj, status); 624 const Formattable *n = arg.number(); 625 const UChar *iso = arg.iso(); 626 627 if(arg.wasCurrency() && u_strcmp(iso, getCurrency())) { 628 // trying to format a different currency. 629 // Right now, we clone. 630 LocalPointer<NumberFormat> cloneFmt((NumberFormat*)this->clone()); 631 cloneFmt->setCurrency(iso, status); 632 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount. 633 return cloneFmt->format(*n, appendTo, posIter, status); 634 } 635 636 if (n->isNumeric() && n->getDigitList() != NULL) { 637 // Decimal Number 638 format(*n->getDigitList(), appendTo, posIter, status); 639 } else { 640 switch (n->getType()) { 641 case Formattable::kDouble: 642 format(n->getDouble(), appendTo, posIter, status); 643 break; 644 case Formattable::kLong: 645 format(n->getLong(), appendTo, posIter, status); 646 break; 647 case Formattable::kInt64: 648 format(n->getInt64(), appendTo, posIter, status); 649 break; 650 default: 651 status = U_INVALID_FORMAT_ERROR; 652 break; 653 } 654 } 655 656 return appendTo; 657 } 658 659 // ------------------------------------- 660 661 UnicodeString& 662 NumberFormat::format(int64_t number, 663 UnicodeString& appendTo, 664 FieldPosition& pos) const 665 { 666 // default so we don't introduce a new abstract method 667 return format((int32_t)number, appendTo, pos); 668 } 669 670 // ------------------------------------- 671 // Parses the string and save the result object as well 672 // as the final parsed position. 673 674 void 675 NumberFormat::parseObject(const UnicodeString& source, 676 Formattable& result, 677 ParsePosition& parse_pos) const 678 { 679 parse(source, result, parse_pos); 680 } 681 682 // ------------------------------------- 683 // Formats a double number and save the result in a string. 684 685 UnicodeString& 686 NumberFormat::format(double number, UnicodeString& appendTo) const 687 { 688 FieldPosition pos(FieldPosition::DONT_CARE); 689 return format(number, appendTo, pos); 690 } 691 692 // ------------------------------------- 693 // Formats a long number and save the result in a string. 694 695 UnicodeString& 696 NumberFormat::format(int32_t number, UnicodeString& appendTo) const 697 { 698 FieldPosition pos(FieldPosition::DONT_CARE); 699 return format(number, appendTo, pos); 700 } 701 702 // ------------------------------------- 703 // Formats a long number and save the result in a string. 704 705 UnicodeString& 706 NumberFormat::format(int64_t number, UnicodeString& appendTo) const 707 { 708 FieldPosition pos(FieldPosition::DONT_CARE); 709 return format(number, appendTo, pos); 710 } 711 712 // ------------------------------------- 713 // Parses the text and save the result object. If the returned 714 // parse position is 0, that means the parsing failed, the status 715 // code needs to be set to failure. Ignores the returned parse 716 // position, otherwise. 717 718 void 719 NumberFormat::parse(const UnicodeString& text, 720 Formattable& result, 721 UErrorCode& status) const 722 { 723 if (U_FAILURE(status)) return; 724 725 ParsePosition parsePosition(0); 726 parse(text, result, parsePosition); 727 if (parsePosition.getIndex() == 0) { 728 status = U_INVALID_FORMAT_ERROR; 729 } 730 } 731 732 CurrencyAmount* NumberFormat::parseCurrency(const UnicodeString& text, 733 ParsePosition& pos) const { 734 // Default implementation only -- subclasses should override 735 Formattable parseResult; 736 int32_t start = pos.getIndex(); 737 parse(text, parseResult, pos); 738 if (pos.getIndex() != start) { 739 UChar curr[4]; 740 UErrorCode ec = U_ZERO_ERROR; 741 getEffectiveCurrency(curr, ec); 742 if (U_SUCCESS(ec)) { 743 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curr, ec), ec); 744 if (U_FAILURE(ec)) { 745 pos.setIndex(start); // indicate failure 746 } else { 747 return currAmt.orphan(); 748 } 749 } 750 } 751 return NULL; 752 } 753 754 // ------------------------------------- 755 // Sets to only parse integers. 756 757 void 758 NumberFormat::setParseIntegerOnly(UBool value) 759 { 760 fParseIntegerOnly = value; 761 } 762 763 // ------------------------------------- 764 // Sets whether lenient parse is enabled. 765 766 void 767 NumberFormat::setLenient(UBool enable) 768 { 769 fLenient = enable; 770 } 771 772 // ------------------------------------- 773 // Create a number style NumberFormat instance with the default locale. 774 775 NumberFormat* U_EXPORT2 776 NumberFormat::createInstance(UErrorCode& status) 777 { 778 return createInstance(Locale::getDefault(), UNUM_DECIMAL, status); 779 } 780 781 // ------------------------------------- 782 // Create a number style NumberFormat instance with the inLocale locale. 783 784 NumberFormat* U_EXPORT2 785 NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status) 786 { 787 return createInstance(inLocale, UNUM_DECIMAL, status); 788 } 789 790 // ------------------------------------- 791 // Create a currency style NumberFormat instance with the default locale. 792 793 NumberFormat* U_EXPORT2 794 NumberFormat::createCurrencyInstance(UErrorCode& status) 795 { 796 return createCurrencyInstance(Locale::getDefault(), status); 797 } 798 799 // ------------------------------------- 800 // Create a currency style NumberFormat instance with the inLocale locale. 801 802 NumberFormat* U_EXPORT2 803 NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status) 804 { 805 return createInstance(inLocale, UNUM_CURRENCY, status); 806 } 807 808 // ------------------------------------- 809 // Create a percent style NumberFormat instance with the default locale. 810 811 NumberFormat* U_EXPORT2 812 NumberFormat::createPercentInstance(UErrorCode& status) 813 { 814 return createInstance(Locale::getDefault(), UNUM_PERCENT, status); 815 } 816 817 // ------------------------------------- 818 // Create a percent style NumberFormat instance with the inLocale locale. 819 820 NumberFormat* U_EXPORT2 821 NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status) 822 { 823 return createInstance(inLocale, UNUM_PERCENT, status); 824 } 825 826 // ------------------------------------- 827 // Create a scientific style NumberFormat instance with the default locale. 828 829 NumberFormat* U_EXPORT2 830 NumberFormat::createScientificInstance(UErrorCode& status) 831 { 832 return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC, status); 833 } 834 835 // ------------------------------------- 836 // Create a scientific style NumberFormat instance with the inLocale locale. 837 838 NumberFormat* U_EXPORT2 839 NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status) 840 { 841 return createInstance(inLocale, UNUM_SCIENTIFIC, status); 842 } 843 844 // ------------------------------------- 845 846 const Locale* U_EXPORT2 847 NumberFormat::getAvailableLocales(int32_t& count) 848 { 849 return Locale::getAvailableLocales(count); 850 } 851 852 // ------------------------------------------ 853 // 854 // Registration 855 // 856 //------------------------------------------- 857 858 #if !UCONFIG_NO_SERVICE 859 860 // ------------------------------------- 861 862 class ICUNumberFormatFactory : public ICUResourceBundleFactory { 863 public: 864 virtual ~ICUNumberFormatFactory(); 865 protected: 866 virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const { 867 return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status); 868 } 869 }; 870 871 ICUNumberFormatFactory::~ICUNumberFormatFactory() {} 872 873 // ------------------------------------- 874 875 class NFFactory : public LocaleKeyFactory { 876 private: 877 NumberFormatFactory* _delegate; 878 Hashtable* _ids; 879 880 public: 881 NFFactory(NumberFormatFactory* delegate) 882 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE) 883 , _delegate(delegate) 884 , _ids(NULL) 885 { 886 } 887 888 virtual ~NFFactory(); 889 890 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const 891 { 892 if (handlesKey(key, status)) { 893 const LocaleKey& lkey = (const LocaleKey&)key; 894 Locale loc; 895 lkey.canonicalLocale(loc); 896 int32_t kind = lkey.kind(); 897 898 UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)kind); 899 if (result == NULL) { 900 result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status); 901 } 902 return result; 903 } 904 return NULL; 905 } 906 907 protected: 908 /** 909 * Return the set of ids that this factory supports (visible or 910 * otherwise). This can be called often and might need to be 911 * cached if it is expensive to create. 912 */ 913 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const 914 { 915 if (U_SUCCESS(status)) { 916 if (!_ids) { 917 int32_t count = 0; 918 const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status); 919 ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */ 920 if (_ids) { 921 for (int i = 0; i < count; ++i) { 922 _ids->put(idlist[i], (void*)this, status); 923 } 924 } 925 } 926 return _ids; 927 } 928 return NULL; 929 } 930 }; 931 932 NFFactory::~NFFactory() 933 { 934 delete _delegate; 935 delete _ids; 936 } 937 938 class ICUNumberFormatService : public ICULocaleService { 939 public: 940 ICUNumberFormatService() 941 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format")) 942 { 943 UErrorCode status = U_ZERO_ERROR; 944 registerFactory(new ICUNumberFormatFactory(), status); 945 } 946 947 virtual ~ICUNumberFormatService(); 948 949 virtual UObject* cloneInstance(UObject* instance) const { 950 return ((NumberFormat*)instance)->clone(); 951 } 952 953 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const { 954 LocaleKey& lkey = (LocaleKey&)key; 955 int32_t kind = lkey.kind(); 956 Locale loc; 957 lkey.currentLocale(loc); 958 return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status); 959 } 960 961 virtual UBool isDefault() const { 962 return countFactories() == 1; 963 } 964 }; 965 966 ICUNumberFormatService::~ICUNumberFormatService() {} 967 968 // ------------------------------------- 969 970 static void U_CALLCONV initNumberFormatService() { 971 U_ASSERT(gService == NULL); 972 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup); 973 gService = new ICUNumberFormatService(); 974 } 975 976 static ICULocaleService* 977 getNumberFormatService(void) 978 { 979 umtx_initOnce(gServiceInitOnce, &initNumberFormatService); 980 return gService; 981 } 982 983 static UBool haveService() { 984 return !gServiceInitOnce.isReset() && (getNumberFormatService() != NULL); 985 } 986 987 // ------------------------------------- 988 989 URegistryKey U_EXPORT2 990 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status) 991 { 992 ICULocaleService *service = getNumberFormatService(); 993 if (service) { 994 NFFactory *tempnnf = new NFFactory(toAdopt); 995 if (tempnnf != NULL) { 996 return service->registerFactory(tempnnf, status); 997 } 998 } 999 status = U_MEMORY_ALLOCATION_ERROR; 1000 return NULL; 1001 } 1002 1003 // ------------------------------------- 1004 1005 UBool U_EXPORT2 1006 NumberFormat::unregister(URegistryKey key, UErrorCode& status) 1007 { 1008 if (U_FAILURE(status)) { 1009 return FALSE; 1010 } 1011 if (haveService()) { 1012 return gService->unregister(key, status); 1013 } else { 1014 status = U_ILLEGAL_ARGUMENT_ERROR; 1015 return FALSE; 1016 } 1017 } 1018 1019 // ------------------------------------- 1020 StringEnumeration* U_EXPORT2 1021 NumberFormat::getAvailableLocales(void) 1022 { 1023 ICULocaleService *service = getNumberFormatService(); 1024 if (service) { 1025 return service->getAvailableLocales(); 1026 } 1027 return NULL; // no way to return error condition 1028 } 1029 #endif /* UCONFIG_NO_SERVICE */ 1030 // ------------------------------------- 1031 1032 enum { kKeyValueLenMax = 32 }; 1033 1034 NumberFormat* 1035 NumberFormat::internalCreateInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { 1036 if (kind == UNUM_CURRENCY) { 1037 char cfKeyValue[kKeyValueLenMax] = {0}; 1038 UErrorCode kvStatus = U_ZERO_ERROR; 1039 int32_t kLen = loc.getKeywordValue("cf", cfKeyValue, kKeyValueLenMax, kvStatus); 1040 if (U_SUCCESS(kvStatus) && kLen > 0 && uprv_strcmp(cfKeyValue,"account")==0) { 1041 kind = UNUM_CURRENCY_ACCOUNTING; 1042 } 1043 } 1044 #if !UCONFIG_NO_SERVICE 1045 if (haveService()) { 1046 return (NumberFormat*)gService->get(loc, kind, status); 1047 } 1048 #endif 1049 return makeInstance(loc, kind, status); 1050 } 1051 1052 NumberFormat* U_EXPORT2 1053 NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { 1054 if (kind != UNUM_DECIMAL) { 1055 return internalCreateInstance(loc, kind, status); 1056 } 1057 const SharedNumberFormat *shared = createSharedInstance(loc, kind, status); 1058 if (U_FAILURE(status)) { 1059 return NULL; 1060 } 1061 NumberFormat *result = static_cast<NumberFormat *>((*shared)->clone()); 1062 shared->removeRef(); 1063 if (result == NULL) { 1064 status = U_MEMORY_ALLOCATION_ERROR; 1065 } 1066 return result; 1067 } 1068 1069 1070 // ------------------------------------- 1071 // Checks if the thousand/10 thousand grouping is used in the 1072 // NumberFormat instance. 1073 1074 UBool 1075 NumberFormat::isGroupingUsed() const 1076 { 1077 return fGroupingUsed; 1078 } 1079 1080 // ------------------------------------- 1081 // Sets to use the thousand/10 thousand grouping in the 1082 // NumberFormat instance. 1083 1084 void 1085 NumberFormat::setGroupingUsed(UBool newValue) 1086 { 1087 fGroupingUsed = newValue; 1088 } 1089 1090 // ------------------------------------- 1091 // Gets the maximum number of digits for the integral part for 1092 // this NumberFormat instance. 1093 1094 int32_t NumberFormat::getMaximumIntegerDigits() const 1095 { 1096 return fMaxIntegerDigits; 1097 } 1098 1099 // ------------------------------------- 1100 // Sets the maximum number of digits for the integral part for 1101 // this NumberFormat instance. 1102 1103 void 1104 NumberFormat::setMaximumIntegerDigits(int32_t newValue) 1105 { 1106 fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gDefaultMaxIntegerDigits)); 1107 if(fMinIntegerDigits > fMaxIntegerDigits) 1108 fMinIntegerDigits = fMaxIntegerDigits; 1109 } 1110 1111 // ------------------------------------- 1112 // Gets the minimum number of digits for the integral part for 1113 // this NumberFormat instance. 1114 1115 int32_t 1116 NumberFormat::getMinimumIntegerDigits() const 1117 { 1118 return fMinIntegerDigits; 1119 } 1120 1121 // ------------------------------------- 1122 // Sets the minimum number of digits for the integral part for 1123 // this NumberFormat instance. 1124 1125 void 1126 NumberFormat::setMinimumIntegerDigits(int32_t newValue) 1127 { 1128 fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gDefaultMinIntegerDigits)); 1129 if(fMinIntegerDigits > fMaxIntegerDigits) 1130 fMaxIntegerDigits = fMinIntegerDigits; 1131 } 1132 1133 // ------------------------------------- 1134 // Gets the maximum number of digits for the fractional part for 1135 // this NumberFormat instance. 1136 1137 int32_t 1138 NumberFormat::getMaximumFractionDigits() const 1139 { 1140 return fMaxFractionDigits; 1141 } 1142 1143 // ------------------------------------- 1144 // Sets the maximum number of digits for the fractional part for 1145 // this NumberFormat instance. 1146 1147 void 1148 NumberFormat::setMaximumFractionDigits(int32_t newValue) 1149 { 1150 fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gDefaultMaxIntegerDigits)); 1151 if(fMaxFractionDigits < fMinFractionDigits) 1152 fMinFractionDigits = fMaxFractionDigits; 1153 } 1154 1155 // ------------------------------------- 1156 // Gets the minimum number of digits for the fractional part for 1157 // this NumberFormat instance. 1158 1159 int32_t 1160 NumberFormat::getMinimumFractionDigits() const 1161 { 1162 return fMinFractionDigits; 1163 } 1164 1165 // ------------------------------------- 1166 // Sets the minimum number of digits for the fractional part for 1167 // this NumberFormat instance. 1168 1169 void 1170 NumberFormat::setMinimumFractionDigits(int32_t newValue) 1171 { 1172 fMinFractionDigits = uprv_max(0, uprv_min(newValue, gDefaultMinIntegerDigits)); 1173 if (fMaxFractionDigits < fMinFractionDigits) 1174 fMaxFractionDigits = fMinFractionDigits; 1175 } 1176 1177 // ------------------------------------- 1178 1179 void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { 1180 if (U_FAILURE(ec)) { 1181 return; 1182 } 1183 if (theCurrency) { 1184 u_strncpy(fCurrency, theCurrency, 3); 1185 fCurrency[3] = 0; 1186 } else { 1187 fCurrency[0] = 0; 1188 } 1189 } 1190 1191 const char16_t* NumberFormat::getCurrency() const { 1192 return fCurrency; 1193 } 1194 1195 void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { 1196 const UChar* c = getCurrency(); 1197 if (*c != 0) { 1198 u_strncpy(result, c, 3); 1199 result[3] = 0; 1200 } else { 1201 const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec); 1202 if (loc == NULL) { 1203 loc = uloc_getDefault(); 1204 } 1205 ucurr_forLocale(loc, result, 4, &ec); 1206 } 1207 } 1208 1209 //---------------------------------------------------------------------- 1210 1211 1212 void NumberFormat::setContext(UDisplayContext value, UErrorCode& status) 1213 { 1214 if (U_FAILURE(status)) 1215 return; 1216 if ( (UDisplayContextType)((uint32_t)value >> 8) == UDISPCTX_TYPE_CAPITALIZATION ) { 1217 fCapitalizationContext = value; 1218 } else { 1219 status = U_ILLEGAL_ARGUMENT_ERROR; 1220 } 1221 } 1222 1223 1224 UDisplayContext NumberFormat::getContext(UDisplayContextType type, UErrorCode& status) const 1225 { 1226 if (U_FAILURE(status)) 1227 return (UDisplayContext)0; 1228 if (type != UDISPCTX_TYPE_CAPITALIZATION) { 1229 status = U_ILLEGAL_ARGUMENT_ERROR; 1230 return (UDisplayContext)0; 1231 } 1232 return fCapitalizationContext; 1233 } 1234 1235 1236 // ------------------------------------- 1237 // Creates the NumberFormat instance of the specified style (number, currency, 1238 // or percent) for the desired locale. 1239 1240 static void U_CALLCONV nscacheInit() { 1241 U_ASSERT(NumberingSystem_cache == NULL); 1242 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup); 1243 UErrorCode status = U_ZERO_ERROR; 1244 NumberingSystem_cache = uhash_open(uhash_hashLong, 1245 uhash_compareLong, 1246 NULL, 1247 &status); 1248 if (U_FAILURE(status)) { 1249 // Number Format code will run with no cache if creation fails. 1250 NumberingSystem_cache = NULL; 1251 return; 1252 } 1253 uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem); 1254 } 1255 1256 template<> U_I18N_API 1257 const SharedNumberFormat *LocaleCacheKey<SharedNumberFormat>::createObject( 1258 const void * /*unused*/, UErrorCode &status) const { 1259 const char *localeId = fLoc.getName(); 1260 NumberFormat *nf = NumberFormat::internalCreateInstance( 1261 localeId, UNUM_DECIMAL, status); 1262 if (U_FAILURE(status)) { 1263 return NULL; 1264 } 1265 SharedNumberFormat *result = new SharedNumberFormat(nf); 1266 if (result == NULL) { 1267 status = U_MEMORY_ALLOCATION_ERROR; 1268 delete nf; 1269 return NULL; 1270 } 1271 result->addRef(); 1272 return result; 1273 } 1274 1275 const SharedNumberFormat* U_EXPORT2 1276 NumberFormat::createSharedInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { 1277 if (U_FAILURE(status)) { 1278 return NULL; 1279 } 1280 if (kind != UNUM_DECIMAL) { 1281 status = U_UNSUPPORTED_ERROR; 1282 return NULL; 1283 } 1284 const SharedNumberFormat *result = NULL; 1285 UnifiedCache::getByLocale(loc, result, status); 1286 return result; 1287 } 1288 1289 UBool 1290 NumberFormat::isStyleSupported(UNumberFormatStyle style) { 1291 return gLastResortNumberPatterns[style] != NULL; 1292 } 1293 1294 NumberFormat* 1295 NumberFormat::makeInstance(const Locale& desiredLocale, 1296 UNumberFormatStyle style, 1297 UErrorCode& status) { 1298 return makeInstance(desiredLocale, style, false, status); 1299 } 1300 1301 NumberFormat* 1302 NumberFormat::makeInstance(const Locale& desiredLocale, 1303 UNumberFormatStyle style, 1304 UBool mustBeDecimalFormat, 1305 UErrorCode& status) { 1306 if (U_FAILURE(status)) return NULL; 1307 1308 if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) { 1309 status = U_ILLEGAL_ARGUMENT_ERROR; 1310 return NULL; 1311 } 1312 1313 // Some styles are not supported. This is a result of merging 1314 // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle. 1315 // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations: 1316 // this one and unum_open(). 1317 // The UNUM_PATTERN_ styles are not supported here 1318 // because this method does not take a pattern string. 1319 if (!isStyleSupported(style)) { 1320 status = U_UNSUPPORTED_ERROR; 1321 return NULL; 1322 } 1323 1324 #if U_PLATFORM_USES_ONLY_WIN32_API 1325 if (!mustBeDecimalFormat) { 1326 char buffer[8]; 1327 int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status); 1328 1329 // if the locale has "@compat=host", create a host-specific NumberFormat 1330 if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) { 1331 Win32NumberFormat *f = NULL; 1332 UBool curr = TRUE; 1333 1334 switch (style) { 1335 case UNUM_DECIMAL: 1336 curr = FALSE; 1337 // fall-through 1338 1339 case UNUM_CURRENCY: 1340 case UNUM_CURRENCY_ISO: // do not support plural formatting here 1341 case UNUM_CURRENCY_PLURAL: 1342 case UNUM_CURRENCY_ACCOUNTING: 1343 case UNUM_CASH_CURRENCY: 1344 case UNUM_CURRENCY_STANDARD: 1345 f = new Win32NumberFormat(desiredLocale, curr, status); 1346 1347 if (U_SUCCESS(status)) { 1348 return f; 1349 } 1350 1351 delete f; 1352 break; 1353 default: 1354 break; 1355 } 1356 } 1357 } 1358 #endif 1359 // Use numbering system cache hashtable 1360 umtx_initOnce(gNSCacheInitOnce, &nscacheInit); 1361 1362 // Get cached numbering system 1363 LocalPointer<NumberingSystem> ownedNs; 1364 NumberingSystem *ns = NULL; 1365 if (NumberingSystem_cache != NULL) { 1366 // TODO: Bad hash key usage, see ticket #8504. 1367 int32_t hashKey = desiredLocale.hashCode(); 1368 1369 Mutex lock(&nscacheMutex); 1370 ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey); 1371 if (ns == NULL) { 1372 ns = NumberingSystem::createInstance(desiredLocale,status); 1373 uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status); 1374 } 1375 } else { 1376 ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status)); 1377 ns = ownedNs.getAlias(); 1378 } 1379 1380 // check results of getting a numbering system 1381 if (U_FAILURE(status)) { 1382 return NULL; 1383 } 1384 1385 if (mustBeDecimalFormat && ns->isAlgorithmic()) { 1386 status = U_UNSUPPORTED_ERROR; 1387 return NULL; 1388 } 1389 1390 LocalPointer<DecimalFormatSymbols> symbolsToAdopt; 1391 UnicodeString pattern; 1392 LocalUResourceBundlePointer ownedResource(ures_open(NULL, desiredLocale.getName(), &status)); 1393 if (U_FAILURE(status)) { 1394 return NULL; 1395 } 1396 else { 1397 // Loads the decimal symbols of the desired locale. 1398 symbolsToAdopt.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(desiredLocale, status), status); 1399 if (U_FAILURE(status)) { 1400 return NULL; 1401 } 1402 1403 UResourceBundle *resource = ownedResource.orphan(); 1404 UResourceBundle *numElements = ures_getByKeyWithFallback(resource, gNumberElements, NULL, &status); 1405 resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &status); 1406 resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); 1407 ownedResource.adoptInstead(resource); 1408 1409 int32_t patLen = 0; 1410 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status); 1411 1412 // Didn't find a pattern specific to the numbering system, so fall back to "latn" 1413 if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(gLatn,ns->getName())) { 1414 status = U_ZERO_ERROR; 1415 resource = ures_getByKeyWithFallback(numElements, gLatn, resource, &status); 1416 resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); 1417 patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status); 1418 } 1419 1420 ures_close(numElements); 1421 1422 // Creates the specified decimal format style of the desired locale. 1423 pattern.setTo(TRUE, patResStr, patLen); 1424 } 1425 if (U_FAILURE(status)) { 1426 return NULL; 1427 } 1428 if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO || style == UNUM_CURRENCY_ACCOUNTING 1429 || style == UNUM_CASH_CURRENCY || style == UNUM_CURRENCY_STANDARD){ 1430 const UChar* currPattern = symbolsToAdopt->getCurrencyPattern(); 1431 if(currPattern!=NULL){ 1432 pattern.setTo(currPattern, u_strlen(currPattern)); 1433 } 1434 } 1435 1436 1437 NumberFormat *f; 1438 if (ns->isAlgorithmic()) { 1439 UnicodeString nsDesc; 1440 UnicodeString nsRuleSetGroup; 1441 UnicodeString nsRuleSetName; 1442 Locale nsLoc; 1443 URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM; 1444 1445 nsDesc.setTo(ns->getDescription()); 1446 int32_t firstSlash = nsDesc.indexOf(gSlash); 1447 int32_t lastSlash = nsDesc.lastIndexOf(gSlash); 1448 if ( lastSlash > firstSlash ) { 1449 CharString nsLocID; 1450 1451 nsLocID.appendInvariantChars(nsDesc.tempSubString(0, firstSlash), status); 1452 nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1); 1453 nsRuleSetName.setTo(nsDesc,lastSlash+1); 1454 1455 nsLoc = Locale::createFromName(nsLocID.data()); 1456 1457 UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules"); 1458 if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) { 1459 desiredRulesType = URBNF_SPELLOUT; 1460 } 1461 } else { 1462 nsLoc = desiredLocale; 1463 nsRuleSetName.setTo(nsDesc); 1464 } 1465 1466 RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status); 1467 if (r == NULL) { 1468 status = U_MEMORY_ALLOCATION_ERROR; 1469 return NULL; 1470 } 1471 r->setDefaultRuleSet(nsRuleSetName,status); 1472 f = r; 1473 } else { 1474 // replace single currency sign in the pattern with double currency sign 1475 // if the style is UNUM_CURRENCY_ISO 1476 if (style == UNUM_CURRENCY_ISO) { 1477 pattern.findAndReplace(UnicodeString(TRUE, gSingleCurrencySign, 1), 1478 UnicodeString(TRUE, gDoubleCurrencySign, 2)); 1479 } 1480 1481 // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails. 1482 DecimalFormatSymbols *syms = symbolsToAdopt.orphan(); 1483 DecimalFormat* df = new DecimalFormat(pattern, syms, style, status); 1484 1485 // if it is cash currency style, setCurrencyUsage with usage 1486 if (style == UNUM_CASH_CURRENCY){ 1487 df->setCurrencyUsage(UCURR_USAGE_CASH, &status); 1488 } 1489 1490 if (U_FAILURE(status)) { 1491 delete df; 1492 return NULL; 1493 } 1494 1495 f = df; 1496 if (f == NULL) { 1497 delete syms; 1498 status = U_MEMORY_ALLOCATION_ERROR; 1499 return NULL; 1500 } 1501 } 1502 1503 f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status), 1504 ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status)); 1505 if (U_FAILURE(status)) { 1506 delete f; 1507 return NULL; 1508 } 1509 return f; 1510 } 1511 1512 /** 1513 * Get the rounding mode. 1514 * @return A rounding mode 1515 */ 1516 NumberFormat::ERoundingMode NumberFormat::getRoundingMode() const { 1517 // Default value. ICU4J throws an exception and we can't change this API. 1518 return NumberFormat::ERoundingMode::kRoundUnnecessary; 1519 } 1520 1521 /** 1522 * Set the rounding mode. This has no effect unless the rounding 1523 * increment is greater than zero. 1524 * @param roundingMode A rounding mode 1525 */ 1526 void NumberFormat::setRoundingMode(NumberFormat::ERoundingMode /*roundingMode*/) { 1527 // No-op ICU4J throws an exception, and we can't change this API. 1528 } 1529 1530 U_NAMESPACE_END 1531 1532 #endif /* #if !UCONFIG_NO_FORMATTING */ 1533 1534 //eof 1535