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