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