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