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