1/* 2******************************************************************************* 3* Copyright (C) 1997-2014, International Business Machines Corporation and * 4* others. All Rights Reserved. * 5******************************************************************************* 6* 7* File DECIMFMT.CPP 8* 9* Modification History: 10* 11* Date Name Description 12* 02/19/97 aliu Converted from java. 13* 03/20/97 clhuang Implemented with new APIs. 14* 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it. 15* 04/3/97 aliu Rewrote parsing and formatting completely, and 16* cleaned up and debugged. Actually works now. 17* Implemented NAN and INF handling, for both parsing 18* and formatting. Extensive testing & debugging. 19* 04/10/97 aliu Modified to compile on AIX. 20* 04/16/97 aliu Rewrote to use DigitList, which has been resurrected. 21* Changed DigitCount to int per code review. 22* 07/09/97 helena Made ParsePosition into a class. 23* 08/26/97 aliu Extensive changes to applyPattern; completely 24* rewritten from the Java. 25* 09/09/97 aliu Ported over support for exponential formats. 26* 07/20/98 stephen JDK 1.2 sync up. 27* Various instances of '0' replaced with 'NULL' 28* Check for grouping size in subFormat() 29* Brought subParse() in line with Java 1.2 30* Added method appendAffix() 31* 08/24/1998 srl Removed Mutex calls. This is not a thread safe class! 32* 02/22/99 stephen Removed character literals for EBCDIC safety 33* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes 34* 06/28/99 stephen Fixed bugs in toPattern(). 35* 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad, 36* fPadPosition 37******************************************************************************** 38*/ 39 40#include "unicode/utypes.h" 41 42#if !UCONFIG_NO_FORMATTING 43 44#include "fphdlimp.h" 45#include "unicode/decimfmt.h" 46#include "unicode/choicfmt.h" 47#include "unicode/ucurr.h" 48#include "unicode/ustring.h" 49#include "unicode/dcfmtsym.h" 50#include "unicode/ures.h" 51#include "unicode/uchar.h" 52#include "unicode/uniset.h" 53#include "unicode/curramt.h" 54#include "unicode/currpinf.h" 55#include "unicode/plurrule.h" 56#include "unicode/utf16.h" 57#include "unicode/numsys.h" 58#include "unicode/localpointer.h" 59#include "uresimp.h" 60#include "ucurrimp.h" 61#include "charstr.h" 62#include "cmemory.h" 63#include "patternprops.h" 64#include "digitlst.h" 65#include "cstring.h" 66#include "umutex.h" 67#include "uassert.h" 68#include "putilimp.h" 69#include <math.h> 70#include "hash.h" 71#include "decfmtst.h" 72#include "dcfmtimp.h" 73#include "plurrule_impl.h" 74#include "decimalformatpattern.h" 75 76/* 77 * On certain platforms, round is a macro defined in math.h 78 * This undefine is to avoid conflict between the macro and 79 * the function defined below. 80 */ 81#ifdef round 82#undef round 83#endif 84 85 86U_NAMESPACE_BEGIN 87 88#ifdef FMT_DEBUG 89#include <stdio.h> 90static void _debugout(const char *f, int l, const UnicodeString& s) { 91 char buf[2000]; 92 s.extract((int32_t) 0, s.length(), buf, "utf-8"); 93 printf("%s:%d: %s\n", f,l, buf); 94} 95#define debugout(x) _debugout(__FILE__,__LINE__,x) 96#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); 97static const UnicodeString dbg_null("<NULL>",""); 98#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) 99#else 100#define debugout(x) 101#define debug(x) 102#endif 103 104 105 106/* == Fastpath calculation. == 107 */ 108#if UCONFIG_FORMAT_FASTPATHS_49 109inline DecimalFormatInternal& internalData(uint8_t *reserved) { 110 return *reinterpret_cast<DecimalFormatInternal*>(reserved); 111} 112inline const DecimalFormatInternal& internalData(const uint8_t *reserved) { 113 return *reinterpret_cast<const DecimalFormatInternal*>(reserved); 114} 115#else 116#endif 117 118/* For currency parsing purose, 119 * Need to remember all prefix patterns and suffix patterns of 120 * every currency format pattern, 121 * including the pattern of default currecny style 122 * and plural currency style. And the patterns are set through applyPattern. 123 */ 124struct AffixPatternsForCurrency : public UMemory { 125 // negative prefix pattern 126 UnicodeString negPrefixPatternForCurrency; 127 // negative suffix pattern 128 UnicodeString negSuffixPatternForCurrency; 129 // positive prefix pattern 130 UnicodeString posPrefixPatternForCurrency; 131 // positive suffix pattern 132 UnicodeString posSuffixPatternForCurrency; 133 int8_t patternType; 134 135 AffixPatternsForCurrency(const UnicodeString& negPrefix, 136 const UnicodeString& negSuffix, 137 const UnicodeString& posPrefix, 138 const UnicodeString& posSuffix, 139 int8_t type) { 140 negPrefixPatternForCurrency = negPrefix; 141 negSuffixPatternForCurrency = negSuffix; 142 posPrefixPatternForCurrency = posPrefix; 143 posSuffixPatternForCurrency = posSuffix; 144 patternType = type; 145 } 146#ifdef FMT_DEBUG 147 void dump() const { 148 debugout( UnicodeString("AffixPatternsForCurrency( -=\"") + 149 negPrefixPatternForCurrency + (UnicodeString)"\"/\"" + 150 negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" + 151 posPrefixPatternForCurrency + (UnicodeString)"\"/\"" + 152 posSuffixPatternForCurrency + (UnicodeString)"\" )"); 153 } 154#endif 155}; 156 157/* affix for currency formatting when the currency sign in the pattern 158 * equals to 3, such as the pattern contains 3 currency sign or 159 * the formatter style is currency plural format style. 160 */ 161struct AffixesForCurrency : public UMemory { 162 // negative prefix 163 UnicodeString negPrefixForCurrency; 164 // negative suffix 165 UnicodeString negSuffixForCurrency; 166 // positive prefix 167 UnicodeString posPrefixForCurrency; 168 // positive suffix 169 UnicodeString posSuffixForCurrency; 170 171 int32_t formatWidth; 172 173 AffixesForCurrency(const UnicodeString& negPrefix, 174 const UnicodeString& negSuffix, 175 const UnicodeString& posPrefix, 176 const UnicodeString& posSuffix) { 177 negPrefixForCurrency = negPrefix; 178 negSuffixForCurrency = negSuffix; 179 posPrefixForCurrency = posPrefix; 180 posSuffixForCurrency = posSuffix; 181 } 182#ifdef FMT_DEBUG 183 void dump() const { 184 debugout( UnicodeString("AffixesForCurrency( -=\"") + 185 negPrefixForCurrency + (UnicodeString)"\"/\"" + 186 negSuffixForCurrency + (UnicodeString)"\" +=\"" + 187 posPrefixForCurrency + (UnicodeString)"\"/\"" + 188 posSuffixForCurrency + (UnicodeString)"\" )"); 189 } 190#endif 191}; 192 193U_CDECL_BEGIN 194 195/** 196 * @internal ICU 4.2 197 */ 198static UBool U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2); 199 200/** 201 * @internal ICU 4.2 202 */ 203static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2); 204 205 206static UBool 207U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2) { 208 const AffixesForCurrency* affix_1 = 209 (AffixesForCurrency*)val1.pointer; 210 const AffixesForCurrency* affix_2 = 211 (AffixesForCurrency*)val2.pointer; 212 return affix_1->negPrefixForCurrency == affix_2->negPrefixForCurrency && 213 affix_1->negSuffixForCurrency == affix_2->negSuffixForCurrency && 214 affix_1->posPrefixForCurrency == affix_2->posPrefixForCurrency && 215 affix_1->posSuffixForCurrency == affix_2->posSuffixForCurrency; 216} 217 218 219static UBool 220U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) { 221 const AffixPatternsForCurrency* affix_1 = 222 (AffixPatternsForCurrency*)val1.pointer; 223 const AffixPatternsForCurrency* affix_2 = 224 (AffixPatternsForCurrency*)val2.pointer; 225 return affix_1->negPrefixPatternForCurrency == 226 affix_2->negPrefixPatternForCurrency && 227 affix_1->negSuffixPatternForCurrency == 228 affix_2->negSuffixPatternForCurrency && 229 affix_1->posPrefixPatternForCurrency == 230 affix_2->posPrefixPatternForCurrency && 231 affix_1->posSuffixPatternForCurrency == 232 affix_2->posSuffixPatternForCurrency && 233 affix_1->patternType == affix_2->patternType; 234} 235 236U_CDECL_END 237 238 239 240 241// ***************************************************************************** 242// class DecimalFormat 243// ***************************************************************************** 244 245UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat) 246 247// Constants for characters used in programmatic (unlocalized) patterns. 248#define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ 249#define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ 250#define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ 251#define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ 252#define kPatternPerMill ((UChar)0x2030) 253#define kPatternPercent ((UChar)0x0025) /*'%'*/ 254#define kPatternDigit ((UChar)0x0023) /*'#'*/ 255#define kPatternSeparator ((UChar)0x003B) /*';'*/ 256#define kPatternExponent ((UChar)0x0045) /*'E'*/ 257#define kPatternPlus ((UChar)0x002B) /*'+'*/ 258#define kPatternMinus ((UChar)0x002D) /*'-'*/ 259#define kPatternPadEscape ((UChar)0x002A) /*'*'*/ 260#define kQuote ((UChar)0x0027) /*'\''*/ 261/** 262 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It 263 * is used in patterns and substitued with either the currency symbol, 264 * or if it is doubled, with the international currency symbol. If the 265 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is 266 * replaced with the monetary decimal separator. 267 */ 268#define kCurrencySign ((UChar)0x00A4) 269#define kDefaultPad ((UChar)0x0020) /* */ 270 271const int32_t DecimalFormat::kDoubleIntegerDigits = 309; 272const int32_t DecimalFormat::kDoubleFractionDigits = 340; 273 274const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8; 275 276/** 277 * These are the tags we expect to see in normal resource bundle files associated 278 * with a locale. 279 */ 280const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used 281static const char fgNumberElements[]="NumberElements"; 282static const char fgLatn[]="latn"; 283static const char fgPatterns[]="patterns"; 284static const char fgDecimalFormat[]="decimalFormat"; 285static const char fgCurrencyFormat[]="currencyFormat"; 286 287static const UChar fgTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0}; 288 289inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; } 290inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; } 291 292static void copyString(const UnicodeString& src, UBool isBogus, UnicodeString *& dest, UErrorCode &status) { 293 if (U_FAILURE(status)) { 294 return; 295 } 296 if (isBogus) { 297 delete dest; 298 dest = NULL; 299 } else { 300 if (dest != NULL) { 301 *dest = src; 302 } else { 303 dest = new UnicodeString(src); 304 if (dest == NULL) { 305 status = U_MEMORY_ALLOCATION_ERROR; 306 return; 307 } 308 } 309 } 310} 311 312 313//------------------------------------------------------------------------------ 314// Constructs a DecimalFormat instance in the default locale. 315 316DecimalFormat::DecimalFormat(UErrorCode& status) { 317 init(); 318 UParseError parseError; 319 construct(status, parseError); 320} 321 322//------------------------------------------------------------------------------ 323// Constructs a DecimalFormat instance with the specified number format 324// pattern in the default locale. 325 326DecimalFormat::DecimalFormat(const UnicodeString& pattern, 327 UErrorCode& status) { 328 init(); 329 UParseError parseError; 330 construct(status, parseError, &pattern); 331} 332 333//------------------------------------------------------------------------------ 334// Constructs a DecimalFormat instance with the specified number format 335// pattern and the number format symbols in the default locale. The 336// created instance owns the symbols. 337 338DecimalFormat::DecimalFormat(const UnicodeString& pattern, 339 DecimalFormatSymbols* symbolsToAdopt, 340 UErrorCode& status) { 341 init(); 342 UParseError parseError; 343 if (symbolsToAdopt == NULL) 344 status = U_ILLEGAL_ARGUMENT_ERROR; 345 construct(status, parseError, &pattern, symbolsToAdopt); 346} 347 348DecimalFormat::DecimalFormat( const UnicodeString& pattern, 349 DecimalFormatSymbols* symbolsToAdopt, 350 UParseError& parseErr, 351 UErrorCode& status) { 352 init(); 353 if (symbolsToAdopt == NULL) 354 status = U_ILLEGAL_ARGUMENT_ERROR; 355 construct(status,parseErr, &pattern, symbolsToAdopt); 356} 357 358//------------------------------------------------------------------------------ 359// Constructs a DecimalFormat instance with the specified number format 360// pattern and the number format symbols in the default locale. The 361// created instance owns the clone of the symbols. 362 363DecimalFormat::DecimalFormat(const UnicodeString& pattern, 364 const DecimalFormatSymbols& symbols, 365 UErrorCode& status) { 366 init(); 367 UParseError parseError; 368 construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols)); 369} 370 371//------------------------------------------------------------------------------ 372// Constructs a DecimalFormat instance with the specified number format 373// pattern, the number format symbols, and the number format style. 374// The created instance owns the clone of the symbols. 375 376DecimalFormat::DecimalFormat(const UnicodeString& pattern, 377 DecimalFormatSymbols* symbolsToAdopt, 378 UNumberFormatStyle style, 379 UErrorCode& status) { 380 init(); 381 fStyle = style; 382 UParseError parseError; 383 construct(status, parseError, &pattern, symbolsToAdopt); 384} 385 386//----------------------------------------------------------------------------- 387// Common DecimalFormat initialization. 388// Put all fields of an uninitialized object into a known state. 389// Common code, shared by all constructors. 390// Can not fail. Leave the object in good enough shape that the destructor 391// or assignment operator can run successfully. 392void 393DecimalFormat::init() { 394 fPosPrefixPattern = 0; 395 fPosSuffixPattern = 0; 396 fNegPrefixPattern = 0; 397 fNegSuffixPattern = 0; 398 fCurrencyChoice = 0; 399 fMultiplier = NULL; 400 fScale = 0; 401 fGroupingSize = 0; 402 fGroupingSize2 = 0; 403 fDecimalSeparatorAlwaysShown = FALSE; 404 fSymbols = NULL; 405 fUseSignificantDigits = FALSE; 406 fMinSignificantDigits = 1; 407 fMaxSignificantDigits = 6; 408 fUseExponentialNotation = FALSE; 409 fMinExponentDigits = 0; 410 fExponentSignAlwaysShown = FALSE; 411 fBoolFlags.clear(); 412 fRoundingIncrement = 0; 413 fRoundingMode = kRoundHalfEven; 414 fPad = 0; 415 fFormatWidth = 0; 416 fPadPosition = kPadBeforePrefix; 417 fStyle = UNUM_DECIMAL; 418 fCurrencySignCount = fgCurrencySignCountZero; 419 fAffixPatternsForCurrency = NULL; 420 fAffixesForCurrency = NULL; 421 fPluralAffixesForCurrency = NULL; 422 fCurrencyPluralInfo = NULL; 423#if UCONFIG_HAVE_PARSEALLINPUT 424 fParseAllInput = UNUM_MAYBE; 425#endif 426 427#if UCONFIG_FORMAT_FASTPATHS_49 428 DecimalFormatInternal &data = internalData(fReserved); 429 data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later. 430 data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later. 431#endif 432 fStaticSets = NULL; 433} 434 435//------------------------------------------------------------------------------ 436// Constructs a DecimalFormat instance with the specified number format 437// pattern and the number format symbols in the desired locale. The 438// created instance owns the symbols. 439 440void 441DecimalFormat::construct(UErrorCode& status, 442 UParseError& parseErr, 443 const UnicodeString* pattern, 444 DecimalFormatSymbols* symbolsToAdopt) 445{ 446 fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!! 447 fRoundingIncrement = NULL; 448 fRoundingMode = kRoundHalfEven; 449 fPad = kPatternPadEscape; 450 fPadPosition = kPadBeforePrefix; 451 if (U_FAILURE(status)) 452 return; 453 454 fPosPrefixPattern = fPosSuffixPattern = NULL; 455 fNegPrefixPattern = fNegSuffixPattern = NULL; 456 setMultiplier(1); 457 fGroupingSize = 3; 458 fGroupingSize2 = 0; 459 fDecimalSeparatorAlwaysShown = FALSE; 460 fUseExponentialNotation = FALSE; 461 fMinExponentDigits = 0; 462 463 if (fSymbols == NULL) 464 { 465 fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status); 466 if (fSymbols == 0) { 467 status = U_MEMORY_ALLOCATION_ERROR; 468 return; 469 } 470 } 471 fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 472 if (U_FAILURE(status)) { 473 return; 474 } 475 UErrorCode nsStatus = U_ZERO_ERROR; 476 NumberingSystem *ns = NumberingSystem::createInstance(nsStatus); 477 if (U_FAILURE(nsStatus)) { 478 status = nsStatus; 479 return; 480 } 481 482 UnicodeString str; 483 // Uses the default locale's number format pattern if there isn't 484 // one specified. 485 if (pattern == NULL) 486 { 487 int32_t len = 0; 488 UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status); 489 490 UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status); 491 resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status); 492 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 493 const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 494 if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) { 495 status = U_ZERO_ERROR; 496 resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status); 497 resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status); 498 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 499 resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 500 } 501 str.setTo(TRUE, resStr, len); 502 pattern = &str; 503 ures_close(resource); 504 ures_close(top); 505 } 506 507 delete ns; 508 509 if (U_FAILURE(status)) 510 { 511 return; 512 } 513 514 if (pattern->indexOf((UChar)kCurrencySign) >= 0) { 515 // If it looks like we are going to use a currency pattern 516 // then do the time consuming lookup. 517 setCurrencyForSymbols(); 518 } else { 519 setCurrencyInternally(NULL, status); 520 } 521 522 const UnicodeString* patternUsed; 523 UnicodeString currencyPluralPatternForOther; 524 // apply pattern 525 if (fStyle == UNUM_CURRENCY_PLURAL) { 526 fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status); 527 if (U_FAILURE(status)) { 528 return; 529 } 530 531 // the pattern used in format is not fixed until formatting, 532 // in which, the number is known and 533 // will be used to pick the right pattern based on plural count. 534 // Here, set the pattern as the pattern of plural count == "other". 535 // For most locale, the patterns are probably the same for all 536 // plural count. If not, the right pattern need to be re-applied 537 // during format. 538 fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther); 539 patternUsed = ¤cyPluralPatternForOther; 540 // TODO: not needed? 541 setCurrencyForSymbols(); 542 543 } else { 544 patternUsed = pattern; 545 } 546 547 if (patternUsed->indexOf(kCurrencySign) != -1) { 548 // initialize for currency, not only for plural format, 549 // but also for mix parsing 550 if (fCurrencyPluralInfo == NULL) { 551 fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status); 552 if (U_FAILURE(status)) { 553 return; 554 } 555 } 556 // need it for mix parsing 557 setupCurrencyAffixPatterns(status); 558 // expanded affixes for plural names 559 if (patternUsed->indexOf(fgTripleCurrencySign, 3, 0) != -1) { 560 setupCurrencyAffixes(*patternUsed, TRUE, TRUE, status); 561 } 562 } 563 564 applyPatternWithoutExpandAffix(*patternUsed,FALSE, parseErr, status); 565 566 // expand affixes 567 if (fCurrencySignCount != fgCurrencySignCountInPluralFormat) { 568 expandAffixAdjustWidth(NULL); 569 } 570 571 // If it was a currency format, apply the appropriate rounding by 572 // resetting the currency. NOTE: this copies fCurrency on top of itself. 573 if (fCurrencySignCount != fgCurrencySignCountZero) { 574 setCurrencyInternally(getCurrency(), status); 575 } 576#if UCONFIG_FORMAT_FASTPATHS_49 577 DecimalFormatInternal &data = internalData(fReserved); 578 data.fFastFormatStatus = kFastpathNO; // allow it to be calculated 579 data.fFastParseStatus = kFastpathNO; // allow it to be calculated 580 handleChanged(); 581#endif 582} 583 584 585void 586DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) { 587 if (U_FAILURE(status)) { 588 return; 589 } 590 UParseError parseErr; 591 fAffixPatternsForCurrency = initHashForAffixPattern(status); 592 if (U_FAILURE(status)) { 593 return; 594 } 595 596 NumberingSystem *ns = NumberingSystem::createInstance(fSymbols->getLocale(),status); 597 if (U_FAILURE(status)) { 598 return; 599 } 600 601 // Save the default currency patterns of this locale. 602 // Here, chose onlyApplyPatternWithoutExpandAffix without 603 // expanding the affix patterns into affixes. 604 UnicodeString currencyPattern; 605 UErrorCode error = U_ZERO_ERROR; 606 607 UResourceBundle *resource = ures_open(NULL, fSymbols->getLocale().getName(), &error); 608 UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error); 609 resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error); 610 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); 611 int32_t patLen = 0; 612 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 613 if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) { 614 error = U_ZERO_ERROR; 615 resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error); 616 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); 617 patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 618 } 619 ures_close(numElements); 620 ures_close(resource); 621 delete ns; 622 623 if (U_SUCCESS(error)) { 624 applyPatternWithoutExpandAffix(UnicodeString(patResStr, patLen), false, 625 parseErr, status); 626 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 627 *fNegPrefixPattern, 628 *fNegSuffixPattern, 629 *fPosPrefixPattern, 630 *fPosSuffixPattern, 631 UCURR_SYMBOL_NAME); 632 fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status); 633 } 634 635 // save the unique currency plural patterns of this locale. 636 Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern; 637 const UHashElement* element = NULL; 638 int32_t pos = -1; 639 Hashtable pluralPatternSet; 640 while ((element = pluralPtn->nextElement(pos)) != NULL) { 641 const UHashTok valueTok = element->value; 642 const UnicodeString* value = (UnicodeString*)valueTok.pointer; 643 const UHashTok keyTok = element->key; 644 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 645 if (pluralPatternSet.geti(*value) != 1) { 646 pluralPatternSet.puti(*value, 1, status); 647 applyPatternWithoutExpandAffix(*value, false, parseErr, status); 648 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 649 *fNegPrefixPattern, 650 *fNegSuffixPattern, 651 *fPosPrefixPattern, 652 *fPosSuffixPattern, 653 UCURR_LONG_NAME); 654 fAffixPatternsForCurrency->put(*key, affixPtn, status); 655 } 656 } 657} 658 659 660void 661DecimalFormat::setupCurrencyAffixes(const UnicodeString& pattern, 662 UBool setupForCurrentPattern, 663 UBool setupForPluralPattern, 664 UErrorCode& status) { 665 if (U_FAILURE(status)) { 666 return; 667 } 668 UParseError parseErr; 669 if (setupForCurrentPattern) { 670 if (fAffixesForCurrency) { 671 deleteHashForAffix(fAffixesForCurrency); 672 } 673 fAffixesForCurrency = initHashForAffix(status); 674 if (U_SUCCESS(status)) { 675 applyPatternWithoutExpandAffix(pattern, false, parseErr, status); 676 const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules(); 677 StringEnumeration* keywords = pluralRules->getKeywords(status); 678 if (U_SUCCESS(status)) { 679 const UnicodeString* pluralCount; 680 while ((pluralCount = keywords->snext(status)) != NULL) { 681 if ( U_SUCCESS(status) ) { 682 expandAffixAdjustWidth(pluralCount); 683 AffixesForCurrency* affix = new AffixesForCurrency( 684 fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix); 685 fAffixesForCurrency->put(*pluralCount, affix, status); 686 } 687 } 688 } 689 delete keywords; 690 } 691 } 692 693 if (U_FAILURE(status)) { 694 return; 695 } 696 697 if (setupForPluralPattern) { 698 if (fPluralAffixesForCurrency) { 699 deleteHashForAffix(fPluralAffixesForCurrency); 700 } 701 fPluralAffixesForCurrency = initHashForAffix(status); 702 if (U_SUCCESS(status)) { 703 const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules(); 704 StringEnumeration* keywords = pluralRules->getKeywords(status); 705 if (U_SUCCESS(status)) { 706 const UnicodeString* pluralCount; 707 while ((pluralCount = keywords->snext(status)) != NULL) { 708 if ( U_SUCCESS(status) ) { 709 UnicodeString ptn; 710 fCurrencyPluralInfo->getCurrencyPluralPattern(*pluralCount, ptn); 711 applyPatternInternally(*pluralCount, ptn, false, parseErr, status); 712 AffixesForCurrency* affix = new AffixesForCurrency( 713 fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix); 714 fPluralAffixesForCurrency->put(*pluralCount, affix, status); 715 } 716 } 717 } 718 delete keywords; 719 } 720 } 721} 722 723 724//------------------------------------------------------------------------------ 725 726DecimalFormat::~DecimalFormat() 727{ 728 delete fPosPrefixPattern; 729 delete fPosSuffixPattern; 730 delete fNegPrefixPattern; 731 delete fNegSuffixPattern; 732 delete fCurrencyChoice; 733 delete fMultiplier; 734 delete fSymbols; 735 delete fRoundingIncrement; 736 deleteHashForAffixPattern(); 737 deleteHashForAffix(fAffixesForCurrency); 738 deleteHashForAffix(fPluralAffixesForCurrency); 739 delete fCurrencyPluralInfo; 740} 741 742//------------------------------------------------------------------------------ 743// copy constructor 744 745DecimalFormat::DecimalFormat(const DecimalFormat &source) : 746 NumberFormat(source) { 747 init(); 748 *this = source; 749} 750 751//------------------------------------------------------------------------------ 752// assignment operator 753 754template <class T> 755static void _copy_ptr(T** pdest, const T* source) { 756 if (source == NULL) { 757 delete *pdest; 758 *pdest = NULL; 759 } else if (*pdest == NULL) { 760 *pdest = new T(*source); 761 } else { 762 **pdest = *source; 763 } 764} 765 766template <class T> 767static void _clone_ptr(T** pdest, const T* source) { 768 delete *pdest; 769 if (source == NULL) { 770 *pdest = NULL; 771 } else { 772 *pdest = static_cast<T*>(source->clone()); 773 } 774} 775 776DecimalFormat& 777DecimalFormat::operator=(const DecimalFormat& rhs) 778{ 779 if(this != &rhs) { 780 UErrorCode status = U_ZERO_ERROR; 781 NumberFormat::operator=(rhs); 782 fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 783 fPositivePrefix = rhs.fPositivePrefix; 784 fPositiveSuffix = rhs.fPositiveSuffix; 785 fNegativePrefix = rhs.fNegativePrefix; 786 fNegativeSuffix = rhs.fNegativeSuffix; 787 _copy_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern); 788 _copy_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern); 789 _copy_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern); 790 _copy_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern); 791 _clone_ptr(&fCurrencyChoice, rhs.fCurrencyChoice); 792 setRoundingIncrement(rhs.getRoundingIncrement()); 793 fRoundingMode = rhs.fRoundingMode; 794 setMultiplier(rhs.getMultiplier()); 795 fGroupingSize = rhs.fGroupingSize; 796 fGroupingSize2 = rhs.fGroupingSize2; 797 fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown; 798 _copy_ptr(&fSymbols, rhs.fSymbols); 799 fUseExponentialNotation = rhs.fUseExponentialNotation; 800 fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown; 801 fBoolFlags = rhs.fBoolFlags; 802 /*Bertrand A. D. Update 98.03.17*/ 803 fCurrencySignCount = rhs.fCurrencySignCount; 804 /*end of Update*/ 805 fMinExponentDigits = rhs.fMinExponentDigits; 806 807 /* sfb 990629 */ 808 fFormatWidth = rhs.fFormatWidth; 809 fPad = rhs.fPad; 810 fPadPosition = rhs.fPadPosition; 811 /* end sfb */ 812 fMinSignificantDigits = rhs.fMinSignificantDigits; 813 fMaxSignificantDigits = rhs.fMaxSignificantDigits; 814 fUseSignificantDigits = rhs.fUseSignificantDigits; 815 fFormatPattern = rhs.fFormatPattern; 816 fStyle = rhs.fStyle; 817 _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo); 818 deleteHashForAffixPattern(); 819 if (rhs.fAffixPatternsForCurrency) { 820 UErrorCode status = U_ZERO_ERROR; 821 fAffixPatternsForCurrency = initHashForAffixPattern(status); 822 copyHashForAffixPattern(rhs.fAffixPatternsForCurrency, 823 fAffixPatternsForCurrency, status); 824 } 825 deleteHashForAffix(fAffixesForCurrency); 826 if (rhs.fAffixesForCurrency) { 827 UErrorCode status = U_ZERO_ERROR; 828 fAffixesForCurrency = initHashForAffixPattern(status); 829 copyHashForAffix(rhs.fAffixesForCurrency, fAffixesForCurrency, status); 830 } 831 deleteHashForAffix(fPluralAffixesForCurrency); 832 if (rhs.fPluralAffixesForCurrency) { 833 UErrorCode status = U_ZERO_ERROR; 834 fPluralAffixesForCurrency = initHashForAffixPattern(status); 835 copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCurrency, status); 836 } 837#if UCONFIG_FORMAT_FASTPATHS_49 838 DecimalFormatInternal &data = internalData(fReserved); 839 const DecimalFormatInternal &rhsData = internalData(rhs.fReserved); 840 data = rhsData; 841#endif 842 } 843 return *this; 844} 845 846//------------------------------------------------------------------------------ 847 848UBool 849DecimalFormat::operator==(const Format& that) const 850{ 851 if (this == &that) 852 return TRUE; 853 854 // NumberFormat::operator== guarantees this cast is safe 855 const DecimalFormat* other = (DecimalFormat*)&that; 856 857#ifdef FMT_DEBUG 858 // This code makes it easy to determine why two format objects that should 859 // be equal aren't. 860 UBool first = TRUE; 861 if (!NumberFormat::operator==(that)) { 862 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 863 debug("NumberFormat::!="); 864 } else { 865 if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null 866 fPositivePrefix == other->fPositivePrefix) 867 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 && 868 *fPosPrefixPattern == *other->fPosPrefixPattern))) { 869 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 870 debug("Pos Prefix !="); 871 } 872 if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null 873 fPositiveSuffix == other->fPositiveSuffix) 874 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 && 875 *fPosSuffixPattern == *other->fPosSuffixPattern))) { 876 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 877 debug("Pos Suffix !="); 878 } 879 if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null 880 fNegativePrefix == other->fNegativePrefix) 881 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 && 882 *fNegPrefixPattern == *other->fNegPrefixPattern))) { 883 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 884 debug("Neg Prefix "); 885 if (fNegPrefixPattern == NULL) { 886 debug("NULL("); 887 debugout(fNegativePrefix); 888 debug(")"); 889 } else { 890 debugout(*fNegPrefixPattern); 891 } 892 debug(" != "); 893 if (other->fNegPrefixPattern == NULL) { 894 debug("NULL("); 895 debugout(other->fNegativePrefix); 896 debug(")"); 897 } else { 898 debugout(*other->fNegPrefixPattern); 899 } 900 } 901 if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null 902 fNegativeSuffix == other->fNegativeSuffix) 903 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 && 904 *fNegSuffixPattern == *other->fNegSuffixPattern))) { 905 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 906 debug("Neg Suffix "); 907 if (fNegSuffixPattern == NULL) { 908 debug("NULL("); 909 debugout(fNegativeSuffix); 910 debug(")"); 911 } else { 912 debugout(*fNegSuffixPattern); 913 } 914 debug(" != "); 915 if (other->fNegSuffixPattern == NULL) { 916 debug("NULL("); 917 debugout(other->fNegativeSuffix); 918 debug(")"); 919 } else { 920 debugout(*other->fNegSuffixPattern); 921 } 922 } 923 if (!((fRoundingIncrement == other->fRoundingIncrement) // both null 924 || (fRoundingIncrement != NULL && 925 other->fRoundingIncrement != NULL && 926 *fRoundingIncrement == *other->fRoundingIncrement))) { 927 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 928 debug("Rounding Increment !="); 929 } 930 if (fRoundingMode != other->fRoundingMode) { 931 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 932 printf("Rounding Mode %d != %d", (int)fRoundingMode, (int)other->fRoundingMode); 933 } 934 if (getMultiplier() != other->getMultiplier()) { 935 if (first) { printf("[ "); first = FALSE; } 936 printf("Multiplier %ld != %ld", getMultiplier(), other->getMultiplier()); 937 } 938 if (fGroupingSize != other->fGroupingSize) { 939 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 940 printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize); 941 } 942 if (fGroupingSize2 != other->fGroupingSize2) { 943 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 944 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGroupingSize2); 945 } 946 if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) { 947 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 948 printf("fDecimalSeparatorAlwaysShown %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown); 949 } 950 if (fUseExponentialNotation != other->fUseExponentialNotation) { 951 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 952 debug("fUseExponentialNotation !="); 953 } 954 if (fUseExponentialNotation && 955 fMinExponentDigits != other->fMinExponentDigits) { 956 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 957 debug("fMinExponentDigits !="); 958 } 959 if (fUseExponentialNotation && 960 fExponentSignAlwaysShown != other->fExponentSignAlwaysShown) { 961 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 962 debug("fExponentSignAlwaysShown !="); 963 } 964 if (fBoolFlags.getAll() != other->fBoolFlags.getAll()) { 965 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 966 debug("fBoolFlags !="); 967 } 968 if (*fSymbols != *(other->fSymbols)) { 969 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 970 debug("Symbols !="); 971 } 972 // TODO Add debug stuff for significant digits here 973 if (fUseSignificantDigits != other->fUseSignificantDigits) { 974 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 975 debug("fUseSignificantDigits !="); 976 } 977 if (fUseSignificantDigits && 978 fMinSignificantDigits != other->fMinSignificantDigits) { 979 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 980 debug("fMinSignificantDigits !="); 981 } 982 if (fUseSignificantDigits && 983 fMaxSignificantDigits != other->fMaxSignificantDigits) { 984 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 985 debug("fMaxSignificantDigits !="); 986 } 987 if (fFormatWidth != other->fFormatWidth) { 988 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 989 debug("fFormatWidth !="); 990 } 991 if (fPad != other->fPad) { 992 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 993 debug("fPad !="); 994 } 995 if (fPadPosition != other->fPadPosition) { 996 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 997 debug("fPadPosition !="); 998 } 999 if (fStyle == UNUM_CURRENCY_PLURAL && 1000 fStyle != other->fStyle) 1001 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1002 debug("fStyle !="); 1003 } 1004 if (fStyle == UNUM_CURRENCY_PLURAL && 1005 fFormatPattern != other->fFormatPattern) { 1006 if (first) { printf("[ "); first = FALSE; } else { printf(", "); } 1007 debug("fFormatPattern !="); 1008 } 1009 1010 if (!first) { printf(" ]"); } 1011 if (fCurrencySignCount != other->fCurrencySignCount) { 1012 debug("fCurrencySignCount !="); 1013 } 1014 if (fCurrencyPluralInfo == other->fCurrencyPluralInfo) { 1015 debug("fCurrencyPluralInfo == "); 1016 if (fCurrencyPluralInfo == NULL) { 1017 debug("fCurrencyPluralInfo == NULL"); 1018 } 1019 } 1020 if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL && 1021 *fCurrencyPluralInfo != *(other->fCurrencyPluralInfo)) { 1022 debug("fCurrencyPluralInfo !="); 1023 } 1024 if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo == NULL || 1025 fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo != NULL) { 1026 debug("fCurrencyPluralInfo one NULL, the other not"); 1027 } 1028 if (fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo == NULL) { 1029 debug("fCurrencyPluralInfo == "); 1030 } 1031 } 1032#endif 1033 1034 return ( 1035 NumberFormat::operator==(that) && 1036 1037 ((fCurrencySignCount == fgCurrencySignCountInPluralFormat) ? 1038 (fAffixPatternsForCurrency->equals(*other->fAffixPatternsForCurrency)) : 1039 (((fPosPrefixPattern == other->fPosPrefixPattern && // both null 1040 fPositivePrefix == other->fPositivePrefix) 1041 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 && 1042 *fPosPrefixPattern == *other->fPosPrefixPattern)) && 1043 ((fPosSuffixPattern == other->fPosSuffixPattern && // both null 1044 fPositiveSuffix == other->fPositiveSuffix) 1045 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 && 1046 *fPosSuffixPattern == *other->fPosSuffixPattern)) && 1047 ((fNegPrefixPattern == other->fNegPrefixPattern && // both null 1048 fNegativePrefix == other->fNegativePrefix) 1049 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 && 1050 *fNegPrefixPattern == *other->fNegPrefixPattern)) && 1051 ((fNegSuffixPattern == other->fNegSuffixPattern && // both null 1052 fNegativeSuffix == other->fNegativeSuffix) 1053 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 && 1054 *fNegSuffixPattern == *other->fNegSuffixPattern)))) && 1055 1056 ((fRoundingIncrement == other->fRoundingIncrement) // both null 1057 || (fRoundingIncrement != NULL && 1058 other->fRoundingIncrement != NULL && 1059 *fRoundingIncrement == *other->fRoundingIncrement)) && 1060 1061 fRoundingMode == other->fRoundingMode && 1062 getMultiplier() == other->getMultiplier() && 1063 fGroupingSize == other->fGroupingSize && 1064 fGroupingSize2 == other->fGroupingSize2 && 1065 fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown && 1066 fUseExponentialNotation == other->fUseExponentialNotation && 1067 1068 (!fUseExponentialNotation || 1069 (fMinExponentDigits == other->fMinExponentDigits && fExponentSignAlwaysShown == other->fExponentSignAlwaysShown)) && 1070 1071 fBoolFlags.getAll() == other->fBoolFlags.getAll() && 1072 *fSymbols == *(other->fSymbols) && 1073 fUseSignificantDigits == other->fUseSignificantDigits && 1074 1075 (!fUseSignificantDigits || 1076 (fMinSignificantDigits == other->fMinSignificantDigits && fMaxSignificantDigits == other->fMaxSignificantDigits)) && 1077 1078 fFormatWidth == other->fFormatWidth && 1079 fPad == other->fPad && 1080 fPadPosition == other->fPadPosition && 1081 1082 (fStyle != UNUM_CURRENCY_PLURAL || 1083 (fStyle == other->fStyle && fFormatPattern == other->fFormatPattern)) && 1084 1085 fCurrencySignCount == other->fCurrencySignCount && 1086 1087 ((fCurrencyPluralInfo == other->fCurrencyPluralInfo && 1088 fCurrencyPluralInfo == NULL) || 1089 (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL && 1090 *fCurrencyPluralInfo == *(other->fCurrencyPluralInfo))) 1091 1092 // depending on other settings we may also need to compare 1093 // fCurrencyChoice (mostly deprecated?), 1094 // fAffixesForCurrency & fPluralAffixesForCurrency (only relevant in some cases) 1095 ); 1096} 1097 1098//------------------------------------------------------------------------------ 1099 1100Format* 1101DecimalFormat::clone() const 1102{ 1103 return new DecimalFormat(*this); 1104} 1105 1106 1107FixedDecimal 1108DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const { 1109 FixedDecimal result; 1110 1111 if (U_FAILURE(status)) { 1112 return result; 1113 } 1114 1115 if (uprv_isNaN(number) || uprv_isPositiveInfinity(fabs(number))) { 1116 // For NaN and Infinity the state of the formatter is ignored. 1117 result.init(number); 1118 return result; 1119 } 1120 1121 if (fMultiplier == NULL && fScale == 0 && fRoundingIncrement == 0 && areSignificantDigitsUsed() == FALSE && 1122 result.quickInit(number) && result.visibleDecimalDigitCount <= getMaximumFractionDigits()) { 1123 // Fast Path. Construction of an exact FixedDecimal directly from the double, without passing 1124 // through a DigitList, was successful, and the formatter is doing nothing tricky with rounding. 1125 // printf("getFixedDecimal(%g): taking fast path.\n", number); 1126 result.adjustForMinFractionDigits(getMinimumFractionDigits()); 1127 } else { 1128 // Slow path. Create a DigitList, and have this formatter round it according to the 1129 // requirements of the format, and fill the fixedDecimal from that. 1130 DigitList digits; 1131 digits.set(number); 1132 result = getFixedDecimal(digits, status); 1133 } 1134 return result; 1135} 1136 1137// MSVC optimizer bug? 1138// turn off optimization as it causes different behavior in the int64->double->int64 conversion 1139#if defined (_MSC_VER) 1140#pragma optimize ( "", off ) 1141#endif 1142FixedDecimal 1143DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const { 1144 if (U_FAILURE(status)) { 1145 return FixedDecimal(); 1146 } 1147 if (!number.isNumeric()) { 1148 status = U_ILLEGAL_ARGUMENT_ERROR; 1149 return FixedDecimal(); 1150 } 1151 1152 DigitList *dl = number.getDigitList(); 1153 if (dl != NULL) { 1154 DigitList clonedDL(*dl); 1155 return getFixedDecimal(clonedDL, status); 1156 } 1157 1158 Formattable::Type type = number.getType(); 1159 if (type == Formattable::kDouble || type == Formattable::kLong) { 1160 return getFixedDecimal(number.getDouble(status), status); 1161 } 1162 1163 if (type == Formattable::kInt64) { 1164 // "volatile" here is a workaround to avoid optimization issues. 1165 volatile double fdv = number.getDouble(status); 1166 // Note: conversion of int64_t -> double rounds with some compilers to 1167 // values beyond what can be represented as a 64 bit int. Subsequent 1168 // testing or conversion with int64_t produces bad results. 1169 // So filter the problematic values, route them to DigitList. 1170 if (fdv != (double)U_INT64_MAX && fdv != (double)U_INT64_MIN && 1171 number.getInt64() == (int64_t)fdv) { 1172 return getFixedDecimal(number.getDouble(status), status); 1173 } 1174 } 1175 1176 // The only case left is type==int64_t, with a value with more digits than a double can represent. 1177 // Any formattable originating as a big decimal will have had a pre-existing digit list. 1178 // Any originating as a double or int32 will have been handled as a double. 1179 1180 U_ASSERT(type == Formattable::kInt64); 1181 DigitList digits; 1182 digits.set(number.getInt64()); 1183 return getFixedDecimal(digits, status); 1184} 1185// end workaround MSVC optimizer bug 1186#if defined (_MSC_VER) 1187#pragma optimize ( "", on ) 1188#endif 1189 1190 1191// Create a fixed decimal from a DigitList. 1192// The digit list may be modified. 1193// Internal function only. 1194FixedDecimal 1195DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const { 1196 // Round the number according to the requirements of this Format. 1197 FixedDecimal result; 1198 _round(number, number, result.isNegative, status); 1199 1200 // The int64_t fields in FixedDecimal can easily overflow. 1201 // In deciding what to discard in this event, consider that fixedDecimal 1202 // is being used only with PluralRules, and those rules mostly look at least significant 1203 // few digits of the integer part, and whether the fraction part is zero or not. 1204 // 1205 // So, in case of overflow when filling in the fields of the FixedDecimal object, 1206 // for the integer part, discard the most significant digits. 1207 // for the fraction part, discard the least significant digits, 1208 // don't truncate the fraction value to zero. 1209 // For simplicity, the int64_t fields are limited to 18 decimal digits, even 1210 // though they could hold most (but not all) 19 digit values. 1211 1212 // Integer Digits. 1213 int32_t di = number.getDecimalAt()-18; // Take at most 18 digits. 1214 if (di < 0) { 1215 di = 0; 1216 } 1217 result.intValue = 0; 1218 for (; di<number.getDecimalAt(); di++) { 1219 result.intValue = result.intValue * 10 + (number.getDigit(di) & 0x0f); 1220 } 1221 if (result.intValue == 0 && number.getDecimalAt()-18 > 0) { 1222 // The number is something like 100000000000000000000000. 1223 // More than 18 digits integer digits, but the least significant 18 are all zero. 1224 // We don't want to return zero as the int part, but want to keep zeros 1225 // for several of the least significant digits. 1226 result.intValue = 100000000000000000LL; 1227 } 1228 1229 // Fraction digits. 1230 result.decimalDigits = result.decimalDigitsWithoutTrailingZeros = result.visibleDecimalDigitCount = 0; 1231 for (di = number.getDecimalAt(); di < number.getCount(); di++) { 1232 result.visibleDecimalDigitCount++; 1233 if (result.decimalDigits < 100000000000000000LL) { 1234 // 9223372036854775807 Largest 64 bit signed integer 1235 int32_t digitVal = number.getDigit(di) & 0x0f; // getDigit() returns a char, '0'-'9'. 1236 result.decimalDigits = result.decimalDigits * 10 + digitVal; 1237 if (digitVal > 0) { 1238 result.decimalDigitsWithoutTrailingZeros = result.decimalDigits; 1239 } 1240 } 1241 } 1242 1243 result.hasIntegerValue = (result.decimalDigits == 0); 1244 1245 // Trailing fraction zeros. The format specification may require more trailing 1246 // zeros than the numeric value. Add any such on now. 1247 1248 int32_t minFractionDigits; 1249 if (areSignificantDigitsUsed()) { 1250 minFractionDigits = getMinimumSignificantDigits() - number.getDecimalAt(); 1251 if (minFractionDigits < 0) { 1252 minFractionDigits = 0; 1253 } 1254 } else { 1255 minFractionDigits = getMinimumFractionDigits(); 1256 } 1257 result.adjustForMinFractionDigits(minFractionDigits); 1258 1259 return result; 1260} 1261 1262 1263//------------------------------------------------------------------------------ 1264 1265UnicodeString& 1266DecimalFormat::format(int32_t number, 1267 UnicodeString& appendTo, 1268 FieldPosition& fieldPosition) const 1269{ 1270 return format((int64_t)number, appendTo, fieldPosition); 1271} 1272 1273UnicodeString& 1274DecimalFormat::format(int32_t number, 1275 UnicodeString& appendTo, 1276 FieldPosition& fieldPosition, 1277 UErrorCode& status) const 1278{ 1279 return format((int64_t)number, appendTo, fieldPosition, status); 1280} 1281 1282UnicodeString& 1283DecimalFormat::format(int32_t number, 1284 UnicodeString& appendTo, 1285 FieldPositionIterator* posIter, 1286 UErrorCode& status) const 1287{ 1288 return format((int64_t)number, appendTo, posIter, status); 1289} 1290 1291 1292#if UCONFIG_FORMAT_FASTPATHS_49 1293void DecimalFormat::handleChanged() { 1294 DecimalFormatInternal &data = internalData(fReserved); 1295 1296 if(data.fFastFormatStatus == kFastpathUNKNOWN || data.fFastParseStatus == kFastpathUNKNOWN) { 1297 return; // still constructing. Wait. 1298 } 1299 1300 data.fFastParseStatus = data.fFastFormatStatus = kFastpathNO; 1301 1302#if UCONFIG_HAVE_PARSEALLINPUT 1303 if(fParseAllInput == UNUM_NO) { 1304 debug("No Parse fastpath: fParseAllInput==UNUM_NO"); 1305 } else 1306#endif 1307 if (fFormatWidth!=0) { 1308 debug("No Parse fastpath: fFormatWidth"); 1309 } else if(fPositivePrefix.length()>0) { 1310 debug("No Parse fastpath: positive prefix"); 1311 } else if(fPositiveSuffix.length()>0) { 1312 debug("No Parse fastpath: positive suffix"); 1313 } else if(fNegativePrefix.length()>1 1314 || ((fNegativePrefix.length()==1) && (fNegativePrefix.charAt(0)!=0x002D))) { 1315 debug("No Parse fastpath: negative prefix that isn't '-'"); 1316 } else if(fNegativeSuffix.length()>0) { 1317 debug("No Parse fastpath: negative suffix"); 1318 } else { 1319 data.fFastParseStatus = kFastpathYES; 1320 debug("parse fastpath: YES"); 1321 } 1322 1323 if (fGroupingSize!=0 && isGroupingUsed()) { 1324 debug("No format fastpath: fGroupingSize!=0 and grouping is used"); 1325#ifdef FMT_DEBUG 1326 printf("groupingsize=%d\n", fGroupingSize); 1327#endif 1328 } else if(fGroupingSize2!=0 && isGroupingUsed()) { 1329 debug("No format fastpath: fGroupingSize2!=0"); 1330 } else if(fUseExponentialNotation) { 1331 debug("No format fastpath: fUseExponentialNotation"); 1332 } else if(fFormatWidth!=0) { 1333 debug("No format fastpath: fFormatWidth!=0"); 1334 } else if(fMinSignificantDigits!=1) { 1335 debug("No format fastpath: fMinSignificantDigits!=1"); 1336 } else if(fMultiplier!=NULL) { 1337 debug("No format fastpath: fMultiplier!=NULL"); 1338 } else if(fScale!=0) { 1339 debug("No format fastpath: fScale!=0"); 1340 } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)) { 1341 debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)"); 1342 } else if(fDecimalSeparatorAlwaysShown) { 1343 debug("No format fastpath: fDecimalSeparatorAlwaysShown"); 1344 } else if(getMinimumFractionDigits()>0) { 1345 debug("No format fastpath: fMinFractionDigits>0"); 1346 } else if(fCurrencySignCount != fgCurrencySignCountZero) { 1347 debug("No format fastpath: fCurrencySignCount != fgCurrencySignCountZero"); 1348 } else if(fRoundingIncrement!=0) { 1349 debug("No format fastpath: fRoundingIncrement!=0"); 1350 } else { 1351 data.fFastFormatStatus = kFastpathYES; 1352 debug("format:kFastpathYES!"); 1353 } 1354 1355 1356} 1357#endif 1358//------------------------------------------------------------------------------ 1359 1360UnicodeString& 1361DecimalFormat::format(int64_t number, 1362 UnicodeString& appendTo, 1363 FieldPosition& fieldPosition) const 1364{ 1365 UErrorCode status = U_ZERO_ERROR; /* ignored */ 1366 FieldPositionOnlyHandler handler(fieldPosition); 1367 return _format(number, appendTo, handler, status); 1368} 1369 1370UnicodeString& 1371DecimalFormat::format(int64_t number, 1372 UnicodeString& appendTo, 1373 FieldPosition& fieldPosition, 1374 UErrorCode& status) const 1375{ 1376 FieldPositionOnlyHandler handler(fieldPosition); 1377 return _format(number, appendTo, handler, status); 1378} 1379 1380UnicodeString& 1381DecimalFormat::format(int64_t number, 1382 UnicodeString& appendTo, 1383 FieldPositionIterator* posIter, 1384 UErrorCode& status) const 1385{ 1386 FieldPositionIteratorHandler handler(posIter, status); 1387 return _format(number, appendTo, handler, status); 1388} 1389 1390UnicodeString& 1391DecimalFormat::_format(int64_t number, 1392 UnicodeString& appendTo, 1393 FieldPositionHandler& handler, 1394 UErrorCode &status) const 1395{ 1396 // Bottleneck function for formatting int64_t 1397 if (U_FAILURE(status)) { 1398 return appendTo; 1399 } 1400 1401#if UCONFIG_FORMAT_FASTPATHS_49 1402 // const UnicodeString *posPrefix = fPosPrefixPattern; 1403 // const UnicodeString *posSuffix = fPosSuffixPattern; 1404 // const UnicodeString *negSuffix = fNegSuffixPattern; 1405 1406 const DecimalFormatInternal &data = internalData(fReserved); 1407 1408#ifdef FMT_DEBUG 1409 data.dump(); 1410 printf("fastpath? [%d]\n", number); 1411#endif 1412 1413 if( data.fFastFormatStatus==kFastpathYES) { 1414 1415#define kZero 0x0030 1416 const int32_t MAX_IDX = MAX_DIGITS+2; 1417 UChar outputStr[MAX_IDX]; 1418 int32_t destIdx = MAX_IDX; 1419 outputStr[--destIdx] = 0; // term 1420 1421 int64_t n = number; 1422 if (number < 1) { 1423 // Negative numbers are slightly larger than positive 1424 // output the first digit (or the leading zero) 1425 outputStr[--destIdx] = (-(n % 10) + kZero); 1426 n /= -10; 1427 } 1428 // get any remaining digits 1429 while (n > 0) { 1430 outputStr[--destIdx] = (n % 10) + kZero; 1431 n /= 10; 1432 } 1433 1434 1435 // Slide the number to the start of the output str 1436 U_ASSERT(destIdx >= 0); 1437 int32_t length = MAX_IDX - destIdx -1; 1438 /*int32_t prefixLen = */ appendAffix(appendTo, number, handler, number<0, TRUE); 1439 int32_t maxIntDig = getMaximumIntegerDigits(); 1440 int32_t destlength = length<=maxIntDig?length:maxIntDig; // dest length pinned to max int digits 1441 1442 if(length>maxIntDig && fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) { 1443 status = U_ILLEGAL_ARGUMENT_ERROR; 1444 } 1445 1446 int32_t prependZero = getMinimumIntegerDigits() - destlength; 1447 1448#ifdef FMT_DEBUG 1449 printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d skip=%d\n", prependZero, length, getMinimumIntegerDigits(), maxIntDig, destlength, length-destlength); 1450#endif 1451 int32_t intBegin = appendTo.length(); 1452 1453 while((prependZero--)>0) { 1454 appendTo.append((UChar)0x0030); // '0' 1455 } 1456 1457 appendTo.append(outputStr+destIdx+ 1458 (length-destlength), // skip any leading digits 1459 destlength); 1460 handler.addAttribute(kIntegerField, intBegin, appendTo.length()); 1461 1462 /*int32_t suffixLen =*/ appendAffix(appendTo, number, handler, number<0, FALSE); 1463 1464 //outputStr[length]=0; 1465 1466#ifdef FMT_DEBUG 1467 printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr+destIdx, length, MAX_IDX, number); 1468#endif 1469 1470#undef kZero 1471 1472 return appendTo; 1473 } // end fastpath 1474#endif 1475 1476 // Else the slow way - via DigitList 1477 DigitList digits; 1478 digits.set(number); 1479 return _format(digits, appendTo, handler, status); 1480} 1481 1482//------------------------------------------------------------------------------ 1483 1484UnicodeString& 1485DecimalFormat::format( double number, 1486 UnicodeString& appendTo, 1487 FieldPosition& fieldPosition) const 1488{ 1489 UErrorCode status = U_ZERO_ERROR; /* ignored */ 1490 FieldPositionOnlyHandler handler(fieldPosition); 1491 return _format(number, appendTo, handler, status); 1492} 1493 1494UnicodeString& 1495DecimalFormat::format( double number, 1496 UnicodeString& appendTo, 1497 FieldPosition& fieldPosition, 1498 UErrorCode& status) const 1499{ 1500 FieldPositionOnlyHandler handler(fieldPosition); 1501 return _format(number, appendTo, handler, status); 1502} 1503 1504UnicodeString& 1505DecimalFormat::format( double number, 1506 UnicodeString& appendTo, 1507 FieldPositionIterator* posIter, 1508 UErrorCode& status) const 1509{ 1510 FieldPositionIteratorHandler handler(posIter, status); 1511 return _format(number, appendTo, handler, status); 1512} 1513 1514UnicodeString& 1515DecimalFormat::_format( double number, 1516 UnicodeString& appendTo, 1517 FieldPositionHandler& handler, 1518 UErrorCode &status) const 1519{ 1520 if (U_FAILURE(status)) { 1521 return appendTo; 1522 } 1523 // Special case for NaN, sets the begin and end index to be the 1524 // the string length of localized name of NaN. 1525 // TODO: let NaNs go through DigitList. 1526 if (uprv_isNaN(number)) 1527 { 1528 int begin = appendTo.length(); 1529 appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 1530 1531 handler.addAttribute(kIntegerField, begin, appendTo.length()); 1532 1533 addPadding(appendTo, handler, 0, 0); 1534 return appendTo; 1535 } 1536 1537 DigitList digits; 1538 digits.set(number); 1539 _format(digits, appendTo, handler, status); 1540 // No way to return status from here. 1541 return appendTo; 1542} 1543 1544//------------------------------------------------------------------------------ 1545 1546 1547UnicodeString& 1548DecimalFormat::format(const StringPiece &number, 1549 UnicodeString &toAppendTo, 1550 FieldPositionIterator *posIter, 1551 UErrorCode &status) const 1552{ 1553#if UCONFIG_FORMAT_FASTPATHS_49 1554 // don't bother if the int64 path is not optimized 1555 int32_t len = number.length(); 1556 1557 if(len>0&&len<10) { /* 10 or more digits may not be an int64 */ 1558 const char *data = number.data(); 1559 int64_t num = 0; 1560 UBool neg = FALSE; 1561 UBool ok = TRUE; 1562 1563 int32_t start = 0; 1564 1565 if(data[start]=='+') { 1566 start++; 1567 } else if(data[start]=='-') { 1568 neg=TRUE; 1569 start++; 1570 } 1571 1572 int32_t place = 1; /* 1, 10, ... */ 1573 for(int32_t i=len-1;i>=start;i--) { 1574 if(data[i]>='0'&&data[i]<='9') { 1575 num+=place*(int64_t)(data[i]-'0'); 1576 } else { 1577 ok=FALSE; 1578 break; 1579 } 1580 place *= 10; 1581 } 1582 1583 if(ok) { 1584 if(neg) { 1585 num = -num;// add minus bit 1586 } 1587 // format as int64_t 1588 return format(num, toAppendTo, posIter, status); 1589 } 1590 // else fall through 1591 } 1592#endif 1593 1594 DigitList dnum; 1595 dnum.set(number, status); 1596 if (U_FAILURE(status)) { 1597 return toAppendTo; 1598 } 1599 FieldPositionIteratorHandler handler(posIter, status); 1600 _format(dnum, toAppendTo, handler, status); 1601 return toAppendTo; 1602} 1603 1604 1605UnicodeString& 1606DecimalFormat::format(const DigitList &number, 1607 UnicodeString &appendTo, 1608 FieldPositionIterator *posIter, 1609 UErrorCode &status) const { 1610 FieldPositionIteratorHandler handler(posIter, status); 1611 _format(number, appendTo, handler, status); 1612 return appendTo; 1613} 1614 1615 1616 1617UnicodeString& 1618DecimalFormat::format(const DigitList &number, 1619 UnicodeString& appendTo, 1620 FieldPosition& pos, 1621 UErrorCode &status) const { 1622 FieldPositionOnlyHandler handler(pos); 1623 _format(number, appendTo, handler, status); 1624 return appendTo; 1625} 1626 1627DigitList& 1628DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& isNegative, UErrorCode &status) const { 1629 if (U_FAILURE(status)) { 1630 return adjustedNum; 1631 } 1632 1633 // note: number and adjustedNum may refer to the same DigitList, in cases where a copy 1634 // is not needed by the caller. 1635 1636 adjustedNum = number; 1637 isNegative = false; 1638 if (number.isNaN()) { 1639 return adjustedNum; 1640 } 1641 1642 // Do this BEFORE checking to see if value is infinite or negative! Sets the 1643 // begin and end index to be length of the string composed of 1644 // localized name of Infinite and the positive/negative localized 1645 // signs. 1646 1647 adjustedNum.setRoundingMode(fRoundingMode); 1648 if (fMultiplier != NULL) { 1649 adjustedNum.mult(*fMultiplier, status); 1650 if (U_FAILURE(status)) { 1651 return adjustedNum; 1652 } 1653 } 1654 1655 if (fScale != 0) { 1656 DigitList ten; 1657 ten.set((int32_t)10); 1658 if (fScale > 0) { 1659 for (int32_t i = fScale ; i > 0 ; i--) { 1660 adjustedNum.mult(ten, status); 1661 if (U_FAILURE(status)) { 1662 return adjustedNum; 1663 } 1664 } 1665 } else { 1666 for (int32_t i = fScale ; i < 0 ; i++) { 1667 adjustedNum.div(ten, status); 1668 if (U_FAILURE(status)) { 1669 return adjustedNum; 1670 } 1671 } 1672 } 1673 } 1674 1675 /* 1676 * Note: sign is important for zero as well as non-zero numbers. 1677 * Proper detection of -0.0 is needed to deal with the 1678 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98. 1679 */ 1680 isNegative = !adjustedNum.isPositive(); 1681 1682 // Apply rounding after multiplier 1683 1684 adjustedNum.fContext.status &= ~DEC_Inexact; 1685 if (fRoundingIncrement != NULL) { 1686 adjustedNum.div(*fRoundingIncrement, status); 1687 adjustedNum.toIntegralValue(); 1688 adjustedNum.mult(*fRoundingIncrement, status); 1689 adjustedNum.trim(); 1690 if (U_FAILURE(status)) { 1691 return adjustedNum; 1692 } 1693 } 1694 if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) { 1695 status = U_FORMAT_INEXACT_ERROR; 1696 return adjustedNum; 1697 } 1698 1699 if (adjustedNum.isInfinite()) { 1700 return adjustedNum; 1701 } 1702 1703 if (fUseExponentialNotation || areSignificantDigitsUsed()) { 1704 int32_t sigDigits = precision(); 1705 if (sigDigits > 0) { 1706 adjustedNum.round(sigDigits); 1707 // Travis Keep (21/2/2014): Calling round on a digitList does not necessarily 1708 // preserve the sign of that digit list. Preserving the sign is especially 1709 // important when formatting -0.0 for instance. Not preserving the sign seems 1710 // like a bug because I cannot think of any case where the sign would actually 1711 // have to change when rounding. For now, we preserve the sign by setting the 1712 // positive attribute directly. 1713 adjustedNum.setPositive(!isNegative); 1714 } 1715 } else { 1716 // Fixed point format. Round to a set number of fraction digits. 1717 int32_t numFractionDigits = precision(); 1718 adjustedNum.roundFixedPoint(numFractionDigits); 1719 } 1720 if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) { 1721 status = U_FORMAT_INEXACT_ERROR; 1722 return adjustedNum; 1723 } 1724 return adjustedNum; 1725} 1726 1727UnicodeString& 1728DecimalFormat::_format(const DigitList &number, 1729 UnicodeString& appendTo, 1730 FieldPositionHandler& handler, 1731 UErrorCode &status) const 1732{ 1733 if (U_FAILURE(status)) { 1734 return appendTo; 1735 } 1736 1737 // Special case for NaN, sets the begin and end index to be the 1738 // the string length of localized name of NaN. 1739 if (number.isNaN()) 1740 { 1741 int begin = appendTo.length(); 1742 appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 1743 1744 handler.addAttribute(kIntegerField, begin, appendTo.length()); 1745 1746 addPadding(appendTo, handler, 0, 0); 1747 return appendTo; 1748 } 1749 1750 DigitList adjustedNum; 1751 UBool isNegative; 1752 _round(number, adjustedNum, isNegative, status); 1753 if (U_FAILURE(status)) { 1754 return appendTo; 1755 } 1756 1757 // Special case for INFINITE, 1758 if (adjustedNum.isInfinite()) { 1759 int32_t prefixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, TRUE); 1760 1761 int begin = appendTo.length(); 1762 appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol); 1763 1764 handler.addAttribute(kIntegerField, begin, appendTo.length()); 1765 1766 int32_t suffixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, FALSE); 1767 1768 addPadding(appendTo, handler, prefixLen, suffixLen); 1769 return appendTo; 1770 } 1771 return subformat(appendTo, handler, adjustedNum, FALSE, status); 1772} 1773 1774/** 1775 * Return true if a grouping separator belongs at the given 1776 * position, based on whether grouping is in use and the values of 1777 * the primary and secondary grouping interval. 1778 * @param pos the number of integer digits to the right of 1779 * the current position. Zero indicates the position after the 1780 * rightmost integer digit. 1781 * @return true if a grouping character belongs at the current 1782 * position. 1783 */ 1784UBool DecimalFormat::isGroupingPosition(int32_t pos) const { 1785 UBool result = FALSE; 1786 if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) { 1787 if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) { 1788 result = ((pos - fGroupingSize) % fGroupingSize2) == 0; 1789 } else { 1790 result = pos % fGroupingSize == 0; 1791 } 1792 } 1793 return result; 1794} 1795 1796//------------------------------------------------------------------------------ 1797 1798/** 1799 * Complete the formatting of a finite number. On entry, the DigitList must 1800 * be filled in with the correct digits. 1801 */ 1802UnicodeString& 1803DecimalFormat::subformat(UnicodeString& appendTo, 1804 FieldPositionHandler& handler, 1805 DigitList& digits, 1806 UBool isInteger, 1807 UErrorCode& status) const 1808{ 1809 // char zero = '0'; 1810 // DigitList returns digits as '0' thru '9', so we will need to 1811 // always need to subtract the character 0 to get the numeric value to use for indexing. 1812 1813 UChar32 localizedDigits[10]; 1814 localizedDigits[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 1815 localizedDigits[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0); 1816 localizedDigits[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0); 1817 localizedDigits[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0); 1818 localizedDigits[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0); 1819 localizedDigits[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0); 1820 localizedDigits[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0); 1821 localizedDigits[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0); 1822 localizedDigits[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0); 1823 localizedDigits[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0); 1824 1825 const UnicodeString *grouping ; 1826 if(fCurrencySignCount == fgCurrencySignCountZero) { 1827 grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); 1828 }else{ 1829 grouping = &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); 1830 } 1831 const UnicodeString *decimal; 1832 if(fCurrencySignCount == fgCurrencySignCountZero) { 1833 decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1834 } else { 1835 decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 1836 } 1837 UBool useSigDig = areSignificantDigitsUsed(); 1838 int32_t maxIntDig = getMaximumIntegerDigits(); 1839 int32_t minIntDig = getMinimumIntegerDigits(); 1840 1841 // Appends the prefix. 1842 double doubleValue = digits.getDouble(); 1843 int32_t prefixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), TRUE); 1844 1845 if (fUseExponentialNotation) 1846 { 1847 int currentLength = appendTo.length(); 1848 int intBegin = currentLength; 1849 int intEnd = -1; 1850 int fracBegin = -1; 1851 1852 int32_t minFracDig = 0; 1853 if (useSigDig) { 1854 maxIntDig = minIntDig = 1; 1855 minFracDig = getMinimumSignificantDigits() - 1; 1856 } else { 1857 minFracDig = getMinimumFractionDigits(); 1858 if (maxIntDig > kMaxScientificIntegerDigits) { 1859 maxIntDig = 1; 1860 if (maxIntDig < minIntDig) { 1861 maxIntDig = minIntDig; 1862 } 1863 } 1864 if (maxIntDig > minIntDig) { 1865 minIntDig = 1; 1866 } 1867 } 1868 1869 // Minimum integer digits are handled in exponential format by 1870 // adjusting the exponent. For example, 0.01234 with 3 minimum 1871 // integer digits is "123.4E-4". 1872 1873 // Maximum integer digits are interpreted as indicating the 1874 // repeating range. This is useful for engineering notation, in 1875 // which the exponent is restricted to a multiple of 3. For 1876 // example, 0.01234 with 3 maximum integer digits is "12.34e-3". 1877 // If maximum integer digits are defined and are larger than 1878 // minimum integer digits, then minimum integer digits are 1879 // ignored. 1880 digits.reduce(); // Removes trailing zero digits. 1881 int32_t exponent = digits.getDecimalAt(); 1882 if (maxIntDig > 1 && maxIntDig != minIntDig) { 1883 // A exponent increment is defined; adjust to it. 1884 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig 1885 : (exponent / maxIntDig) - 1; 1886 exponent *= maxIntDig; 1887 } else { 1888 // No exponent increment is defined; use minimum integer digits. 1889 // If none is specified, as in "#E0", generate 1 integer digit. 1890 exponent -= (minIntDig > 0 || minFracDig > 0) 1891 ? minIntDig : 1; 1892 } 1893 1894 // We now output a minimum number of digits, and more if there 1895 // are more digits, up to the maximum number of digits. We 1896 // place the decimal point after the "integer" digits, which 1897 // are the first (decimalAt - exponent) digits. 1898 int32_t minimumDigits = minIntDig + minFracDig; 1899 // The number of integer digits is handled specially if the number 1900 // is zero, since then there may be no digits. 1901 int32_t integerDigits = digits.isZero() ? minIntDig : 1902 digits.getDecimalAt() - exponent; 1903 int32_t totalDigits = digits.getCount(); 1904 if (minimumDigits > totalDigits) 1905 totalDigits = minimumDigits; 1906 if (integerDigits > totalDigits) 1907 totalDigits = integerDigits; 1908 1909 // totalDigits records total number of digits needs to be processed 1910 int32_t i; 1911 for (i=0; i<totalDigits; ++i) 1912 { 1913 if (i == integerDigits) 1914 { 1915 intEnd = appendTo.length(); 1916 handler.addAttribute(kIntegerField, intBegin, intEnd); 1917 1918 appendTo += *decimal; 1919 1920 fracBegin = appendTo.length(); 1921 handler.addAttribute(kDecimalSeparatorField, fracBegin - 1, fracBegin); 1922 } 1923 // Restores the digit character or pads the buffer with zeros. 1924 UChar32 c = (UChar32)((i < digits.getCount()) ? 1925 localizedDigits[digits.getDigitValue(i)] : 1926 localizedDigits[0]); 1927 appendTo += c; 1928 } 1929 1930 currentLength = appendTo.length(); 1931 1932 if (intEnd < 0) { 1933 handler.addAttribute(kIntegerField, intBegin, currentLength); 1934 } 1935 if (fracBegin > 0) { 1936 handler.addAttribute(kFractionField, fracBegin, currentLength); 1937 } 1938 1939 // The exponent is output using the pattern-specified minimum 1940 // exponent digits. There is no maximum limit to the exponent 1941 // digits, since truncating the exponent would appendTo in an 1942 // unacceptable inaccuracy. 1943 appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 1944 1945 handler.addAttribute(kExponentSymbolField, currentLength, appendTo.length()); 1946 currentLength = appendTo.length(); 1947 1948 // For zero values, we force the exponent to zero. We 1949 // must do this here, and not earlier, because the value 1950 // is used to determine integer digit count above. 1951 if (digits.isZero()) 1952 exponent = 0; 1953 1954 if (exponent < 0) { 1955 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1956 handler.addAttribute(kExponentSignField, currentLength, appendTo.length()); 1957 } else if (fExponentSignAlwaysShown) { 1958 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1959 handler.addAttribute(kExponentSignField, currentLength, appendTo.length()); 1960 } 1961 1962 currentLength = appendTo.length(); 1963 1964 DigitList expDigits; 1965 expDigits.set(exponent); 1966 { 1967 int expDig = fMinExponentDigits; 1968 if (fUseExponentialNotation && expDig < 1) { 1969 expDig = 1; 1970 } 1971 for (i=expDigits.getDecimalAt(); i<expDig; ++i) 1972 appendTo += (localizedDigits[0]); 1973 } 1974 for (i=0; i<expDigits.getDecimalAt(); ++i) 1975 { 1976 UChar32 c = (UChar32)((i < expDigits.getCount()) ? 1977 localizedDigits[expDigits.getDigitValue(i)] : 1978 localizedDigits[0]); 1979 appendTo += c; 1980 } 1981 1982 handler.addAttribute(kExponentField, currentLength, appendTo.length()); 1983 } 1984 else // Not using exponential notation 1985 { 1986 int currentLength = appendTo.length(); 1987 int intBegin = currentLength; 1988 1989 int32_t sigCount = 0; 1990 int32_t minSigDig = getMinimumSignificantDigits(); 1991 int32_t maxSigDig = getMaximumSignificantDigits(); 1992 if (!useSigDig) { 1993 minSigDig = 0; 1994 maxSigDig = INT32_MAX; 1995 } 1996 1997 // Output the integer portion. Here 'count' is the total 1998 // number of integer digits we will display, including both 1999 // leading zeros required to satisfy getMinimumIntegerDigits, 2000 // and actual digits present in the number. 2001 int32_t count = useSigDig ? 2002 _max(1, digits.getDecimalAt()) : minIntDig; 2003 if (digits.getDecimalAt() > 0 && count < digits.getDecimalAt()) { 2004 count = digits.getDecimalAt(); 2005 } 2006 2007 // Handle the case where getMaximumIntegerDigits() is smaller 2008 // than the real number of integer digits. If this is so, we 2009 // output the least significant max integer digits. For example, 2010 // the value 1997 printed with 2 max integer digits is just "97". 2011 2012 int32_t digitIndex = 0; // Index into digitList.fDigits[] 2013 if (count > maxIntDig && maxIntDig >= 0) { 2014 count = maxIntDig; 2015 digitIndex = digits.getDecimalAt() - count; 2016 if(fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) { 2017 status = U_ILLEGAL_ARGUMENT_ERROR; 2018 } 2019 } 2020 2021 int32_t sizeBeforeIntegerPart = appendTo.length(); 2022 2023 int32_t i; 2024 for (i=count-1; i>=0; --i) 2025 { 2026 if (i < digits.getDecimalAt() && digitIndex < digits.getCount() && 2027 sigCount < maxSigDig) { 2028 // Output a real digit 2029 appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)]; 2030 ++sigCount; 2031 } 2032 else 2033 { 2034 // Output a zero (leading or trailing) 2035 appendTo += localizedDigits[0]; 2036 if (sigCount > 0) { 2037 ++sigCount; 2038 } 2039 } 2040 2041 // Output grouping separator if necessary. 2042 if (isGroupingPosition(i)) { 2043 currentLength = appendTo.length(); 2044 appendTo.append(*grouping); 2045 handler.addAttribute(kGroupingSeparatorField, currentLength, appendTo.length()); 2046 } 2047 } 2048 2049 // This handles the special case of formatting 0. For zero only, we count the 2050 // zero to the left of the decimal point as one signficant digit. Ordinarily we 2051 // do not count any leading 0's as significant. If the number we are formatting 2052 // is not zero, then either sigCount or digits.getCount() will be non-zero. 2053 if (sigCount == 0 && digits.getCount() == 0) { 2054 sigCount = 1; 2055 } 2056 2057 // TODO(dlf): this looks like it was a bug, we marked the int field as ending 2058 // before the zero was generated. 2059 // Record field information for caller. 2060 // if (fieldPosition.getField() == NumberFormat::kIntegerField) 2061 // fieldPosition.setEndIndex(appendTo.length()); 2062 2063 // Determine whether or not there are any printable fractional 2064 // digits. If we've used up the digits we know there aren't. 2065 UBool fractionPresent = (!isInteger && digitIndex < digits.getCount()) || 2066 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0)); 2067 2068 // If there is no fraction present, and we haven't printed any 2069 // integer digits, then print a zero. Otherwise we won't print 2070 // _any_ digits, and we won't be able to parse this string. 2071 if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart) 2072 appendTo += localizedDigits[0]; 2073 2074 currentLength = appendTo.length(); 2075 handler.addAttribute(kIntegerField, intBegin, currentLength); 2076 2077 // Output the decimal separator if we always do so. 2078 if (fDecimalSeparatorAlwaysShown || fractionPresent) { 2079 appendTo += *decimal; 2080 handler.addAttribute(kDecimalSeparatorField, currentLength, appendTo.length()); 2081 currentLength = appendTo.length(); 2082 } 2083 2084 int fracBegin = currentLength; 2085 2086 count = useSigDig ? INT32_MAX : getMaximumFractionDigits(); 2087 if (useSigDig && (sigCount == maxSigDig || 2088 (sigCount >= minSigDig && digitIndex == digits.getCount()))) { 2089 count = 0; 2090 } 2091 2092 for (i=0; i < count; ++i) { 2093 // Here is where we escape from the loop. We escape 2094 // if we've output the maximum fraction digits 2095 // (specified in the for expression above). We also 2096 // stop when we've output the minimum digits and 2097 // either: we have an integer, so there is no 2098 // fractional stuff to display, or we're out of 2099 // significant digits. 2100 if (!useSigDig && i >= getMinimumFractionDigits() && 2101 (isInteger || digitIndex >= digits.getCount())) { 2102 break; 2103 } 2104 2105 // Output leading fractional zeros. These are zeros 2106 // that come after the decimal but before any 2107 // significant digits. These are only output if 2108 // abs(number being formatted) < 1.0. 2109 if (-1-i > (digits.getDecimalAt()-1)) { 2110 appendTo += localizedDigits[0]; 2111 continue; 2112 } 2113 2114 // Output a digit, if we have any precision left, or a 2115 // zero if we don't. We don't want to output noise digits. 2116 if (!isInteger && digitIndex < digits.getCount()) { 2117 appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)]; 2118 } else { 2119 appendTo += localizedDigits[0]; 2120 } 2121 2122 // If we reach the maximum number of significant 2123 // digits, or if we output all the real digits and 2124 // reach the minimum, then we are done. 2125 ++sigCount; 2126 if (useSigDig && 2127 (sigCount == maxSigDig || 2128 (digitIndex == digits.getCount() && sigCount >= minSigDig))) { 2129 break; 2130 } 2131 } 2132 2133 handler.addAttribute(kFractionField, fracBegin, appendTo.length()); 2134 } 2135 2136 int32_t suffixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), FALSE); 2137 2138 addPadding(appendTo, handler, prefixLen, suffixLen); 2139 return appendTo; 2140} 2141 2142/** 2143 * Inserts the character fPad as needed to expand result to fFormatWidth. 2144 * @param result the string to be padded 2145 */ 2146void DecimalFormat::addPadding(UnicodeString& appendTo, 2147 FieldPositionHandler& handler, 2148 int32_t prefixLen, 2149 int32_t suffixLen) const 2150{ 2151 if (fFormatWidth > 0) { 2152 int32_t len = fFormatWidth - appendTo.length(); 2153 if (len > 0) { 2154 UnicodeString padding; 2155 for (int32_t i=0; i<len; ++i) { 2156 padding += fPad; 2157 } 2158 switch (fPadPosition) { 2159 case kPadAfterPrefix: 2160 appendTo.insert(prefixLen, padding); 2161 break; 2162 case kPadBeforePrefix: 2163 appendTo.insert(0, padding); 2164 break; 2165 case kPadBeforeSuffix: 2166 appendTo.insert(appendTo.length() - suffixLen, padding); 2167 break; 2168 case kPadAfterSuffix: 2169 appendTo += padding; 2170 break; 2171 } 2172 if (fPadPosition == kPadBeforePrefix || fPadPosition == kPadAfterPrefix) { 2173 handler.shiftLast(len); 2174 } 2175 } 2176 } 2177} 2178 2179//------------------------------------------------------------------------------ 2180 2181void 2182DecimalFormat::parse(const UnicodeString& text, 2183 Formattable& result, 2184 ParsePosition& parsePosition) const { 2185 parse(text, result, parsePosition, NULL); 2186} 2187 2188CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, 2189 ParsePosition& pos) const { 2190 Formattable parseResult; 2191 int32_t start = pos.getIndex(); 2192 UChar curbuf[4] = {}; 2193 parse(text, parseResult, pos, curbuf); 2194 if (pos.getIndex() != start) { 2195 UErrorCode ec = U_ZERO_ERROR; 2196 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec)); 2197 if (U_FAILURE(ec)) { 2198 pos.setIndex(start); // indicate failure 2199 } else { 2200 return currAmt.orphan(); 2201 } 2202 } 2203 return NULL; 2204} 2205 2206/** 2207 * Parses the given text as a number, optionally providing a currency amount. 2208 * @param text the string to parse 2209 * @param result output parameter for the numeric result. 2210 * @param parsePosition input-output position; on input, the 2211 * position within text to match; must have 0 <= pos.getIndex() < 2212 * text.length(); on output, the position after the last matched 2213 * character. If the parse fails, the position in unchanged upon 2214 * output. 2215 * @param currency if non-NULL, it should point to a 4-UChar buffer. 2216 * In this case the text is parsed as a currency format, and the 2217 * ISO 4217 code for the parsed currency is put into the buffer. 2218 * Otherwise the text is parsed as a non-currency format. 2219 */ 2220void DecimalFormat::parse(const UnicodeString& text, 2221 Formattable& result, 2222 ParsePosition& parsePosition, 2223 UChar* currency) const { 2224 int32_t startIdx, backup; 2225 int32_t i = startIdx = backup = parsePosition.getIndex(); 2226 2227 // clear any old contents in the result. In particular, clears any DigitList 2228 // that it may be holding. 2229 result.setLong(0); 2230 if (currency != NULL) { 2231 for (int32_t ci=0; ci<4; ci++) { 2232 currency[ci] = 0; 2233 } 2234 } 2235 2236 // Handle NaN as a special case: 2237 2238 // Skip padding characters, if around prefix 2239 if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix || 2240 fPadPosition == kPadAfterPrefix)) { 2241 i = skipPadding(text, i); 2242 } 2243 2244 if (isLenient()) { 2245 // skip any leading whitespace 2246 i = backup = skipUWhiteSpace(text, i); 2247 } 2248 2249 // If the text is composed of the representation of NaN, returns NaN.length 2250 const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 2251 int32_t nanLen = (text.compare(i, nan->length(), *nan) 2252 ? 0 : nan->length()); 2253 if (nanLen) { 2254 i += nanLen; 2255 if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix || 2256 fPadPosition == kPadAfterSuffix)) { 2257 i = skipPadding(text, i); 2258 } 2259 parsePosition.setIndex(i); 2260 result.setDouble(uprv_getNaN()); 2261 return; 2262 } 2263 2264 // NaN parse failed; start over 2265 i = backup; 2266 parsePosition.setIndex(i); 2267 2268 // status is used to record whether a number is infinite. 2269 UBool status[fgStatusLength]; 2270 2271 DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer 2272 if (digits == NULL) { 2273 return; // no way to report error from here. 2274 } 2275 2276 if (fCurrencySignCount != fgCurrencySignCountZero) { 2277 if (!parseForCurrency(text, parsePosition, *digits, 2278 status, currency)) { 2279 return; 2280 } 2281 } else { 2282 if (!subparse(text, 2283 fNegPrefixPattern, fNegSuffixPattern, 2284 fPosPrefixPattern, fPosSuffixPattern, 2285 FALSE, UCURR_SYMBOL_NAME, 2286 parsePosition, *digits, status, currency)) { 2287 debug("!subparse(...) - rewind"); 2288 parsePosition.setIndex(startIdx); 2289 return; 2290 } 2291 } 2292 2293 // Handle infinity 2294 if (status[fgStatusInfinite]) { 2295 double inf = uprv_getInfinity(); 2296 result.setDouble(digits->isPositive() ? inf : -inf); 2297 // TODO: set the dl to infinity, and let it fall into the code below. 2298 } 2299 2300 else { 2301 2302 if (fMultiplier != NULL) { 2303 UErrorCode ec = U_ZERO_ERROR; 2304 digits->div(*fMultiplier, ec); 2305 } 2306 2307 if (fScale != 0) { 2308 DigitList ten; 2309 ten.set((int32_t)10); 2310 if (fScale > 0) { 2311 for (int32_t i = fScale; i > 0; i--) { 2312 UErrorCode ec = U_ZERO_ERROR; 2313 digits->div(ten,ec); 2314 } 2315 } else { 2316 for (int32_t i = fScale; i < 0; i++) { 2317 UErrorCode ec = U_ZERO_ERROR; 2318 digits->mult(ten,ec); 2319 } 2320 } 2321 } 2322 2323 // Negative zero special case: 2324 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable. 2325 // if not parsing integerOnly, leave as -0, which a double can represent. 2326 if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) { 2327 digits->setPositive(TRUE); 2328 } 2329 result.adoptDigitList(digits); 2330 } 2331} 2332 2333 2334 2335UBool 2336DecimalFormat::parseForCurrency(const UnicodeString& text, 2337 ParsePosition& parsePosition, 2338 DigitList& digits, 2339 UBool* status, 2340 UChar* currency) const { 2341 int origPos = parsePosition.getIndex(); 2342 int maxPosIndex = origPos; 2343 int maxErrorPos = -1; 2344 // First, parse against current pattern. 2345 // Since current pattern could be set by applyPattern(), 2346 // it could be an arbitrary pattern, and it may not be the one 2347 // defined in current locale. 2348 UBool tmpStatus[fgStatusLength]; 2349 ParsePosition tmpPos(origPos); 2350 DigitList tmpDigitList; 2351 UBool found; 2352 if (fStyle == UNUM_CURRENCY_PLURAL) { 2353 found = subparse(text, 2354 fNegPrefixPattern, fNegSuffixPattern, 2355 fPosPrefixPattern, fPosSuffixPattern, 2356 TRUE, UCURR_LONG_NAME, 2357 tmpPos, tmpDigitList, tmpStatus, currency); 2358 } else { 2359 found = subparse(text, 2360 fNegPrefixPattern, fNegSuffixPattern, 2361 fPosPrefixPattern, fPosSuffixPattern, 2362 TRUE, UCURR_SYMBOL_NAME, 2363 tmpPos, tmpDigitList, tmpStatus, currency); 2364 } 2365 if (found) { 2366 if (tmpPos.getIndex() > maxPosIndex) { 2367 maxPosIndex = tmpPos.getIndex(); 2368 for (int32_t i = 0; i < fgStatusLength; ++i) { 2369 status[i] = tmpStatus[i]; 2370 } 2371 digits = tmpDigitList; 2372 } 2373 } else { 2374 maxErrorPos = tmpPos.getErrorIndex(); 2375 } 2376 // Then, parse against affix patterns. 2377 // Those are currency patterns and currency plural patterns. 2378 int32_t pos = -1; 2379 const UHashElement* element = NULL; 2380 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 2381 const UHashTok valueTok = element->value; 2382 const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer; 2383 UBool tmpStatus[fgStatusLength]; 2384 ParsePosition tmpPos(origPos); 2385 DigitList tmpDigitList; 2386 2387#ifdef FMT_DEBUG 2388 debug("trying affix for currency.."); 2389 affixPtn->dump(); 2390#endif 2391 2392 UBool result = subparse(text, 2393 &affixPtn->negPrefixPatternForCurrency, 2394 &affixPtn->negSuffixPatternForCurrency, 2395 &affixPtn->posPrefixPatternForCurrency, 2396 &affixPtn->posSuffixPatternForCurrency, 2397 TRUE, affixPtn->patternType, 2398 tmpPos, tmpDigitList, tmpStatus, currency); 2399 if (result) { 2400 found = true; 2401 if (tmpPos.getIndex() > maxPosIndex) { 2402 maxPosIndex = tmpPos.getIndex(); 2403 for (int32_t i = 0; i < fgStatusLength; ++i) { 2404 status[i] = tmpStatus[i]; 2405 } 2406 digits = tmpDigitList; 2407 } 2408 } else { 2409 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? 2410 tmpPos.getErrorIndex() : maxErrorPos; 2411 } 2412 } 2413 // Finally, parse against simple affix to find the match. 2414 // For example, in TestMonster suite, 2415 // if the to-be-parsed text is "-\u00A40,00". 2416 // complexAffixCompare will not find match, 2417 // since there is no ISO code matches "\u00A4", 2418 // and the parse stops at "\u00A4". 2419 // We will just use simple affix comparison (look for exact match) 2420 // to pass it. 2421 // 2422 // TODO: We should parse against simple affix first when 2423 // output currency is not requested. After the complex currency 2424 // parsing implementation was introduced, the default currency 2425 // instance parsing slowed down because of the new code flow. 2426 // I filed #10312 - Yoshito 2427 UBool tmpStatus_2[fgStatusLength]; 2428 ParsePosition tmpPos_2(origPos); 2429 DigitList tmpDigitList_2; 2430 2431 // Disable complex currency parsing and try it again. 2432 UBool result = subparse(text, 2433 &fNegativePrefix, &fNegativeSuffix, 2434 &fPositivePrefix, &fPositiveSuffix, 2435 FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME, 2436 tmpPos_2, tmpDigitList_2, tmpStatus_2, 2437 currency); 2438 if (result) { 2439 if (tmpPos_2.getIndex() > maxPosIndex) { 2440 maxPosIndex = tmpPos_2.getIndex(); 2441 for (int32_t i = 0; i < fgStatusLength; ++i) { 2442 status[i] = tmpStatus_2[i]; 2443 } 2444 digits = tmpDigitList_2; 2445 } 2446 found = true; 2447 } else { 2448 maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ? 2449 tmpPos_2.getErrorIndex() : maxErrorPos; 2450 } 2451 2452 if (!found) { 2453 //parsePosition.setIndex(origPos); 2454 parsePosition.setErrorIndex(maxErrorPos); 2455 } else { 2456 parsePosition.setIndex(maxPosIndex); 2457 parsePosition.setErrorIndex(-1); 2458 } 2459 return found; 2460} 2461 2462 2463/** 2464 * Parse the given text into a number. The text is parsed beginning at 2465 * parsePosition, until an unparseable character is seen. 2466 * @param text the string to parse. 2467 * @param negPrefix negative prefix. 2468 * @param negSuffix negative suffix. 2469 * @param posPrefix positive prefix. 2470 * @param posSuffix positive suffix. 2471 * @param complexCurrencyParsing whether it is complex currency parsing or not. 2472 * @param type the currency type to parse against, LONG_NAME only or not. 2473 * @param parsePosition The position at which to being parsing. Upon 2474 * return, the first unparsed character. 2475 * @param digits the DigitList to set to the parsed value. 2476 * @param status output param containing boolean status flags indicating 2477 * whether the value was infinite and whether it was positive. 2478 * @param currency return value for parsed currency, for generic 2479 * currency parsing mode, or NULL for normal parsing. In generic 2480 * currency parsing mode, any currency is parsed, not just the 2481 * currency that this formatter is set to. 2482 */ 2483UBool DecimalFormat::subparse(const UnicodeString& text, 2484 const UnicodeString* negPrefix, 2485 const UnicodeString* negSuffix, 2486 const UnicodeString* posPrefix, 2487 const UnicodeString* posSuffix, 2488 UBool complexCurrencyParsing, 2489 int8_t type, 2490 ParsePosition& parsePosition, 2491 DigitList& digits, UBool* status, 2492 UChar* currency) const 2493{ 2494 // The parsing process builds up the number as char string, in the neutral format that 2495 // will be acceptable to the decNumber library, then at the end passes that string 2496 // off for conversion to a decNumber. 2497 UErrorCode err = U_ZERO_ERROR; 2498 CharString parsedNum; 2499 digits.setToZero(); 2500 2501 int32_t position = parsePosition.getIndex(); 2502 int32_t oldStart = position; 2503 int32_t textLength = text.length(); // One less pointer to follow 2504 UBool strictParse = !isLenient(); 2505 UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 2506 const UnicodeString *groupingString = &getConstSymbol(fCurrencySignCount == fgCurrencySignCountZero ? 2507 DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); 2508 UChar32 groupingChar = groupingString->char32At(0); 2509 int32_t groupingStringLength = groupingString->length(); 2510 int32_t groupingCharLength = U16_LENGTH(groupingChar); 2511 UBool groupingUsed = isGroupingUsed(); 2512#ifdef FMT_DEBUG 2513 UChar dbgbuf[300]; 2514 UnicodeString s(dbgbuf,0,300);; 2515 s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " ); 2516#define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeString(" ")); } else { s.append(UnicodeString(#x "=NULL ")); } 2517 DBGAPPD(negPrefix); 2518 DBGAPPD(negSuffix); 2519 DBGAPPD(posPrefix); 2520 DBGAPPD(posSuffix); 2521 debugout(s); 2522 printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, (isParseIntegerOnly())?'Y':'N', text.length(), negPrefix!=NULL?negPrefix->length():-1); 2523#endif 2524 2525 UBool fastParseOk = false; /* TRUE iff fast parse is OK */ 2526 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */ 2527 const DecimalFormatInternal &data = internalData(fReserved); 2528 if((data.fFastParseStatus==kFastpathYES) && 2529 fCurrencySignCount == fgCurrencySignCountZero && 2530 // (negPrefix!=NULL&&negPrefix->isEmpty()) || 2531 text.length()>0 && 2532 text.length()<32 && 2533 (posPrefix==NULL||posPrefix->isEmpty()) && 2534 (posSuffix==NULL||posSuffix->isEmpty()) && 2535 // (negPrefix==NULL||negPrefix->isEmpty()) && 2536 // (negSuffix==NULL||(negSuffix->isEmpty()) ) && 2537 TRUE) { // optimized path 2538 int j=position; 2539 int l=text.length(); 2540 int digitCount=0; 2541 UChar32 ch = text.char32At(j); 2542 const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 2543 UChar32 decimalChar = 0; 2544 UBool intOnly = FALSE; 2545 UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0; 2546 2547 int32_t decimalCount = decimalString->countChar32(0,3); 2548 if(isParseIntegerOnly()) { 2549 decimalChar = 0; // not allowed 2550 intOnly = TRUE; // Don't look for decimals. 2551 } else if(decimalCount==1) { 2552 decimalChar = decimalString->char32At(0); // Look for this decimal 2553 } else if(decimalCount==0) { 2554 decimalChar=0; // NO decimal set 2555 } else { 2556 j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation. 2557 } 2558 2559#ifdef FMT_DEBUG 2560 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n", 2561 decimalChar, groupingChar, ch, 2562 (intOnly)?'y':'n', 2563 (strictParse)?'y':'n'); 2564#endif 2565 if(ch==0x002D) { // '-' 2566 j=l+1;//=break - negative number. 2567 2568 /* 2569 parsedNum.append('-',err); 2570 j+=U16_LENGTH(ch); 2571 if(j<l) ch = text.char32At(j); 2572 */ 2573 } else { 2574 parsedNum.append('+',err); 2575 } 2576 while(j<l) { 2577 int32_t digit = ch - zero; 2578 if(digit >=0 && digit <= 9) { 2579 parsedNum.append((char)(digit + '0'), err); 2580 if((digitCount>0) || digit!=0 || j==(l-1)) { 2581 digitCount++; 2582 } 2583 } else if(ch == 0) { // break out 2584 digitCount=-1; 2585 break; 2586 } else if(ch == decimalChar) { 2587 parsedNum.append((char)('.'), err); 2588 decimalChar=0; // no more decimals. 2589 // fastParseHadDecimal=TRUE; 2590 } else if(ch == lookForGroup) { 2591 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep 2592 } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) { 2593 // parsing integer only and can fall through 2594 } else { 2595 digitCount=-1; // fail - fall through to slow parse 2596 break; 2597 } 2598 j+=U16_LENGTH(ch); 2599 ch = text.char32At(j); // for next 2600 } 2601 if( 2602 ((j==l)||intOnly) // end OR only parsing integer 2603 && (digitCount>0)) { // and have at least one digit 2604#ifdef FMT_DEBUG 2605 printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2); 2606#endif 2607 fastParseOk=true; // Fast parse OK! 2608 2609#ifdef SKIP_OPT 2610 debug("SKIP_OPT"); 2611 /* for testing, try it the slow way. also */ 2612 fastParseOk=false; 2613 parsedNum.clear(); 2614#else 2615 parsePosition.setIndex(position=j); 2616 status[fgStatusInfinite]=false; 2617#endif 2618 } else { 2619 // was not OK. reset, retry 2620#ifdef FMT_DEBUG 2621 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount); 2622#endif 2623 parsedNum.clear(); 2624 } 2625 } else { 2626#ifdef FMT_DEBUG 2627 printf("Could not fastpath parse. "); 2628 printf("fFormatWidth=%d ", fFormatWidth); 2629 printf("text.length()=%d ", text.length()); 2630 printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix); 2631 2632 printf("\n"); 2633#endif 2634 } 2635 2636 if(!fastParseOk 2637#if UCONFIG_HAVE_PARSEALLINPUT 2638 && fParseAllInput!=UNUM_YES 2639#endif 2640 ) 2641 { 2642 // Match padding before prefix 2643 if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) { 2644 position = skipPadding(text, position); 2645 } 2646 2647 // Match positive and negative prefixes; prefer longest match. 2648 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, complexCurrencyParsing, type, currency); 2649 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, complexCurrencyParsing, type, currency); 2650 if (posMatch >= 0 && negMatch >= 0) { 2651 if (posMatch > negMatch) { 2652 negMatch = -1; 2653 } else if (negMatch > posMatch) { 2654 posMatch = -1; 2655 } 2656 } 2657 if (posMatch >= 0) { 2658 position += posMatch; 2659 parsedNum.append('+', err); 2660 } else if (negMatch >= 0) { 2661 position += negMatch; 2662 parsedNum.append('-', err); 2663 } else if (strictParse){ 2664 parsePosition.setErrorIndex(position); 2665 return FALSE; 2666 } else { 2667 // Temporary set positive. This might be changed after checking suffix 2668 parsedNum.append('+', err); 2669 } 2670 2671 // Match padding before prefix 2672 if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) { 2673 position = skipPadding(text, position); 2674 } 2675 2676 if (! strictParse) { 2677 position = skipUWhiteSpace(text, position); 2678 } 2679 2680 // process digits or Inf, find decimal position 2681 const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol); 2682 int32_t infLen = (text.compare(position, inf->length(), *inf) 2683 ? 0 : inf->length()); 2684 position += infLen; // infLen is non-zero when it does equal to infinity 2685 status[fgStatusInfinite] = infLen != 0; 2686 2687 if (infLen != 0) { 2688 parsedNum.append("Infinity", err); 2689 } else { 2690 // We now have a string of digits, possibly with grouping symbols, 2691 // and decimal points. We want to process these into a DigitList. 2692 // We don't want to put a bunch of leading zeros into the DigitList 2693 // though, so we keep track of the location of the decimal point, 2694 // put only significant digits into the DigitList, and adjust the 2695 // exponent as needed. 2696 2697 2698 UBool strictFail = FALSE; // did we exit with a strict parse failure? 2699 int32_t lastGroup = -1; // where did we last see a grouping separator? 2700 int32_t digitStart = position; 2701 int32_t gs2 = fGroupingSize2 == 0 ? fGroupingSize : fGroupingSize2; 2702 2703 const UnicodeString *decimalString; 2704 if (fCurrencySignCount != fgCurrencySignCountZero) { 2705 decimalString = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 2706 } else { 2707 decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 2708 } 2709 UChar32 decimalChar = decimalString->char32At(0); 2710 int32_t decimalStringLength = decimalString->length(); 2711 int32_t decimalCharLength = U16_LENGTH(decimalChar); 2712 2713 UBool sawDecimal = FALSE; 2714 UChar32 sawDecimalChar = 0xFFFF; 2715 UBool sawGrouping = FALSE; 2716 UChar32 sawGroupingChar = 0xFFFF; 2717 UBool sawDigit = FALSE; 2718 int32_t backup = -1; 2719 int32_t digit; 2720 2721 // equivalent grouping and decimal support 2722 const UnicodeSet *decimalSet = NULL; 2723 const UnicodeSet *groupingSet = NULL; 2724 2725 if (decimalCharLength == decimalStringLength) { 2726 decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse); 2727 } 2728 2729 if (groupingCharLength == groupingStringLength) { 2730 if (strictParse) { 2731 groupingSet = fStaticSets->fStrictDefaultGroupingSeparators; 2732 } else { 2733 groupingSet = fStaticSets->fDefaultGroupingSeparators; 2734 } 2735 } 2736 2737 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized. 2738 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet 2739 // If a character matches decimalSet, don't consider it to be a member of the groupingSet. 2740 2741 // We have to track digitCount ourselves, because digits.fCount will 2742 // pin when the maximum allowable digits is reached. 2743 int32_t digitCount = 0; 2744 int32_t integerDigitCount = 0; 2745 2746 for (; position < textLength; ) 2747 { 2748 UChar32 ch = text.char32At(position); 2749 2750 /* We recognize all digit ranges, not only the Latin digit range 2751 * '0'..'9'. We do so by using the Character.digit() method, 2752 * which converts a valid Unicode digit to the range 0..9. 2753 * 2754 * The character 'ch' may be a digit. If so, place its value 2755 * from 0 to 9 in 'digit'. First try using the locale digit, 2756 * which may or MAY NOT be a standard Unicode digit range. If 2757 * this fails, try using the standard Unicode digit ranges by 2758 * calling Character.digit(). If this also fails, digit will 2759 * have a value outside the range 0..9. 2760 */ 2761 digit = ch - zero; 2762 if (digit < 0 || digit > 9) 2763 { 2764 digit = u_charDigitValue(ch); 2765 } 2766 2767 // As a last resort, look through the localized digits if the zero digit 2768 // is not a "standard" Unicode digit. 2769 if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) { 2770 digit = 0; 2771 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is: 2772 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits. 2773 if ( zero!=0x3007 || ch!=0x96F6 ) { 2774 for (digit = 1 ; digit < 10 ; digit++ ) { 2775 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) { 2776 break; 2777 } 2778 } 2779 } 2780 } 2781 2782 if (digit >= 0 && digit <= 9) 2783 { 2784 if (strictParse && backup != -1) { 2785 // comma followed by digit, so group before comma is a 2786 // secondary group. If there was a group separator 2787 // before that, the group must == the secondary group 2788 // length, else it can be <= the the secondary group 2789 // length. 2790 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) || 2791 (lastGroup == -1 && position - digitStart - 1 > gs2)) { 2792 strictFail = TRUE; 2793 break; 2794 } 2795 2796 lastGroup = backup; 2797 } 2798 2799 // Cancel out backup setting (see grouping handler below) 2800 backup = -1; 2801 sawDigit = TRUE; 2802 2803 // Note: this will append leading zeros 2804 parsedNum.append((char)(digit + '0'), err); 2805 2806 // count any digit that's not a leading zero 2807 if (digit > 0 || digitCount > 0 || sawDecimal) { 2808 digitCount += 1; 2809 2810 // count any integer digit that's not a leading zero 2811 if (! sawDecimal) { 2812 integerDigitCount += 1; 2813 } 2814 } 2815 2816 position += U16_LENGTH(ch); 2817 } 2818 else if (groupingStringLength > 0 && 2819 matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet, 2820 decimalChar, decimalSet, 2821 ch) && groupingUsed) 2822 { 2823 if (sawDecimal) { 2824 break; 2825 } 2826 2827 if (strictParse) { 2828 if ( (!sawDigit && groupingSet!=NULL && u_isWhitespace(ch)) || backup != -1 ) { 2829 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for 2830 // backward compatibility) as long as it is not one of the breaking whitespace characters 2831 // that is only treated as a group separator because of the equivalence set. If we get 2832 // here it is because the leading sep was such a breaking space, or there were multiple 2833 // group separators in a row. Note that the DecimalFormat documentation says 2834 // "During parsing, grouping separators are ignored" and that was for strict parsing, 2835 // so we may need to further revisit this strictParse restriction to ensure compatibility. 2836 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F. 2837 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP). 2838 strictFail = TRUE; 2839 break; 2840 } 2841 } 2842 2843 // Ignore grouping characters, if we are using them, but require 2844 // that they be followed by a digit. Otherwise we backup and 2845 // reprocess them. 2846 backup = position; 2847 position += groupingStringLength; 2848 sawGrouping=TRUE; 2849 // Once we see a grouping character, we only accept that grouping character from then on. 2850 sawGroupingChar=ch; 2851 } 2852 else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch)) 2853 { 2854 if (strictParse) { 2855 if (backup != -1 || 2856 (lastGroup != -1 && position - lastGroup != fGroupingSize + 1)) { 2857 strictFail = TRUE; 2858 break; 2859 } 2860 } 2861 2862 // If we're only parsing integers, or if we ALREADY saw the 2863 // decimal, then don't parse this one. 2864 if (isParseIntegerOnly() || sawDecimal) { 2865 break; 2866 } 2867 2868 parsedNum.append('.', err); 2869 position += decimalStringLength; 2870 sawDecimal = TRUE; 2871 // Once we see a decimal character, we only accept that decimal character from then on. 2872 sawDecimalChar=ch; 2873 // decimalSet is considered to consist of (ch,ch) 2874 } 2875 else { 2876 2877 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless.. 2878 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways 2879 const UnicodeString *tmp; 2880 tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 2881 // TODO: CASE 2882 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit 2883 { 2884 // Parse sign, if present 2885 int32_t pos = position + tmp->length(); 2886 char exponentSign = '+'; 2887 2888 if (pos < textLength) 2889 { 2890 tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 2891 if (!text.compare(pos, tmp->length(), *tmp)) 2892 { 2893 pos += tmp->length(); 2894 } 2895 else { 2896 tmp = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 2897 if (!text.compare(pos, tmp->length(), *tmp)) 2898 { 2899 exponentSign = '-'; 2900 pos += tmp->length(); 2901 } 2902 } 2903 } 2904 2905 UBool sawExponentDigit = FALSE; 2906 while (pos < textLength) { 2907 ch = text[(int32_t)pos]; 2908 digit = ch - zero; 2909 2910 if (digit < 0 || digit > 9) { 2911 digit = u_charDigitValue(ch); 2912 } 2913 if (0 <= digit && digit <= 9) { 2914 if (!sawExponentDigit) { 2915 parsedNum.append('E', err); 2916 parsedNum.append(exponentSign, err); 2917 sawExponentDigit = TRUE; 2918 } 2919 ++pos; 2920 parsedNum.append((char)(digit + '0'), err); 2921 } else { 2922 break; 2923 } 2924 } 2925 2926 if (sawExponentDigit) { 2927 position = pos; // Advance past the exponent 2928 } 2929 2930 break; // Whether we fail or succeed, we exit this loop 2931 } else { 2932 break; 2933 } 2934 } else { // not parsing exponent 2935 break; 2936 } 2937 } 2938 } 2939 2940 if (backup != -1) 2941 { 2942 position = backup; 2943 } 2944 2945 if (strictParse && !sawDecimal) { 2946 if (lastGroup != -1 && position - lastGroup != fGroupingSize + 1) { 2947 strictFail = TRUE; 2948 } 2949 } 2950 2951 if (strictFail) { 2952 // only set with strictParse and a grouping separator error 2953 2954 parsePosition.setIndex(oldStart); 2955 parsePosition.setErrorIndex(position); 2956 debug("strictFail!"); 2957 return FALSE; 2958 } 2959 2960 // If there was no decimal point we have an integer 2961 2962 // If none of the text string was recognized. For example, parse 2963 // "x" with pattern "#0.00" (return index and error index both 0) 2964 // parse "$" with pattern "$#0.00". (return index 0 and error index 2965 // 1). 2966 if (!sawDigit && digitCount == 0) { 2967#ifdef FMT_DEBUG 2968 debug("none of text rec"); 2969 printf("position=%d\n",position); 2970#endif 2971 parsePosition.setIndex(oldStart); 2972 parsePosition.setErrorIndex(oldStart); 2973 return FALSE; 2974 } 2975 } 2976 2977 // Match padding before suffix 2978 if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) { 2979 position = skipPadding(text, position); 2980 } 2981 2982 int32_t posSuffixMatch = -1, negSuffixMatch = -1; 2983 2984 // Match positive and negative suffixes; prefer longest match. 2985 if (posMatch >= 0 || (!strictParse && negMatch < 0)) { 2986 posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency); 2987 } 2988 if (negMatch >= 0) { 2989 negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency); 2990 } 2991 if (posSuffixMatch >= 0 && negSuffixMatch >= 0) { 2992 if (posSuffixMatch > negSuffixMatch) { 2993 negSuffixMatch = -1; 2994 } else if (negSuffixMatch > posSuffixMatch) { 2995 posSuffixMatch = -1; 2996 } 2997 } 2998 2999 // Fail if neither or both 3000 if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) { 3001 parsePosition.setErrorIndex(position); 3002 debug("neither or both"); 3003 return FALSE; 3004 } 3005 3006 position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0)); 3007 3008 // Match padding before suffix 3009 if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) { 3010 position = skipPadding(text, position); 3011 } 3012 3013 parsePosition.setIndex(position); 3014 3015 parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-'; 3016#ifdef FMT_DEBUG 3017printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err)); 3018#endif 3019 } /* end SLOW parse */ 3020 if(parsePosition.getIndex() == oldStart) 3021 { 3022#ifdef FMT_DEBUG 3023 printf(" PP didnt move, err\n"); 3024#endif 3025 parsePosition.setErrorIndex(position); 3026 return FALSE; 3027 } 3028#if UCONFIG_HAVE_PARSEALLINPUT 3029 else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength) 3030 { 3031#ifdef FMT_DEBUG 3032 printf(" PP didnt consume all (UNUM_YES), err\n"); 3033#endif 3034 parsePosition.setErrorIndex(position); 3035 return FALSE; 3036 } 3037#endif 3038 // uint32_t bits = (fastParseOk?kFastpathOk:0) | 3039 // (fastParseHadDecimal?0:kNoDecimal); 3040 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits); 3041 digits.set(parsedNum.toStringPiece(), 3042 err, 3043 0//bits 3044 ); 3045 3046 if (U_FAILURE(err)) { 3047#ifdef FMT_DEBUG 3048 printf(" err setting %s\n", u_errorName(err)); 3049#endif 3050 parsePosition.setErrorIndex(position); 3051 return FALSE; 3052 } 3053 return TRUE; 3054} 3055 3056/** 3057 * Starting at position, advance past a run of pad characters, if any. 3058 * Return the index of the first character after position that is not a pad 3059 * character. Result is >= position. 3060 */ 3061int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const { 3062 int32_t padLen = U16_LENGTH(fPad); 3063 while (position < text.length() && 3064 text.char32At(position) == fPad) { 3065 position += padLen; 3066 } 3067 return position; 3068} 3069 3070/** 3071 * Return the length matched by the given affix, or -1 if none. 3072 * Runs of white space in the affix, match runs of white space in 3073 * the input. Pattern white space and input white space are 3074 * determined differently; see code. 3075 * @param text input text 3076 * @param pos offset into input at which to begin matching 3077 * @param isNegative 3078 * @param isPrefix 3079 * @param affixPat affix pattern used for currency affix comparison. 3080 * @param complexCurrencyParsing whether it is currency parsing or not 3081 * @param type the currency type to parse against, LONG_NAME only or not. 3082 * @param currency return value for parsed currency, for generic 3083 * currency parsing mode, or null for normal parsing. In generic 3084 * currency parsing mode, any currency is parsed, not just the 3085 * currency that this formatter is set to. 3086 * @return length of input that matches, or -1 if match failure 3087 */ 3088int32_t DecimalFormat::compareAffix(const UnicodeString& text, 3089 int32_t pos, 3090 UBool isNegative, 3091 UBool isPrefix, 3092 const UnicodeString* affixPat, 3093 UBool complexCurrencyParsing, 3094 int8_t type, 3095 UChar* currency) const 3096{ 3097 const UnicodeString *patternToCompare; 3098 if (fCurrencyChoice != NULL || currency != NULL || 3099 (fCurrencySignCount != fgCurrencySignCountZero && complexCurrencyParsing)) { 3100 3101 if (affixPat != NULL) { 3102 return compareComplexAffix(*affixPat, text, pos, type, currency); 3103 } 3104 } 3105 3106 if (isNegative) { 3107 if (isPrefix) { 3108 patternToCompare = &fNegativePrefix; 3109 } 3110 else { 3111 patternToCompare = &fNegativeSuffix; 3112 } 3113 } 3114 else { 3115 if (isPrefix) { 3116 patternToCompare = &fPositivePrefix; 3117 } 3118 else { 3119 patternToCompare = &fPositiveSuffix; 3120 } 3121 } 3122 return compareSimpleAffix(*patternToCompare, text, pos, isLenient()); 3123} 3124 3125UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const { 3126 if (lhs == rhs) { 3127 return TRUE; 3128 } 3129 U_ASSERT(fStaticSets != NULL); // should already be loaded 3130 const UnicodeSet *minusSigns = fStaticSets->fMinusSigns; 3131 const UnicodeSet *plusSigns = fStaticSets->fPlusSigns; 3132 return (minusSigns->contains(lhs) && minusSigns->contains(rhs)) || 3133 (plusSigns->contains(lhs) && plusSigns->contains(rhs)); 3134} 3135 3136// check for LRM 0x200E, RLM 0x200F, ALM 0x061C 3137#define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C) 3138 3139#define TRIM_BUFLEN 32 3140UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix) { 3141 UChar trimBuf[TRIM_BUFLEN]; 3142 int32_t affixLen = affix.length(); 3143 int32_t affixPos, trimLen = 0; 3144 3145 for (affixPos = 0; affixPos < affixLen; affixPos++) { 3146 UChar c = affix.charAt(affixPos); 3147 if (!IS_BIDI_MARK(c)) { 3148 if (trimLen < TRIM_BUFLEN) { 3149 trimBuf[trimLen++] = c; 3150 } else { 3151 trimLen = 0; 3152 break; 3153 } 3154 } 3155 } 3156 return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix); 3157} 3158 3159/** 3160 * Return the length matched by the given affix, or -1 if none. 3161 * Runs of white space in the affix, match runs of white space in 3162 * the input. Pattern white space and input white space are 3163 * determined differently; see code. 3164 * @param affix pattern string, taken as a literal 3165 * @param input input text 3166 * @param pos offset into input at which to begin matching 3167 * @return length of input that matches, or -1 if match failure 3168 */ 3169int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix, 3170 const UnicodeString& input, 3171 int32_t pos, 3172 UBool lenient) const { 3173 int32_t start = pos; 3174 UnicodeString trimmedAffix; 3175 // For more efficiency we should keep lazily-created trimmed affixes around in 3176 // instance variables instead of trimming each time they are used (the next step) 3177 trimMarksFromAffix(affix, trimmedAffix); 3178 UChar32 affixChar = trimmedAffix.char32At(0); 3179 int32_t affixLength = trimmedAffix.length(); 3180 int32_t inputLength = input.length(); 3181 int32_t affixCharLength = U16_LENGTH(affixChar); 3182 UnicodeSet *affixSet; 3183 UErrorCode status = U_ZERO_ERROR; 3184 3185 U_ASSERT(fStaticSets != NULL); // should already be loaded 3186 3187 if (U_FAILURE(status)) { 3188 return -1; 3189 } 3190 if (!lenient) { 3191 affixSet = fStaticSets->fStrictDashEquivalents; 3192 3193 // If the trimmedAffix is exactly one character long and that character 3194 // is in the dash set and the very next input character is also 3195 // in the dash set, return a match. 3196 if (affixCharLength == affixLength && affixSet->contains(affixChar)) { 3197 UChar32 ic = input.char32At(pos); 3198 if (affixSet->contains(ic)) { 3199 pos += U16_LENGTH(ic); 3200 pos = skipBidiMarks(input, pos); // skip any trailing bidi marks 3201 return pos - start; 3202 } 3203 } 3204 3205 for (int32_t i = 0; i < affixLength; ) { 3206 UChar32 c = trimmedAffix.char32At(i); 3207 int32_t len = U16_LENGTH(c); 3208 if (PatternProps::isWhiteSpace(c)) { 3209 // We may have a pattern like: \u200F \u0020 3210 // and input text like: \u200F \u0020 3211 // Note that U+200F and U+0020 are Pattern_White_Space but only 3212 // U+0020 is UWhiteSpace. So we have to first do a direct 3213 // match of the run of Pattern_White_Space in the pattern, 3214 // then match any extra characters. 3215 UBool literalMatch = FALSE; 3216 while (pos < inputLength) { 3217 UChar32 ic = input.char32At(pos); 3218 if (ic == c) { 3219 literalMatch = TRUE; 3220 i += len; 3221 pos += len; 3222 if (i == affixLength) { 3223 break; 3224 } 3225 c = trimmedAffix.char32At(i); 3226 len = U16_LENGTH(c); 3227 if (!PatternProps::isWhiteSpace(c)) { 3228 break; 3229 } 3230 } else if (IS_BIDI_MARK(ic)) { 3231 pos ++; // just skip over this input text 3232 } else { 3233 break; 3234 } 3235 } 3236 3237 // Advance over run in pattern 3238 i = skipPatternWhiteSpace(trimmedAffix, i); 3239 3240 // Advance over run in input text 3241 // Must see at least one white space char in input, 3242 // unless we've already matched some characters literally. 3243 int32_t s = pos; 3244 pos = skipUWhiteSpace(input, pos); 3245 if (pos == s && !literalMatch) { 3246 return -1; 3247 } 3248 3249 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern. 3250 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that 3251 // is also in the trimmedAffix. 3252 i = skipUWhiteSpace(trimmedAffix, i); 3253 } else { 3254 UBool match = FALSE; 3255 while (pos < inputLength) { 3256 UChar32 ic = input.char32At(pos); 3257 if (!match && ic == c) { 3258 i += len; 3259 pos += len; 3260 match = TRUE; 3261 } else if (IS_BIDI_MARK(ic)) { 3262 pos++; // just skip over this input text 3263 } else { 3264 break; 3265 } 3266 } 3267 if (!match) { 3268 return -1; 3269 } 3270 } 3271 } 3272 } else { 3273 UBool match = FALSE; 3274 3275 affixSet = fStaticSets->fDashEquivalents; 3276 3277 if (affixCharLength == affixLength && affixSet->contains(affixChar)) { 3278 pos = skipUWhiteSpaceAndMarks(input, pos); 3279 UChar32 ic = input.char32At(pos); 3280 3281 if (affixSet->contains(ic)) { 3282 pos += U16_LENGTH(ic); 3283 pos = skipBidiMarks(input, pos); 3284 return pos - start; 3285 } 3286 } 3287 3288 for (int32_t i = 0; i < affixLength; ) 3289 { 3290 //i = skipRuleWhiteSpace(trimmedAffix, i); 3291 i = skipUWhiteSpace(trimmedAffix, i); 3292 pos = skipUWhiteSpaceAndMarks(input, pos); 3293 3294 if (i >= affixLength || pos >= inputLength) { 3295 break; 3296 } 3297 3298 UChar32 c = trimmedAffix.char32At(i); 3299 UChar32 ic = input.char32At(pos); 3300 3301 if (!equalWithSignCompatibility(ic, c)) { 3302 return -1; 3303 } 3304 3305 match = TRUE; 3306 i += U16_LENGTH(c); 3307 pos += U16_LENGTH(ic); 3308 pos = skipBidiMarks(input, pos); 3309 } 3310 3311 if (affixLength > 0 && ! match) { 3312 return -1; 3313 } 3314 } 3315 return pos - start; 3316} 3317 3318/** 3319 * Skip over a run of zero or more Pattern_White_Space characters at 3320 * pos in text. 3321 */ 3322int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) { 3323 const UChar* s = text.getBuffer(); 3324 return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s); 3325} 3326 3327/** 3328 * Skip over a run of zero or more isUWhiteSpace() characters at pos 3329 * in text. 3330 */ 3331int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) { 3332 while (pos < text.length()) { 3333 UChar32 c = text.char32At(pos); 3334 if (!u_isUWhiteSpace(c)) { 3335 break; 3336 } 3337 pos += U16_LENGTH(c); 3338 } 3339 return pos; 3340} 3341 3342/** 3343 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos 3344 * in text. 3345 */ 3346int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos) { 3347 while (pos < text.length()) { 3348 UChar32 c = text.char32At(pos); 3349 if (!u_isUWhiteSpace(c) && !IS_BIDI_MARK(c)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM 3350 break; 3351 } 3352 pos += U16_LENGTH(c); 3353 } 3354 return pos; 3355} 3356 3357/** 3358 * Skip over a run of zero or more bidi marks at pos in text. 3359 */ 3360int32_t DecimalFormat::skipBidiMarks(const UnicodeString& text, int32_t pos) { 3361 while (pos < text.length()) { 3362 UChar c = text.charAt(pos); 3363 if (!IS_BIDI_MARK(c)) { 3364 break; 3365 } 3366 pos++; 3367 } 3368 return pos; 3369} 3370 3371/** 3372 * Return the length matched by the given affix, or -1 if none. 3373 * @param affixPat pattern string 3374 * @param input input text 3375 * @param pos offset into input at which to begin matching 3376 * @param type the currency type to parse against, LONG_NAME only or not. 3377 * @param currency return value for parsed currency, for generic 3378 * currency parsing mode, or null for normal parsing. In generic 3379 * currency parsing mode, any currency is parsed, not just the 3380 * currency that this formatter is set to. 3381 * @return length of input that matches, or -1 if match failure 3382 */ 3383int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat, 3384 const UnicodeString& text, 3385 int32_t pos, 3386 int8_t type, 3387 UChar* currency) const 3388{ 3389 int32_t start = pos; 3390 U_ASSERT(currency != NULL || 3391 (fCurrencyChoice != NULL && *getCurrency() != 0) || 3392 fCurrencySignCount != fgCurrencySignCountZero); 3393 3394 for (int32_t i=0; 3395 i<affixPat.length() && pos >= 0; ) { 3396 UChar32 c = affixPat.char32At(i); 3397 i += U16_LENGTH(c); 3398 3399 if (c == kQuote) { 3400 U_ASSERT(i <= affixPat.length()); 3401 c = affixPat.char32At(i); 3402 i += U16_LENGTH(c); 3403 3404 const UnicodeString* affix = NULL; 3405 3406 switch (c) { 3407 case kCurrencySign: { 3408 // since the currency names in choice format is saved 3409 // the same way as other currency names, 3410 // do not need to do currency choice parsing here. 3411 // the general currency parsing parse against all names, 3412 // including names in choice format. 3413 UBool intl = i<affixPat.length() && 3414 affixPat.char32At(i) == kCurrencySign; 3415 if (intl) { 3416 ++i; 3417 } 3418 UBool plural = i<affixPat.length() && 3419 affixPat.char32At(i) == kCurrencySign; 3420 if (plural) { 3421 ++i; 3422 intl = FALSE; 3423 } 3424 // Parse generic currency -- anything for which we 3425 // have a display name, or any 3-letter ISO code. 3426 // Try to parse display name for our locale; first 3427 // determine our locale. 3428 const char* loc = fCurrencyPluralInfo->getLocale().getName(); 3429 ParsePosition ppos(pos); 3430 UChar curr[4]; 3431 UErrorCode ec = U_ZERO_ERROR; 3432 // Delegate parse of display name => ISO code to Currency 3433 uprv_parseCurrency(loc, text, ppos, type, curr, ec); 3434 3435 // If parse succeeds, populate currency[0] 3436 if (U_SUCCESS(ec) && ppos.getIndex() != pos) { 3437 if (currency) { 3438 u_strcpy(currency, curr); 3439 } else { 3440 // The formatter is currency-style but the client has not requested 3441 // the value of the parsed currency. In this case, if that value does 3442 // not match the formatter's current value, then the parse fails. 3443 UChar effectiveCurr[4]; 3444 getEffectiveCurrency(effectiveCurr, ec); 3445 if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) { 3446 pos = -1; 3447 continue; 3448 } 3449 } 3450 pos = ppos.getIndex(); 3451 } else if (!isLenient()){ 3452 pos = -1; 3453 } 3454 continue; 3455 } 3456 case kPatternPercent: 3457 affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 3458 break; 3459 case kPatternPerMill: 3460 affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 3461 break; 3462 case kPatternPlus: 3463 affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 3464 break; 3465 case kPatternMinus: 3466 affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 3467 break; 3468 default: 3469 // fall through to affix!=0 test, which will fail 3470 break; 3471 } 3472 3473 if (affix != NULL) { 3474 pos = match(text, pos, *affix); 3475 continue; 3476 } 3477 } 3478 3479 pos = match(text, pos, c); 3480 if (PatternProps::isWhiteSpace(c)) { 3481 i = skipPatternWhiteSpace(affixPat, i); 3482 } 3483 } 3484 return pos - start; 3485} 3486 3487/** 3488 * Match a single character at text[pos] and return the index of the 3489 * next character upon success. Return -1 on failure. If 3490 * ch is a Pattern_White_Space then match a run of white space in text. 3491 */ 3492int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) { 3493 if (PatternProps::isWhiteSpace(ch)) { 3494 // Advance over run of white space in input text 3495 // Must see at least one white space char in input 3496 int32_t s = pos; 3497 pos = skipPatternWhiteSpace(text, pos); 3498 if (pos == s) { 3499 return -1; 3500 } 3501 return pos; 3502 } 3503 return (pos >= 0 && text.char32At(pos) == ch) ? 3504 (pos + U16_LENGTH(ch)) : -1; 3505} 3506 3507/** 3508 * Match a string at text[pos] and return the index of the next 3509 * character upon success. Return -1 on failure. Match a run of 3510 * white space in str with a run of white space in text. 3511 */ 3512int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) { 3513 for (int32_t i=0; i<str.length() && pos >= 0; ) { 3514 UChar32 ch = str.char32At(i); 3515 i += U16_LENGTH(ch); 3516 if (PatternProps::isWhiteSpace(ch)) { 3517 i = skipPatternWhiteSpace(str, i); 3518 } 3519 pos = match(text, pos, ch); 3520 } 3521 return pos; 3522} 3523 3524UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol, 3525 UnicodeSet *sset, UChar32 schar) 3526{ 3527 if (sset != NULL) { 3528 return sset->contains(schar); 3529 } 3530 3531 return text.compare(position, length, symbol) == 0; 3532} 3533 3534UBool DecimalFormat::matchDecimal(UChar32 symbolChar, 3535 UBool sawDecimal, UChar32 sawDecimalChar, 3536 const UnicodeSet *sset, UChar32 schar) { 3537 if(sawDecimal) { 3538 return schar==sawDecimalChar; 3539 } else if(schar==symbolChar) { 3540 return TRUE; 3541 } else if(sset!=NULL) { 3542 return sset->contains(schar); 3543 } else { 3544 return FALSE; 3545 } 3546} 3547 3548UBool DecimalFormat::matchGrouping(UChar32 groupingChar, 3549 UBool sawGrouping, UChar32 sawGroupingChar, 3550 const UnicodeSet *sset, 3551 UChar32 /*decimalChar*/, const UnicodeSet *decimalSet, 3552 UChar32 schar) { 3553 if(sawGrouping) { 3554 return schar==sawGroupingChar; // previously found 3555 } else if(schar==groupingChar) { 3556 return TRUE; // char from symbols 3557 } else if(sset!=NULL) { 3558 return sset->contains(schar) && // in groupingSet but... 3559 ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet 3560 } else { 3561 return FALSE; 3562 } 3563} 3564 3565 3566 3567//------------------------------------------------------------------------------ 3568// Gets the pointer to the localized decimal format symbols 3569 3570const DecimalFormatSymbols* 3571DecimalFormat::getDecimalFormatSymbols() const 3572{ 3573 return fSymbols; 3574} 3575 3576//------------------------------------------------------------------------------ 3577// De-owning the current localized symbols and adopt the new symbols. 3578 3579void 3580DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) 3581{ 3582 if (symbolsToAdopt == NULL) { 3583 return; // do not allow caller to set fSymbols to NULL 3584 } 3585 3586 UBool sameSymbols = FALSE; 3587 if (fSymbols != NULL) { 3588 sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == 3589 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) && 3590 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == 3591 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 3592 delete fSymbols; 3593 } 3594 3595 fSymbols = symbolsToAdopt; 3596 if (!sameSymbols) { 3597 // If the currency symbols are the same, there is no need to recalculate. 3598 setCurrencyForSymbols(); 3599 } 3600 expandAffixes(NULL); 3601#if UCONFIG_FORMAT_FASTPATHS_49 3602 handleChanged(); 3603#endif 3604} 3605//------------------------------------------------------------------------------ 3606// Setting the symbols is equlivalent to adopting a newly created localized 3607// symbols. 3608 3609void 3610DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) 3611{ 3612 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); 3613#if UCONFIG_FORMAT_FASTPATHS_49 3614 handleChanged(); 3615#endif 3616} 3617 3618 3619const CurrencyPluralInfo* 3620DecimalFormat::getCurrencyPluralInfo(void) const 3621{ 3622 return fCurrencyPluralInfo; 3623} 3624 3625 3626void 3627DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) 3628{ 3629 if (toAdopt != NULL) { 3630 delete fCurrencyPluralInfo; 3631 fCurrencyPluralInfo = toAdopt; 3632 // re-set currency affix patterns and currency affixes. 3633 if (fCurrencySignCount != fgCurrencySignCountZero) { 3634 UErrorCode status = U_ZERO_ERROR; 3635 if (fAffixPatternsForCurrency) { 3636 deleteHashForAffixPattern(); 3637 } 3638 setupCurrencyAffixPatterns(status); 3639 if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) { 3640 // only setup the affixes of the plural pattern. 3641 setupCurrencyAffixes(fFormatPattern, FALSE, TRUE, status); 3642 } 3643 } 3644 } 3645#if UCONFIG_FORMAT_FASTPATHS_49 3646 handleChanged(); 3647#endif 3648} 3649 3650void 3651DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) 3652{ 3653 adoptCurrencyPluralInfo(info.clone()); 3654#if UCONFIG_FORMAT_FASTPATHS_49 3655 handleChanged(); 3656#endif 3657} 3658 3659 3660/** 3661 * Update the currency object to match the symbols. This method 3662 * is used only when the caller has passed in a symbols object 3663 * that may not be the default object for its locale. 3664 */ 3665void 3666DecimalFormat::setCurrencyForSymbols() { 3667 /*Bug 4212072 3668 Update the affix strings accroding to symbols in order to keep 3669 the affix strings up to date. 3670 [Richard/GCL] 3671 */ 3672 3673 // With the introduction of the Currency object, the currency 3674 // symbols in the DFS object are ignored. For backward 3675 // compatibility, we check any explicitly set DFS object. If it 3676 // is a default symbols object for its locale, we change the 3677 // currency object to one for that locale. If it is custom, 3678 // we set the currency to null. 3679 UErrorCode ec = U_ZERO_ERROR; 3680 const UChar* c = NULL; 3681 const char* loc = fSymbols->getLocale().getName(); 3682 UChar intlCurrencySymbol[4]; 3683 ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec); 3684 UnicodeString currencySymbol; 3685 3686 uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec); 3687 if (U_SUCCESS(ec) 3688 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol 3689 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == UnicodeString(intlCurrencySymbol)) 3690 { 3691 // Trap an error in mapping locale to currency. If we can't 3692 // map, then don't fail and set the currency to "". 3693 c = intlCurrencySymbol; 3694 } 3695 ec = U_ZERO_ERROR; // reset local error code! 3696 setCurrencyInternally(c, ec); 3697#if UCONFIG_FORMAT_FASTPATHS_49 3698 handleChanged(); 3699#endif 3700} 3701 3702 3703//------------------------------------------------------------------------------ 3704// Gets the positive prefix of the number pattern. 3705 3706UnicodeString& 3707DecimalFormat::getPositivePrefix(UnicodeString& result) const 3708{ 3709 result = fPositivePrefix; 3710 return result; 3711} 3712 3713//------------------------------------------------------------------------------ 3714// Sets the positive prefix of the number pattern. 3715 3716void 3717DecimalFormat::setPositivePrefix(const UnicodeString& newValue) 3718{ 3719 fPositivePrefix = newValue; 3720 delete fPosPrefixPattern; 3721 fPosPrefixPattern = 0; 3722#if UCONFIG_FORMAT_FASTPATHS_49 3723 handleChanged(); 3724#endif 3725} 3726 3727//------------------------------------------------------------------------------ 3728// Gets the negative prefix of the number pattern. 3729 3730UnicodeString& 3731DecimalFormat::getNegativePrefix(UnicodeString& result) const 3732{ 3733 result = fNegativePrefix; 3734 return result; 3735} 3736 3737//------------------------------------------------------------------------------ 3738// Gets the negative prefix of the number pattern. 3739 3740void 3741DecimalFormat::setNegativePrefix(const UnicodeString& newValue) 3742{ 3743 fNegativePrefix = newValue; 3744 delete fNegPrefixPattern; 3745 fNegPrefixPattern = 0; 3746#if UCONFIG_FORMAT_FASTPATHS_49 3747 handleChanged(); 3748#endif 3749} 3750 3751//------------------------------------------------------------------------------ 3752// Gets the positive suffix of the number pattern. 3753 3754UnicodeString& 3755DecimalFormat::getPositiveSuffix(UnicodeString& result) const 3756{ 3757 result = fPositiveSuffix; 3758 return result; 3759} 3760 3761//------------------------------------------------------------------------------ 3762// Sets the positive suffix of the number pattern. 3763 3764void 3765DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) 3766{ 3767 fPositiveSuffix = newValue; 3768 delete fPosSuffixPattern; 3769 fPosSuffixPattern = 0; 3770#if UCONFIG_FORMAT_FASTPATHS_49 3771 handleChanged(); 3772#endif 3773} 3774 3775//------------------------------------------------------------------------------ 3776// Gets the negative suffix of the number pattern. 3777 3778UnicodeString& 3779DecimalFormat::getNegativeSuffix(UnicodeString& result) const 3780{ 3781 result = fNegativeSuffix; 3782 return result; 3783} 3784 3785//------------------------------------------------------------------------------ 3786// Sets the negative suffix of the number pattern. 3787 3788void 3789DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) 3790{ 3791 fNegativeSuffix = newValue; 3792 delete fNegSuffixPattern; 3793 fNegSuffixPattern = 0; 3794#if UCONFIG_FORMAT_FASTPATHS_49 3795 handleChanged(); 3796#endif 3797} 3798 3799//------------------------------------------------------------------------------ 3800// Gets the multiplier of the number pattern. 3801// Multipliers are stored as decimal numbers (DigitLists) because that 3802// is the most convenient for muliplying or dividing the numbers to be formatted. 3803// A NULL multiplier implies one, and the scaling operations are skipped. 3804 3805int32_t 3806DecimalFormat::getMultiplier() const 3807{ 3808 if (fMultiplier == NULL) { 3809 return 1; 3810 } else { 3811 return fMultiplier->getLong(); 3812 } 3813} 3814 3815//------------------------------------------------------------------------------ 3816// Sets the multiplier of the number pattern. 3817void 3818DecimalFormat::setMultiplier(int32_t newValue) 3819{ 3820// if (newValue == 0) { 3821// throw new IllegalArgumentException("Bad multiplier: " + newValue); 3822// } 3823 if (newValue == 0) { 3824 newValue = 1; // one being the benign default value for a multiplier. 3825 } 3826 if (newValue == 1) { 3827 delete fMultiplier; 3828 fMultiplier = NULL; 3829 } else { 3830 if (fMultiplier == NULL) { 3831 fMultiplier = new DigitList; 3832 } 3833 if (fMultiplier != NULL) { 3834 fMultiplier->set(newValue); 3835 } 3836 } 3837#if UCONFIG_FORMAT_FASTPATHS_49 3838 handleChanged(); 3839#endif 3840} 3841 3842/** 3843 * Get the rounding increment. 3844 * @return A positive rounding increment, or 0.0 if rounding 3845 * is not in effect. 3846 * @see #setRoundingIncrement 3847 * @see #getRoundingMode 3848 * @see #setRoundingMode 3849 */ 3850double DecimalFormat::getRoundingIncrement() const { 3851 if (fRoundingIncrement == NULL) { 3852 return 0.0; 3853 } else { 3854 return fRoundingIncrement->getDouble(); 3855 } 3856} 3857 3858/** 3859 * Set the rounding increment. This method also controls whether 3860 * rounding is enabled. 3861 * @param newValue A positive rounding increment, or 0.0 to disable rounding. 3862 * Negative increments are equivalent to 0.0. 3863 * @see #getRoundingIncrement 3864 * @see #getRoundingMode 3865 * @see #setRoundingMode 3866 */ 3867void DecimalFormat::setRoundingIncrement(double newValue) { 3868 if (newValue > 0.0) { 3869 if (fRoundingIncrement == NULL) { 3870 fRoundingIncrement = new DigitList(); 3871 } 3872 if (fRoundingIncrement != NULL) { 3873 fRoundingIncrement->set(newValue); 3874 return; 3875 } 3876 } 3877 // These statements are executed if newValue is less than 0.0 3878 // or fRoundingIncrement could not be created. 3879 delete fRoundingIncrement; 3880 fRoundingIncrement = NULL; 3881#if UCONFIG_FORMAT_FASTPATHS_49 3882 handleChanged(); 3883#endif 3884} 3885 3886/** 3887 * Get the rounding mode. 3888 * @return A rounding mode 3889 * @see #setRoundingIncrement 3890 * @see #getRoundingIncrement 3891 * @see #setRoundingMode 3892 */ 3893DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const { 3894 return fRoundingMode; 3895} 3896 3897/** 3898 * Set the rounding mode. This has no effect unless the rounding 3899 * increment is greater than zero. 3900 * @param roundingMode A rounding mode 3901 * @see #setRoundingIncrement 3902 * @see #getRoundingIncrement 3903 * @see #getRoundingMode 3904 */ 3905void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) { 3906 fRoundingMode = roundingMode; 3907#if UCONFIG_FORMAT_FASTPATHS_49 3908 handleChanged(); 3909#endif 3910} 3911 3912/** 3913 * Get the width to which the output of <code>format()</code> is padded. 3914 * @return the format width, or zero if no padding is in effect 3915 * @see #setFormatWidth 3916 * @see #getPadCharacter 3917 * @see #setPadCharacter 3918 * @see #getPadPosition 3919 * @see #setPadPosition 3920 */ 3921int32_t DecimalFormat::getFormatWidth() const { 3922 return fFormatWidth; 3923} 3924 3925/** 3926 * Set the width to which the output of <code>format()</code> is padded. 3927 * This method also controls whether padding is enabled. 3928 * @param width the width to which to pad the result of 3929 * <code>format()</code>, or zero to disable padding. A negative 3930 * width is equivalent to 0. 3931 * @see #getFormatWidth 3932 * @see #getPadCharacter 3933 * @see #setPadCharacter 3934 * @see #getPadPosition 3935 * @see #setPadPosition 3936 */ 3937void DecimalFormat::setFormatWidth(int32_t width) { 3938 fFormatWidth = (width > 0) ? width : 0; 3939#if UCONFIG_FORMAT_FASTPATHS_49 3940 handleChanged(); 3941#endif 3942} 3943 3944UnicodeString DecimalFormat::getPadCharacterString() const { 3945 return UnicodeString(fPad); 3946} 3947 3948void DecimalFormat::setPadCharacter(const UnicodeString &padChar) { 3949 if (padChar.length() > 0) { 3950 fPad = padChar.char32At(0); 3951 } 3952 else { 3953 fPad = kDefaultPad; 3954 } 3955#if UCONFIG_FORMAT_FASTPATHS_49 3956 handleChanged(); 3957#endif 3958} 3959 3960/** 3961 * Get the position at which padding will take place. This is the location 3962 * at which padding will be inserted if the result of <code>format()</code> 3963 * is shorter than the format width. 3964 * @return the pad position, one of <code>kPadBeforePrefix</code>, 3965 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 3966 * <code>kPadAfterSuffix</code>. 3967 * @see #setFormatWidth 3968 * @see #getFormatWidth 3969 * @see #setPadCharacter 3970 * @see #getPadCharacter 3971 * @see #setPadPosition 3972 * @see #kPadBeforePrefix 3973 * @see #kPadAfterPrefix 3974 * @see #kPadBeforeSuffix 3975 * @see #kPadAfterSuffix 3976 */ 3977DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const { 3978 return fPadPosition; 3979} 3980 3981/** 3982 * <strong><font face=helvetica color=red>NEW</font></strong> 3983 * Set the position at which padding will take place. This is the location 3984 * at which padding will be inserted if the result of <code>format()</code> 3985 * is shorter than the format width. This has no effect unless padding is 3986 * enabled. 3987 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>, 3988 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 3989 * <code>kPadAfterSuffix</code>. 3990 * @see #setFormatWidth 3991 * @see #getFormatWidth 3992 * @see #setPadCharacter 3993 * @see #getPadCharacter 3994 * @see #getPadPosition 3995 * @see #kPadBeforePrefix 3996 * @see #kPadAfterPrefix 3997 * @see #kPadBeforeSuffix 3998 * @see #kPadAfterSuffix 3999 */ 4000void DecimalFormat::setPadPosition(EPadPosition padPos) { 4001 fPadPosition = padPos; 4002#if UCONFIG_FORMAT_FASTPATHS_49 4003 handleChanged(); 4004#endif 4005} 4006 4007/** 4008 * Return whether or not scientific notation is used. 4009 * @return TRUE if this object formats and parses scientific notation 4010 * @see #setScientificNotation 4011 * @see #getMinimumExponentDigits 4012 * @see #setMinimumExponentDigits 4013 * @see #isExponentSignAlwaysShown 4014 * @see #setExponentSignAlwaysShown 4015 */ 4016UBool DecimalFormat::isScientificNotation() const { 4017 return fUseExponentialNotation; 4018} 4019 4020/** 4021 * Set whether or not scientific notation is used. 4022 * @param useScientific TRUE if this object formats and parses scientific 4023 * notation 4024 * @see #isScientificNotation 4025 * @see #getMinimumExponentDigits 4026 * @see #setMinimumExponentDigits 4027 * @see #isExponentSignAlwaysShown 4028 * @see #setExponentSignAlwaysShown 4029 */ 4030void DecimalFormat::setScientificNotation(UBool useScientific) { 4031 fUseExponentialNotation = useScientific; 4032#if UCONFIG_FORMAT_FASTPATHS_49 4033 handleChanged(); 4034#endif 4035} 4036 4037/** 4038 * Return the minimum exponent digits that will be shown. 4039 * @return the minimum exponent digits that will be shown 4040 * @see #setScientificNotation 4041 * @see #isScientificNotation 4042 * @see #setMinimumExponentDigits 4043 * @see #isExponentSignAlwaysShown 4044 * @see #setExponentSignAlwaysShown 4045 */ 4046int8_t DecimalFormat::getMinimumExponentDigits() const { 4047 return fMinExponentDigits; 4048} 4049 4050/** 4051 * Set the minimum exponent digits that will be shown. This has no 4052 * effect unless scientific notation is in use. 4053 * @param minExpDig a value >= 1 indicating the fewest exponent digits 4054 * that will be shown. Values less than 1 will be treated as 1. 4055 * @see #setScientificNotation 4056 * @see #isScientificNotation 4057 * @see #getMinimumExponentDigits 4058 * @see #isExponentSignAlwaysShown 4059 * @see #setExponentSignAlwaysShown 4060 */ 4061void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) { 4062 fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1); 4063#if UCONFIG_FORMAT_FASTPATHS_49 4064 handleChanged(); 4065#endif 4066} 4067 4068/** 4069 * Return whether the exponent sign is always shown. 4070 * @return TRUE if the exponent is always prefixed with either the 4071 * localized minus sign or the localized plus sign, false if only negative 4072 * exponents are prefixed with the localized minus sign. 4073 * @see #setScientificNotation 4074 * @see #isScientificNotation 4075 * @see #setMinimumExponentDigits 4076 * @see #getMinimumExponentDigits 4077 * @see #setExponentSignAlwaysShown 4078 */ 4079UBool DecimalFormat::isExponentSignAlwaysShown() const { 4080 return fExponentSignAlwaysShown; 4081} 4082 4083/** 4084 * Set whether the exponent sign is always shown. This has no effect 4085 * unless scientific notation is in use. 4086 * @param expSignAlways TRUE if the exponent is always prefixed with either 4087 * the localized minus sign or the localized plus sign, false if only 4088 * negative exponents are prefixed with the localized minus sign. 4089 * @see #setScientificNotation 4090 * @see #isScientificNotation 4091 * @see #setMinimumExponentDigits 4092 * @see #getMinimumExponentDigits 4093 * @see #isExponentSignAlwaysShown 4094 */ 4095void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { 4096 fExponentSignAlwaysShown = expSignAlways; 4097#if UCONFIG_FORMAT_FASTPATHS_49 4098 handleChanged(); 4099#endif 4100} 4101 4102//------------------------------------------------------------------------------ 4103// Gets the grouping size of the number pattern. For example, thousand or 10 4104// thousand groupings. 4105 4106int32_t 4107DecimalFormat::getGroupingSize() const 4108{ 4109 return fGroupingSize; 4110} 4111 4112//------------------------------------------------------------------------------ 4113// Gets the grouping size of the number pattern. 4114 4115void 4116DecimalFormat::setGroupingSize(int32_t newValue) 4117{ 4118 fGroupingSize = newValue; 4119#if UCONFIG_FORMAT_FASTPATHS_49 4120 handleChanged(); 4121#endif 4122} 4123 4124//------------------------------------------------------------------------------ 4125 4126int32_t 4127DecimalFormat::getSecondaryGroupingSize() const 4128{ 4129 return fGroupingSize2; 4130} 4131 4132//------------------------------------------------------------------------------ 4133 4134void 4135DecimalFormat::setSecondaryGroupingSize(int32_t newValue) 4136{ 4137 fGroupingSize2 = newValue; 4138#if UCONFIG_FORMAT_FASTPATHS_49 4139 handleChanged(); 4140#endif 4141} 4142 4143//------------------------------------------------------------------------------ 4144// Checks if to show the decimal separator. 4145 4146UBool 4147DecimalFormat::isDecimalSeparatorAlwaysShown() const 4148{ 4149 return fDecimalSeparatorAlwaysShown; 4150} 4151 4152//------------------------------------------------------------------------------ 4153// Sets to always show the decimal separator. 4154 4155void 4156DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) 4157{ 4158 fDecimalSeparatorAlwaysShown = newValue; 4159#if UCONFIG_FORMAT_FASTPATHS_49 4160 handleChanged(); 4161#endif 4162} 4163 4164//------------------------------------------------------------------------------ 4165// Emits the pattern of this DecimalFormat instance. 4166 4167UnicodeString& 4168DecimalFormat::toPattern(UnicodeString& result) const 4169{ 4170 return toPattern(result, FALSE); 4171} 4172 4173//------------------------------------------------------------------------------ 4174// Emits the localized pattern this DecimalFormat instance. 4175 4176UnicodeString& 4177DecimalFormat::toLocalizedPattern(UnicodeString& result) const 4178{ 4179 return toPattern(result, TRUE); 4180} 4181 4182//------------------------------------------------------------------------------ 4183/** 4184 * Expand the affix pattern strings into the expanded affix strings. If any 4185 * affix pattern string is null, do not expand it. This method should be 4186 * called any time the symbols or the affix patterns change in order to keep 4187 * the expanded affix strings up to date. 4188 * This method also will be called before formatting if format currency 4189 * plural names, since the plural name is not a static one, it is 4190 * based on the currency plural count, the affix will be known only 4191 * after the currency plural count is know. 4192 * In which case, the parameter 4193 * 'pluralCount' will be a non-null currency plural count. 4194 * In all other cases, the 'pluralCount' is null, which means it is not needed. 4195 */ 4196void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) { 4197 FieldPositionHandler none; 4198 if (fPosPrefixPattern != 0) { 4199 expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCount); 4200 } 4201 if (fPosSuffixPattern != 0) { 4202 expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCount); 4203 } 4204 if (fNegPrefixPattern != 0) { 4205 expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCount); 4206 } 4207 if (fNegSuffixPattern != 0) { 4208 expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCount); 4209 } 4210#ifdef FMT_DEBUG 4211 UnicodeString s; 4212 s.append(UnicodeString("[")) 4213 .append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fPosSuffixPattern)) 4214 .append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fNegSuffixPattern)) 4215 .append((UnicodeString)"]->[") 4216 .append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuffix) 4217 .append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeString)"|").append(fNegativeSuffix) 4218 .append((UnicodeString)"]\n"); 4219 debugout(s); 4220#endif 4221} 4222 4223/** 4224 * Expand an affix pattern into an affix string. All characters in the 4225 * pattern are literal unless prefixed by kQuote. The following characters 4226 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, 4227 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote + 4228 * kCurrencySign + kCurrencySign), it is interpreted as an international 4229 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as 4230 * currency plural long names, such as "US Dollars". 4231 * Any other character after a kQuote represents itself. 4232 * kQuote must be followed by another character; kQuote may not occur by 4233 * itself at the end of the pattern. 4234 * 4235 * This method is used in two distinct ways. First, it is used to expand 4236 * the stored affix patterns into actual affixes. For this usage, doFormat 4237 * must be false. Second, it is used to expand the stored affix patterns 4238 * given a specific number (doFormat == true), for those rare cases in 4239 * which a currency format references a ChoiceFormat (e.g., en_IN display 4240 * name for INR). The number itself is taken from digitList. 4241 * 4242 * When used in the first way, this method has a side effect: It sets 4243 * currencyChoice to a ChoiceFormat object, if the currency's display name 4244 * in this locale is a ChoiceFormat pattern (very rare). It only does this 4245 * if currencyChoice is null to start with. 4246 * 4247 * @param pattern the non-null, fPossibly empty pattern 4248 * @param affix string to receive the expanded equivalent of pattern. 4249 * Previous contents are deleted. 4250 * @param doFormat if false, then the pattern will be expanded, and if a 4251 * currency symbol is encountered that expands to a ChoiceFormat, the 4252 * currencyChoice member variable will be initialized if it is null. If 4253 * doFormat is true, then it is assumed that the currencyChoice has been 4254 * created, and it will be used to format the value in digitList. 4255 * @param pluralCount the plural count. It is only used for currency 4256 * plural format. In which case, it is the plural 4257 * count of the currency amount. For example, 4258 * in en_US, it is the singular "one", or the plural 4259 * "other". For all other cases, it is null, and 4260 * is not being used. 4261 */ 4262void DecimalFormat::expandAffix(const UnicodeString& pattern, 4263 UnicodeString& affix, 4264 double number, 4265 FieldPositionHandler& handler, 4266 UBool doFormat, 4267 const UnicodeString* pluralCount) const { 4268 affix.remove(); 4269 for (int i=0; i<pattern.length(); ) { 4270 UChar32 c = pattern.char32At(i); 4271 i += U16_LENGTH(c); 4272 if (c == kQuote) { 4273 c = pattern.char32At(i); 4274 i += U16_LENGTH(c); 4275 int beginIdx = affix.length(); 4276 switch (c) { 4277 case kCurrencySign: { 4278 // As of ICU 2.2 we use the currency object, and 4279 // ignore the currency symbols in the DFS, unless 4280 // we have a null currency object. This occurs if 4281 // resurrecting a pre-2.2 object or if the user 4282 // sets a custom DFS. 4283 UBool intl = i<pattern.length() && 4284 pattern.char32At(i) == kCurrencySign; 4285 UBool plural = FALSE; 4286 if (intl) { 4287 ++i; 4288 plural = i<pattern.length() && 4289 pattern.char32At(i) == kCurrencySign; 4290 if (plural) { 4291 intl = FALSE; 4292 ++i; 4293 } 4294 } 4295 const UChar* currencyUChars = getCurrency(); 4296 if (currencyUChars[0] != 0) { 4297 UErrorCode ec = U_ZERO_ERROR; 4298 if (plural && pluralCount != NULL) { 4299 // plural name is only needed when pluralCount != null, 4300 // which means when formatting currency plural names. 4301 // For other cases, pluralCount == null, 4302 // and plural names are not needed. 4303 int32_t len; 4304 CharString pluralCountChar; 4305 pluralCountChar.appendInvariantChars(*pluralCount, ec); 4306 UBool isChoiceFormat; 4307 const UChar* s = ucurr_getPluralName(currencyUChars, 4308 fSymbols != NULL ? fSymbols->getLocale().getName() : 4309 Locale::getDefault().getName(), &isChoiceFormat, 4310 pluralCountChar.data(), &len, &ec); 4311 affix += UnicodeString(s, len); 4312 handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 4313 } else if(intl) { 4314 affix.append(currencyUChars, -1); 4315 handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 4316 } else { 4317 int32_t len; 4318 UBool isChoiceFormat; 4319 // If fSymbols is NULL, use default locale 4320 const UChar* s = ucurr_getName(currencyUChars, 4321 fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(), 4322 UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec); 4323 if (isChoiceFormat) { 4324 // Two modes here: If doFormat is false, we set up 4325 // currencyChoice. If doFormat is true, we use the 4326 // previously created currencyChoice to format the 4327 // value in digitList. 4328 if (!doFormat) { 4329 // If the currency is handled by a ChoiceFormat, 4330 // then we're not going to use the expanded 4331 // patterns. Instantiate the ChoiceFormat and 4332 // return. 4333 if (fCurrencyChoice == NULL) { 4334 // TODO Replace double-check with proper thread-safe code 4335 ChoiceFormat* fmt = new ChoiceFormat(UnicodeString(s), ec); 4336 if (U_SUCCESS(ec)) { 4337 umtx_lock(NULL); 4338 if (fCurrencyChoice == NULL) { 4339 // Cast away const 4340 ((DecimalFormat*)this)->fCurrencyChoice = fmt; 4341 fmt = NULL; 4342 } 4343 umtx_unlock(NULL); 4344 delete fmt; 4345 } 4346 } 4347 // We could almost return null or "" here, since the 4348 // expanded affixes are almost not used at all 4349 // in this situation. However, one method -- 4350 // toPattern() -- still does use the expanded 4351 // affixes, in order to set up a padding 4352 // pattern. We use the CURRENCY_SIGN as a 4353 // placeholder. 4354 affix.append(kCurrencySign); 4355 } else { 4356 if (fCurrencyChoice != NULL) { 4357 FieldPosition pos(0); // ignored 4358 if (number < 0) { 4359 number = -number; 4360 } 4361 fCurrencyChoice->format(number, affix, pos); 4362 } else { 4363 // We only arrive here if the currency choice 4364 // format in the locale data is INVALID. 4365 affix.append(currencyUChars, -1); 4366 handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 4367 } 4368 } 4369 continue; 4370 } 4371 affix += UnicodeString(s, len); 4372 handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 4373 } 4374 } else { 4375 if(intl) { 4376 affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 4377 } else { 4378 affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol); 4379 } 4380 handler.addAttribute(kCurrencyField, beginIdx, affix.length()); 4381 } 4382 break; 4383 } 4384 case kPatternPercent: 4385 affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 4386 handler.addAttribute(kPercentField, beginIdx, affix.length()); 4387 break; 4388 case kPatternPerMill: 4389 affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 4390 handler.addAttribute(kPermillField, beginIdx, affix.length()); 4391 break; 4392 case kPatternPlus: 4393 affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 4394 handler.addAttribute(kSignField, beginIdx, affix.length()); 4395 break; 4396 case kPatternMinus: 4397 affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 4398 handler.addAttribute(kSignField, beginIdx, affix.length()); 4399 break; 4400 default: 4401 affix.append(c); 4402 break; 4403 } 4404 } 4405 else { 4406 affix.append(c); 4407 } 4408 } 4409} 4410 4411/** 4412 * Append an affix to the given StringBuffer. 4413 * @param buf buffer to append to 4414 * @param isNegative 4415 * @param isPrefix 4416 */ 4417int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number, 4418 FieldPositionHandler& handler, 4419 UBool isNegative, UBool isPrefix) const { 4420 // plural format precedes choice format 4421 if (fCurrencyChoice != 0 && 4422 fCurrencySignCount != fgCurrencySignCountInPluralFormat) { 4423 const UnicodeString* affixPat; 4424 if (isPrefix) { 4425 affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern; 4426 } else { 4427 affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern; 4428 } 4429 if (affixPat) { 4430 UnicodeString affixBuf; 4431 expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL); 4432 buf.append(affixBuf); 4433 return affixBuf.length(); 4434 } 4435 // else someone called a function that reset the pattern. 4436 } 4437 4438 const UnicodeString* affix; 4439 if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) { 4440 // TODO: get an accurate count of visible fraction digits. 4441 UnicodeString pluralCount; 4442 int32_t minFractionDigits = this->getMinimumFractionDigits(); 4443 if (minFractionDigits > 0) { 4444 FixedDecimal ni(number, this->getMinimumFractionDigits()); 4445 pluralCount = fCurrencyPluralInfo->getPluralRules()->select(ni); 4446 } else { 4447 pluralCount = fCurrencyPluralInfo->getPluralRules()->select(number); 4448 } 4449 AffixesForCurrency* oneSet; 4450 if (fStyle == UNUM_CURRENCY_PLURAL) { 4451 oneSet = (AffixesForCurrency*)fPluralAffixesForCurrency->get(pluralCount); 4452 } else { 4453 oneSet = (AffixesForCurrency*)fAffixesForCurrency->get(pluralCount); 4454 } 4455 if (isPrefix) { 4456 affix = isNegative ? &oneSet->negPrefixForCurrency : 4457 &oneSet->posPrefixForCurrency; 4458 } else { 4459 affix = isNegative ? &oneSet->negSuffixForCurrency : 4460 &oneSet->posSuffixForCurrency; 4461 } 4462 } else { 4463 if (isPrefix) { 4464 affix = isNegative ? &fNegativePrefix : &fPositivePrefix; 4465 } else { 4466 affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix; 4467 } 4468 } 4469 4470 int32_t begin = (int) buf.length(); 4471 4472 buf.append(*affix); 4473 4474 if (handler.isRecording()) { 4475 int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol)); 4476 if (offset > -1) { 4477 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol); 4478 handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length()); 4479 } 4480 4481 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 4482 if (offset > -1) { 4483 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 4484 handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length()); 4485 } 4486 4487 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)); 4488 if (offset > -1) { 4489 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 4490 handler.addAttribute(kSignField, begin + offset, begin + offset + aff.length()); 4491 } 4492 4493 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)); 4494 if (offset > -1) { 4495 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 4496 handler.addAttribute(kPercentField, begin + offset, begin + offset + aff.length()); 4497 } 4498 4499 offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)); 4500 if (offset > -1) { 4501 UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 4502 handler.addAttribute(kPermillField, begin + offset, begin + offset + aff.length()); 4503 } 4504 } 4505 return affix->length(); 4506} 4507 4508/** 4509 * Appends an affix pattern to the given StringBuffer, quoting special 4510 * characters as needed. Uses the internal affix pattern, if that exists, 4511 * or the literal affix, if the internal affix pattern is null. The 4512 * appended string will generate the same affix pattern (or literal affix) 4513 * when passed to toPattern(). 4514 * 4515 * @param appendTo the affix string is appended to this 4516 * @param affixPattern a pattern such as fPosPrefixPattern; may be null 4517 * @param expAffix a corresponding expanded affix, such as fPositivePrefix. 4518 * Ignored unless affixPattern is null. If affixPattern is null, then 4519 * expAffix is appended as a literal affix. 4520 * @param localized true if the appended pattern should contain localized 4521 * pattern characters; otherwise, non-localized pattern chars are appended 4522 */ 4523void DecimalFormat::appendAffixPattern(UnicodeString& appendTo, 4524 const UnicodeString* affixPattern, 4525 const UnicodeString& expAffix, 4526 UBool localized) const { 4527 if (affixPattern == 0) { 4528 appendAffixPattern(appendTo, expAffix, localized); 4529 } else { 4530 int i; 4531 for (int pos=0; pos<affixPattern->length(); pos=i) { 4532 i = affixPattern->indexOf(kQuote, pos); 4533 if (i < 0) { 4534 UnicodeString s; 4535 affixPattern->extractBetween(pos, affixPattern->length(), s); 4536 appendAffixPattern(appendTo, s, localized); 4537 break; 4538 } 4539 if (i > pos) { 4540 UnicodeString s; 4541 affixPattern->extractBetween(pos, i, s); 4542 appendAffixPattern(appendTo, s, localized); 4543 } 4544 UChar32 c = affixPattern->char32At(++i); 4545 ++i; 4546 if (c == kQuote) { 4547 appendTo.append(c).append(c); 4548 // Fall through and append another kQuote below 4549 } else if (c == kCurrencySign && 4550 i<affixPattern->length() && 4551 affixPattern->char32At(i) == kCurrencySign) { 4552 ++i; 4553 appendTo.append(c).append(c); 4554 } else if (localized) { 4555 switch (c) { 4556 case kPatternPercent: 4557 appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 4558 break; 4559 case kPatternPerMill: 4560 appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 4561 break; 4562 case kPatternPlus: 4563 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 4564 break; 4565 case kPatternMinus: 4566 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 4567 break; 4568 default: 4569 appendTo.append(c); 4570 } 4571 } else { 4572 appendTo.append(c); 4573 } 4574 } 4575 } 4576} 4577 4578/** 4579 * Append an affix to the given StringBuffer, using quotes if 4580 * there are special characters. Single quotes themselves must be 4581 * escaped in either case. 4582 */ 4583void 4584DecimalFormat::appendAffixPattern(UnicodeString& appendTo, 4585 const UnicodeString& affix, 4586 UBool localized) const { 4587 UBool needQuote; 4588 if(localized) { 4589 needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0 4590 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0 4591 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0 4592 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0 4593 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0 4594 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0 4595 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0 4596 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0 4597 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0 4598 || affix.indexOf(kCurrencySign) >= 0; 4599 } 4600 else { 4601 needQuote = affix.indexOf(kPatternZeroDigit) >= 0 4602 || affix.indexOf(kPatternGroupingSeparator) >= 0 4603 || affix.indexOf(kPatternDecimalSeparator) >= 0 4604 || affix.indexOf(kPatternPercent) >= 0 4605 || affix.indexOf(kPatternPerMill) >= 0 4606 || affix.indexOf(kPatternDigit) >= 0 4607 || affix.indexOf(kPatternSeparator) >= 0 4608 || affix.indexOf(kPatternExponent) >= 0 4609 || affix.indexOf(kPatternPlus) >= 0 4610 || affix.indexOf(kPatternMinus) >= 0 4611 || affix.indexOf(kCurrencySign) >= 0; 4612 } 4613 if (needQuote) 4614 appendTo += (UChar)0x0027 /*'\''*/; 4615 if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0) 4616 appendTo += affix; 4617 else { 4618 for (int32_t j = 0; j < affix.length(); ) { 4619 UChar32 c = affix.char32At(j); 4620 j += U16_LENGTH(c); 4621 appendTo += c; 4622 if (c == 0x0027 /*'\''*/) 4623 appendTo += c; 4624 } 4625 } 4626 if (needQuote) 4627 appendTo += (UChar)0x0027 /*'\''*/; 4628} 4629 4630//------------------------------------------------------------------------------ 4631 4632UnicodeString& 4633DecimalFormat::toPattern(UnicodeString& result, UBool localized) const 4634{ 4635 if (fStyle == UNUM_CURRENCY_PLURAL) { 4636 // the prefix or suffix pattern might not be defined yet, 4637 // so they can not be synthesized, 4638 // instead, get them directly. 4639 // but it might not be the actual pattern used in formatting. 4640 // the actual pattern used in formatting depends on the 4641 // formatted number's plural count. 4642 result = fFormatPattern; 4643 return result; 4644 } 4645 result.remove(); 4646 UChar32 zero, sigDigit = kPatternSignificantDigit; 4647 UnicodeString digit, group; 4648 int32_t i; 4649 int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits 4650 UnicodeString roundingDigits; 4651 int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1; 4652 UnicodeString padSpec; 4653 UBool useSigDig = areSignificantDigitsUsed(); 4654 4655 if (localized) { 4656 digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)); 4657 group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)); 4658 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 4659 if (useSigDig) { 4660 sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); 4661 } 4662 } 4663 else { 4664 digit.append((UChar)kPatternDigit); 4665 group.append((UChar)kPatternGroupingSeparator); 4666 zero = (UChar32)kPatternZeroDigit; 4667 } 4668 if (fFormatWidth > 0) { 4669 if (localized) { 4670 padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol)); 4671 } 4672 else { 4673 padSpec.append((UChar)kPatternPadEscape); 4674 } 4675 padSpec.append(fPad); 4676 } 4677 if (fRoundingIncrement != NULL) { 4678 for(i=0; i<fRoundingIncrement->getCount(); ++i) { 4679 roundingDigits.append(zero+(fRoundingIncrement->getDigitValue(i))); // Convert to Unicode digit 4680 } 4681 roundingDecimalPos = fRoundingIncrement->getDecimalAt(); 4682 } 4683 for (int32_t part=0; part<2; ++part) { 4684 if (padPos == kPadBeforePrefix) { 4685 result.append(padSpec); 4686 } 4687 appendAffixPattern(result, 4688 (part==0 ? fPosPrefixPattern : fNegPrefixPattern), 4689 (part==0 ? fPositivePrefix : fNegativePrefix), 4690 localized); 4691 if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) { 4692 result.append(padSpec); 4693 } 4694 int32_t sub0Start = result.length(); 4695 int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0; 4696 if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) { 4697 g += fGroupingSize2; 4698 } 4699 int32_t maxDig = 0, minDig = 0, maxSigDig = 0; 4700 if (useSigDig) { 4701 minDig = getMinimumSignificantDigits(); 4702 maxDig = maxSigDig = getMaximumSignificantDigits(); 4703 } else { 4704 minDig = getMinimumIntegerDigits(); 4705 maxDig = getMaximumIntegerDigits(); 4706 } 4707 if (fUseExponentialNotation) { 4708 if (maxDig > kMaxScientificIntegerDigits) { 4709 maxDig = 1; 4710 } 4711 } else if (useSigDig) { 4712 maxDig = _max(maxDig, g+1); 4713 } else { 4714 maxDig = _max(_max(g, getMinimumIntegerDigits()), 4715 roundingDecimalPos) + 1; 4716 } 4717 for (i = maxDig; i > 0; --i) { 4718 if (!fUseExponentialNotation && i<maxDig && 4719 isGroupingPosition(i)) { 4720 result.append(group); 4721 } 4722 if (useSigDig) { 4723 // #@,@### (maxSigDig == 5, minSigDig == 2) 4724 // 65 4321 (1-based pos, count from the right) 4725 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig) 4726 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig 4727 if (maxSigDig >= i && i > (maxSigDig - minDig)) { 4728 result.append(sigDigit); 4729 } else { 4730 result.append(digit); 4731 } 4732 } else { 4733 if (! roundingDigits.isEmpty()) { 4734 int32_t pos = roundingDecimalPos - i; 4735 if (pos >= 0 && pos < roundingDigits.length()) { 4736 result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero)); 4737 continue; 4738 } 4739 } 4740 if (i<=minDig) { 4741 result.append(zero); 4742 } else { 4743 result.append(digit); 4744 } 4745 } 4746 } 4747 if (!useSigDig) { 4748 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) { 4749 if (localized) { 4750 result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 4751 } 4752 else { 4753 result.append((UChar)kPatternDecimalSeparator); 4754 } 4755 } 4756 int32_t pos = roundingDecimalPos; 4757 for (i = 0; i < getMaximumFractionDigits(); ++i) { 4758 if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) { 4759 if (pos < 0) { 4760 result.append(zero); 4761 } 4762 else { 4763 result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero)); 4764 } 4765 ++pos; 4766 continue; 4767 } 4768 if (i<getMinimumFractionDigits()) { 4769 result.append(zero); 4770 } 4771 else { 4772 result.append(digit); 4773 } 4774 } 4775 } 4776 if (fUseExponentialNotation) { 4777 if (localized) { 4778 result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 4779 } 4780 else { 4781 result.append((UChar)kPatternExponent); 4782 } 4783 if (fExponentSignAlwaysShown) { 4784 if (localized) { 4785 result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 4786 } 4787 else { 4788 result.append((UChar)kPatternPlus); 4789 } 4790 } 4791 for (i=0; i<fMinExponentDigits; ++i) { 4792 result.append(zero); 4793 } 4794 } 4795 if (! padSpec.isEmpty() && !fUseExponentialNotation) { 4796 int32_t add = fFormatWidth - result.length() + sub0Start 4797 - ((part == 0) 4798 ? fPositivePrefix.length() + fPositiveSuffix.length() 4799 : fNegativePrefix.length() + fNegativeSuffix.length()); 4800 while (add > 0) { 4801 result.insert(sub0Start, digit); 4802 ++maxDig; 4803 --add; 4804 // Only add a grouping separator if we have at least 4805 // 2 additional characters to be added, so we don't 4806 // end up with ",###". 4807 if (add>1 && isGroupingPosition(maxDig)) { 4808 result.insert(sub0Start, group); 4809 --add; 4810 } 4811 } 4812 } 4813 if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) { 4814 result.append(padSpec); 4815 } 4816 if (part == 0) { 4817 appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized); 4818 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) { 4819 result.append(padSpec); 4820 } 4821 UBool isDefault = FALSE; 4822 if ((fNegSuffixPattern == fPosSuffixPattern && // both null 4823 fNegativeSuffix == fPositiveSuffix) 4824 || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 && 4825 *fNegSuffixPattern == *fPosSuffixPattern)) 4826 { 4827 if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL) 4828 { 4829 int32_t length = fPosPrefixPattern->length(); 4830 isDefault = fNegPrefixPattern->length() == (length+2) && 4831 (*fNegPrefixPattern)[(int32_t)0] == kQuote && 4832 (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus && 4833 fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0; 4834 } 4835 if (!isDefault && 4836 fNegPrefixPattern == NULL && fPosPrefixPattern == NULL) 4837 { 4838 int32_t length = fPositivePrefix.length(); 4839 isDefault = fNegativePrefix.length() == (length+1) && 4840 fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 && 4841 fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0; 4842 } 4843 } 4844 if (isDefault) { 4845 break; // Don't output default negative subpattern 4846 } else { 4847 if (localized) { 4848 result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol); 4849 } 4850 else { 4851 result.append((UChar)kPatternSeparator); 4852 } 4853 } 4854 } else { 4855 appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized); 4856 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) { 4857 result.append(padSpec); 4858 } 4859 } 4860 } 4861 4862 return result; 4863} 4864 4865//------------------------------------------------------------------------------ 4866 4867void 4868DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) 4869{ 4870 UParseError parseError; 4871 applyPattern(pattern, FALSE, parseError, status); 4872} 4873 4874//------------------------------------------------------------------------------ 4875 4876void 4877DecimalFormat::applyPattern(const UnicodeString& pattern, 4878 UParseError& parseError, 4879 UErrorCode& status) 4880{ 4881 applyPattern(pattern, FALSE, parseError, status); 4882} 4883//------------------------------------------------------------------------------ 4884 4885void 4886DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status) 4887{ 4888 UParseError parseError; 4889 applyPattern(pattern, TRUE,parseError,status); 4890} 4891 4892//------------------------------------------------------------------------------ 4893 4894void 4895DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, 4896 UParseError& parseError, 4897 UErrorCode& status) 4898{ 4899 applyPattern(pattern, TRUE,parseError,status); 4900} 4901 4902//------------------------------------------------------------------------------ 4903 4904void 4905DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern, 4906 UBool localized, 4907 UParseError& parseError, 4908 UErrorCode& status) 4909{ 4910 if (U_FAILURE(status)) 4911 { 4912 return; 4913 } 4914 DecimalFormatPatternParser patternParser; 4915 if (localized) { 4916 patternParser.useSymbols(*fSymbols); 4917 } 4918 fFormatPattern = pattern; 4919 DecimalFormatPattern out; 4920 patternParser.applyPatternWithoutExpandAffix( 4921 pattern, 4922 out, 4923 parseError, 4924 status); 4925 if (U_FAILURE(status)) { 4926 return; 4927 } 4928 4929 setMinimumIntegerDigits(out.fMinimumIntegerDigits); 4930 setMaximumIntegerDigits(out.fMaximumIntegerDigits); 4931 setMinimumFractionDigits(out.fMinimumFractionDigits); 4932 setMaximumFractionDigits(out.fMaximumFractionDigits); 4933 setSignificantDigitsUsed(out.fUseSignificantDigits); 4934 if (out.fUseSignificantDigits) { 4935 setMinimumSignificantDigits(out.fMinimumSignificantDigits); 4936 setMaximumSignificantDigits(out.fMaximumSignificantDigits); 4937 } 4938 fUseExponentialNotation = out.fUseExponentialNotation; 4939 if (out.fUseExponentialNotation) { 4940 fMinExponentDigits = out.fMinExponentDigits; 4941 } 4942 fExponentSignAlwaysShown = out.fExponentSignAlwaysShown; 4943 fCurrencySignCount = out.fCurrencySignCount; 4944 setGroupingUsed(out.fGroupingUsed); 4945 if (out.fGroupingUsed) { 4946 fGroupingSize = out.fGroupingSize; 4947 fGroupingSize2 = out.fGroupingSize2; 4948 } 4949 setMultiplier(out.fMultiplier); 4950 fDecimalSeparatorAlwaysShown = out.fDecimalSeparatorAlwaysShown; 4951 fFormatWidth = out.fFormatWidth; 4952 if (out.fRoundingIncrementUsed) { 4953 if (fRoundingIncrement != NULL) { 4954 *fRoundingIncrement = out.fRoundingIncrement; 4955 } else { 4956 fRoundingIncrement = new DigitList(out.fRoundingIncrement); 4957 /* test for NULL */ 4958 if (fRoundingIncrement == NULL) { 4959 status = U_MEMORY_ALLOCATION_ERROR; 4960 return; 4961 } 4962 } 4963 } else { 4964 setRoundingIncrement(0.0); 4965 } 4966 fPad = out.fPad; 4967 switch (out.fPadPosition) { 4968 case DecimalFormatPattern::kPadBeforePrefix: 4969 fPadPosition = kPadBeforePrefix; 4970 break; 4971 case DecimalFormatPattern::kPadAfterPrefix: 4972 fPadPosition = kPadAfterPrefix; 4973 break; 4974 case DecimalFormatPattern::kPadBeforeSuffix: 4975 fPadPosition = kPadBeforeSuffix; 4976 break; 4977 case DecimalFormatPattern::kPadAfterSuffix: 4978 fPadPosition = kPadAfterSuffix; 4979 break; 4980 } 4981 copyString(out.fNegPrefixPattern, out.fNegPatternsBogus, fNegPrefixPattern, status); 4982 copyString(out.fNegSuffixPattern, out.fNegPatternsBogus, fNegSuffixPattern, status); 4983 copyString(out.fPosPrefixPattern, out.fPosPatternsBogus, fPosPrefixPattern, status); 4984 copyString(out.fPosSuffixPattern, out.fPosPatternsBogus, fPosSuffixPattern, status); 4985} 4986 4987 4988void 4989DecimalFormat::expandAffixAdjustWidth(const UnicodeString* pluralCount) { 4990 expandAffixes(pluralCount); 4991 if (fFormatWidth > 0) { 4992 // Finish computing format width (see above) 4993 // TODO: how to handle fFormatWidth, 4994 // need to save in f(Plural)AffixesForCurrecy? 4995 fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length(); 4996 } 4997} 4998 4999 5000void 5001DecimalFormat::applyPattern(const UnicodeString& pattern, 5002 UBool localized, 5003 UParseError& parseError, 5004 UErrorCode& status) 5005{ 5006 // do the following re-set first. since they change private data by 5007 // apply pattern again. 5008 if (pattern.indexOf(kCurrencySign) != -1) { 5009 if (fCurrencyPluralInfo == NULL) { 5010 // initialize currencyPluralInfo if needed 5011 fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status); 5012 } 5013 if (fAffixPatternsForCurrency == NULL) { 5014 setupCurrencyAffixPatterns(status); 5015 } 5016 if (pattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) { 5017 // only setup the affixes of the current pattern. 5018 setupCurrencyAffixes(pattern, TRUE, FALSE, status); 5019 } 5020 } 5021 applyPatternWithoutExpandAffix(pattern, localized, parseError, status); 5022 expandAffixAdjustWidth(NULL); 5023#if UCONFIG_FORMAT_FASTPATHS_49 5024 handleChanged(); 5025#endif 5026} 5027 5028 5029void 5030DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount, 5031 const UnicodeString& pattern, 5032 UBool localized, 5033 UParseError& parseError, 5034 UErrorCode& status) { 5035 applyPatternWithoutExpandAffix(pattern, localized, parseError, status); 5036 expandAffixAdjustWidth(&pluralCount); 5037#if UCONFIG_FORMAT_FASTPATHS_49 5038 handleChanged(); 5039#endif 5040} 5041 5042 5043/** 5044 * Sets the maximum number of digits allowed in the integer portion of a 5045 * number. 5046 * @see NumberFormat#setMaximumIntegerDigits 5047 */ 5048void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) { 5049 NumberFormat::setMaximumIntegerDigits(_min(newValue, gDefaultMaxIntegerDigits)); 5050#if UCONFIG_FORMAT_FASTPATHS_49 5051 handleChanged(); 5052#endif 5053} 5054 5055/** 5056 * Sets the minimum number of digits allowed in the integer portion of a 5057 * number. This override limits the integer digit count to 309. 5058 * @see NumberFormat#setMinimumIntegerDigits 5059 */ 5060void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) { 5061 NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits)); 5062#if UCONFIG_FORMAT_FASTPATHS_49 5063 handleChanged(); 5064#endif 5065} 5066 5067/** 5068 * Sets the maximum number of digits allowed in the fraction portion of a 5069 * number. This override limits the fraction digit count to 340. 5070 * @see NumberFormat#setMaximumFractionDigits 5071 */ 5072void DecimalFormat::setMaximumFractionDigits(int32_t newValue) { 5073 NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits)); 5074#if UCONFIG_FORMAT_FASTPATHS_49 5075 handleChanged(); 5076#endif 5077} 5078 5079/** 5080 * Sets the minimum number of digits allowed in the fraction portion of a 5081 * number. This override limits the fraction digit count to 340. 5082 * @see NumberFormat#setMinimumFractionDigits 5083 */ 5084void DecimalFormat::setMinimumFractionDigits(int32_t newValue) { 5085 NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits)); 5086#if UCONFIG_FORMAT_FASTPATHS_49 5087 handleChanged(); 5088#endif 5089} 5090 5091int32_t DecimalFormat::getMinimumSignificantDigits() const { 5092 return fMinSignificantDigits; 5093} 5094 5095int32_t DecimalFormat::getMaximumSignificantDigits() const { 5096 return fMaxSignificantDigits; 5097} 5098 5099void DecimalFormat::setMinimumSignificantDigits(int32_t min) { 5100 if (min < 1) { 5101 min = 1; 5102 } 5103 // pin max sig dig to >= min 5104 int32_t max = _max(fMaxSignificantDigits, min); 5105 fMinSignificantDigits = min; 5106 fMaxSignificantDigits = max; 5107 fUseSignificantDigits = TRUE; 5108#if UCONFIG_FORMAT_FASTPATHS_49 5109 handleChanged(); 5110#endif 5111} 5112 5113void DecimalFormat::setMaximumSignificantDigits(int32_t max) { 5114 if (max < 1) { 5115 max = 1; 5116 } 5117 // pin min sig dig to 1..max 5118 U_ASSERT(fMinSignificantDigits >= 1); 5119 int32_t min = _min(fMinSignificantDigits, max); 5120 fMinSignificantDigits = min; 5121 fMaxSignificantDigits = max; 5122 fUseSignificantDigits = TRUE; 5123#if UCONFIG_FORMAT_FASTPATHS_49 5124 handleChanged(); 5125#endif 5126} 5127 5128UBool DecimalFormat::areSignificantDigitsUsed() const { 5129 return fUseSignificantDigits; 5130} 5131 5132void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) { 5133 fUseSignificantDigits = useSignificantDigits; 5134#if UCONFIG_FORMAT_FASTPATHS_49 5135 handleChanged(); 5136#endif 5137} 5138 5139void DecimalFormat::setCurrencyInternally(const UChar* theCurrency, 5140 UErrorCode& ec) { 5141 // If we are a currency format, then modify our affixes to 5142 // encode the currency symbol for the given currency in our 5143 // locale, and adjust the decimal digits and rounding for the 5144 // given currency. 5145 5146 // Note: The code is ordered so that this object is *not changed* 5147 // until we are sure we are going to succeed. 5148 5149 // NULL or empty currency is *legal* and indicates no currency. 5150 UBool isCurr = (theCurrency && *theCurrency); 5151 5152 double rounding = 0.0; 5153 int32_t frac = 0; 5154 if (fCurrencySignCount != fgCurrencySignCountZero && isCurr) { 5155 rounding = ucurr_getRoundingIncrement(theCurrency, &ec); 5156 frac = ucurr_getDefaultFractionDigits(theCurrency, &ec); 5157 } 5158 5159 NumberFormat::setCurrency(theCurrency, ec); 5160 if (U_FAILURE(ec)) return; 5161 5162 if (fCurrencySignCount != fgCurrencySignCountZero) { 5163 // NULL or empty currency is *legal* and indicates no currency. 5164 if (isCurr) { 5165 setRoundingIncrement(rounding); 5166 setMinimumFractionDigits(frac); 5167 setMaximumFractionDigits(frac); 5168 } 5169 expandAffixes(NULL); 5170 } 5171#if UCONFIG_FORMAT_FASTPATHS_49 5172 handleChanged(); 5173#endif 5174} 5175 5176void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { 5177 // set the currency before compute affixes to get the right currency names 5178 NumberFormat::setCurrency(theCurrency, ec); 5179 if (fFormatPattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) { 5180 UnicodeString savedPtn = fFormatPattern; 5181 setupCurrencyAffixes(fFormatPattern, TRUE, TRUE, ec); 5182 UParseError parseErr; 5183 applyPattern(savedPtn, FALSE, parseErr, ec); 5184 } 5185 // set the currency after apply pattern to get the correct rounding/fraction 5186 setCurrencyInternally(theCurrency, ec); 5187#if UCONFIG_FORMAT_FASTPATHS_49 5188 handleChanged(); 5189#endif 5190} 5191 5192// Deprecated variant with no UErrorCode parameter 5193void DecimalFormat::setCurrency(const UChar* theCurrency) { 5194 UErrorCode ec = U_ZERO_ERROR; 5195 setCurrency(theCurrency, ec); 5196#if UCONFIG_FORMAT_FASTPATHS_49 5197 handleChanged(); 5198#endif 5199} 5200 5201void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { 5202 if (fSymbols == NULL) { 5203 ec = U_MEMORY_ALLOCATION_ERROR; 5204 return; 5205 } 5206 ec = U_ZERO_ERROR; 5207 const UChar* c = getCurrency(); 5208 if (*c == 0) { 5209 const UnicodeString &intl = 5210 fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 5211 c = intl.getBuffer(); // ok for intl to go out of scope 5212 } 5213 u_strncpy(result, c, 3); 5214 result[3] = 0; 5215} 5216 5217/** 5218 * Return the number of fraction digits to display, or the total 5219 * number of digits for significant digit formats and exponential 5220 * formats. 5221 */ 5222int32_t 5223DecimalFormat::precision() const { 5224 if (areSignificantDigitsUsed()) { 5225 return getMaximumSignificantDigits(); 5226 } else if (fUseExponentialNotation) { 5227 return getMinimumIntegerDigits() + getMaximumFractionDigits(); 5228 } else { 5229 return getMaximumFractionDigits(); 5230 } 5231} 5232 5233 5234// TODO: template algorithm 5235Hashtable* 5236DecimalFormat::initHashForAffix(UErrorCode& status) { 5237 if ( U_FAILURE(status) ) { 5238 return NULL; 5239 } 5240 Hashtable* hTable; 5241 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 5242 status = U_MEMORY_ALLOCATION_ERROR; 5243 return NULL; 5244 } 5245 if ( U_FAILURE(status) ) { 5246 delete hTable; 5247 return NULL; 5248 } 5249 hTable->setValueComparator(decimfmtAffixValueComparator); 5250 return hTable; 5251} 5252 5253Hashtable* 5254DecimalFormat::initHashForAffixPattern(UErrorCode& status) { 5255 if ( U_FAILURE(status) ) { 5256 return NULL; 5257 } 5258 Hashtable* hTable; 5259 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 5260 status = U_MEMORY_ALLOCATION_ERROR; 5261 return NULL; 5262 } 5263 if ( U_FAILURE(status) ) { 5264 delete hTable; 5265 return NULL; 5266 } 5267 hTable->setValueComparator(decimfmtAffixPatternValueComparator); 5268 return hTable; 5269} 5270 5271void 5272DecimalFormat::deleteHashForAffix(Hashtable*& table) 5273{ 5274 if ( table == NULL ) { 5275 return; 5276 } 5277 int32_t pos = -1; 5278 const UHashElement* element = NULL; 5279 while ( (element = table->nextElement(pos)) != NULL ) { 5280 const UHashTok valueTok = element->value; 5281 const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer; 5282 delete value; 5283 } 5284 delete table; 5285 table = NULL; 5286} 5287 5288 5289 5290void 5291DecimalFormat::deleteHashForAffixPattern() 5292{ 5293 if ( fAffixPatternsForCurrency == NULL ) { 5294 return; 5295 } 5296 int32_t pos = -1; 5297 const UHashElement* element = NULL; 5298 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 5299 const UHashTok valueTok = element->value; 5300 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; 5301 delete value; 5302 } 5303 delete fAffixPatternsForCurrency; 5304 fAffixPatternsForCurrency = NULL; 5305} 5306 5307 5308void 5309DecimalFormat::copyHashForAffixPattern(const Hashtable* source, 5310 Hashtable* target, 5311 UErrorCode& status) { 5312 if ( U_FAILURE(status) ) { 5313 return; 5314 } 5315 int32_t pos = -1; 5316 const UHashElement* element = NULL; 5317 if ( source ) { 5318 while ( (element = source->nextElement(pos)) != NULL ) { 5319 const UHashTok keyTok = element->key; 5320 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 5321 const UHashTok valueTok = element->value; 5322 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; 5323 AffixPatternsForCurrency* copy = new AffixPatternsForCurrency( 5324 value->negPrefixPatternForCurrency, 5325 value->negSuffixPatternForCurrency, 5326 value->posPrefixPatternForCurrency, 5327 value->posSuffixPatternForCurrency, 5328 value->patternType); 5329 target->put(UnicodeString(*key), copy, status); 5330 if ( U_FAILURE(status) ) { 5331 return; 5332 } 5333 } 5334 } 5335} 5336 5337// this is only overridden to call handleChanged() for fastpath purposes. 5338void 5339DecimalFormat::setGroupingUsed(UBool newValue) { 5340 NumberFormat::setGroupingUsed(newValue); 5341 handleChanged(); 5342} 5343 5344// this is only overridden to call handleChanged() for fastpath purposes. 5345void 5346DecimalFormat::setParseIntegerOnly(UBool newValue) { 5347 NumberFormat::setParseIntegerOnly(newValue); 5348 handleChanged(); 5349} 5350 5351// this is only overridden to call handleChanged() for fastpath purposes. 5352// setContext doesn't affect the fastPath right now, but this is called for completeness 5353void 5354DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) { 5355 NumberFormat::setContext(value, status); 5356 handleChanged(); 5357} 5358 5359 5360DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, 5361 int32_t newValue, 5362 UErrorCode &status) { 5363 if(U_FAILURE(status)) return *this; 5364 5365 switch(attr) { 5366 case UNUM_LENIENT_PARSE: 5367 setLenient(newValue!=0); 5368 break; 5369 5370 case UNUM_PARSE_INT_ONLY: 5371 setParseIntegerOnly(newValue!=0); 5372 break; 5373 5374 case UNUM_GROUPING_USED: 5375 setGroupingUsed(newValue!=0); 5376 break; 5377 5378 case UNUM_DECIMAL_ALWAYS_SHOWN: 5379 setDecimalSeparatorAlwaysShown(newValue!=0); 5380 break; 5381 5382 case UNUM_MAX_INTEGER_DIGITS: 5383 setMaximumIntegerDigits(newValue); 5384 break; 5385 5386 case UNUM_MIN_INTEGER_DIGITS: 5387 setMinimumIntegerDigits(newValue); 5388 break; 5389 5390 case UNUM_INTEGER_DIGITS: 5391 setMinimumIntegerDigits(newValue); 5392 setMaximumIntegerDigits(newValue); 5393 break; 5394 5395 case UNUM_MAX_FRACTION_DIGITS: 5396 setMaximumFractionDigits(newValue); 5397 break; 5398 5399 case UNUM_MIN_FRACTION_DIGITS: 5400 setMinimumFractionDigits(newValue); 5401 break; 5402 5403 case UNUM_FRACTION_DIGITS: 5404 setMinimumFractionDigits(newValue); 5405 setMaximumFractionDigits(newValue); 5406 break; 5407 5408 case UNUM_SIGNIFICANT_DIGITS_USED: 5409 setSignificantDigitsUsed(newValue!=0); 5410 break; 5411 5412 case UNUM_MAX_SIGNIFICANT_DIGITS: 5413 setMaximumSignificantDigits(newValue); 5414 break; 5415 5416 case UNUM_MIN_SIGNIFICANT_DIGITS: 5417 setMinimumSignificantDigits(newValue); 5418 break; 5419 5420 case UNUM_MULTIPLIER: 5421 setMultiplier(newValue); 5422 break; 5423 5424 case UNUM_GROUPING_SIZE: 5425 setGroupingSize(newValue); 5426 break; 5427 5428 case UNUM_ROUNDING_MODE: 5429 setRoundingMode((DecimalFormat::ERoundingMode)newValue); 5430 break; 5431 5432 case UNUM_FORMAT_WIDTH: 5433 setFormatWidth(newValue); 5434 break; 5435 5436 case UNUM_PADDING_POSITION: 5437 /** The position at which padding will take place. */ 5438 setPadPosition((DecimalFormat::EPadPosition)newValue); 5439 break; 5440 5441 case UNUM_SECONDARY_GROUPING_SIZE: 5442 setSecondaryGroupingSize(newValue); 5443 break; 5444 5445#if UCONFIG_HAVE_PARSEALLINPUT 5446 case UNUM_PARSE_ALL_INPUT: 5447 setParseAllInput((UNumberFormatAttributeValue)newValue); 5448 break; 5449#endif 5450 5451 /* These are stored in fBoolFlags */ 5452 case UNUM_PARSE_NO_EXPONENT: 5453 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 5454 if(!fBoolFlags.isValidValue(newValue)) { 5455 status = U_ILLEGAL_ARGUMENT_ERROR; 5456 } else { 5457 fBoolFlags.set(attr, newValue); 5458 } 5459 break; 5460 5461 case UNUM_SCALE: 5462 fScale = newValue; 5463 break; 5464 5465 default: 5466 status = U_UNSUPPORTED_ERROR; 5467 break; 5468 } 5469 return *this; 5470} 5471 5472int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr, 5473 UErrorCode &status ) const { 5474 if(U_FAILURE(status)) return -1; 5475 switch(attr) { 5476 case UNUM_LENIENT_PARSE: 5477 return isLenient(); 5478 5479 case UNUM_PARSE_INT_ONLY: 5480 return isParseIntegerOnly(); 5481 5482 case UNUM_GROUPING_USED: 5483 return isGroupingUsed(); 5484 5485 case UNUM_DECIMAL_ALWAYS_SHOWN: 5486 return isDecimalSeparatorAlwaysShown(); 5487 5488 case UNUM_MAX_INTEGER_DIGITS: 5489 return getMaximumIntegerDigits(); 5490 5491 case UNUM_MIN_INTEGER_DIGITS: 5492 return getMinimumIntegerDigits(); 5493 5494 case UNUM_INTEGER_DIGITS: 5495 // TBD: what should this return? 5496 return getMinimumIntegerDigits(); 5497 5498 case UNUM_MAX_FRACTION_DIGITS: 5499 return getMaximumFractionDigits(); 5500 5501 case UNUM_MIN_FRACTION_DIGITS: 5502 return getMinimumFractionDigits(); 5503 5504 case UNUM_FRACTION_DIGITS: 5505 // TBD: what should this return? 5506 return getMinimumFractionDigits(); 5507 5508 case UNUM_SIGNIFICANT_DIGITS_USED: 5509 return areSignificantDigitsUsed(); 5510 5511 case UNUM_MAX_SIGNIFICANT_DIGITS: 5512 return getMaximumSignificantDigits(); 5513 5514 case UNUM_MIN_SIGNIFICANT_DIGITS: 5515 return getMinimumSignificantDigits(); 5516 5517 case UNUM_MULTIPLIER: 5518 return getMultiplier(); 5519 5520 case UNUM_GROUPING_SIZE: 5521 return getGroupingSize(); 5522 5523 case UNUM_ROUNDING_MODE: 5524 return getRoundingMode(); 5525 5526 case UNUM_FORMAT_WIDTH: 5527 return getFormatWidth(); 5528 5529 case UNUM_PADDING_POSITION: 5530 return getPadPosition(); 5531 5532 case UNUM_SECONDARY_GROUPING_SIZE: 5533 return getSecondaryGroupingSize(); 5534 5535 /* These are stored in fBoolFlags */ 5536 case UNUM_PARSE_NO_EXPONENT: 5537 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 5538 return fBoolFlags.get(attr); 5539 5540 case UNUM_SCALE: 5541 return fScale; 5542 5543 default: 5544 status = U_UNSUPPORTED_ERROR; 5545 break; 5546 } 5547 5548 return -1; /* undefined */ 5549} 5550 5551#if UCONFIG_HAVE_PARSEALLINPUT 5552void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { 5553 fParseAllInput = value; 5554#if UCONFIG_FORMAT_FASTPATHS_49 5555 handleChanged(); 5556#endif 5557} 5558#endif 5559 5560void 5561DecimalFormat::copyHashForAffix(const Hashtable* source, 5562 Hashtable* target, 5563 UErrorCode& status) { 5564 if ( U_FAILURE(status) ) { 5565 return; 5566 } 5567 int32_t pos = -1; 5568 const UHashElement* element = NULL; 5569 if ( source ) { 5570 while ( (element = source->nextElement(pos)) != NULL ) { 5571 const UHashTok keyTok = element->key; 5572 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 5573 5574 const UHashTok valueTok = element->value; 5575 const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer; 5576 AffixesForCurrency* copy = new AffixesForCurrency( 5577 value->negPrefixForCurrency, 5578 value->negSuffixForCurrency, 5579 value->posPrefixForCurrency, 5580 value->posSuffixForCurrency); 5581 target->put(UnicodeString(*key), copy, status); 5582 if ( U_FAILURE(status) ) { 5583 return; 5584 } 5585 } 5586 } 5587} 5588 5589U_NAMESPACE_END 5590 5591#endif /* #if !UCONFIG_NO_FORMATTING */ 5592 5593//eof 5594