1 /* 2 ******************************************************************************* 3 * Copyright (C) 1997-2015, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 * 7 * File DECIMFMT.CPP 8 * 9 * Modification History: 10 * 11 * Date Name Description 12 * 02/19/97 aliu Converted from java. 13 * 03/20/97 clhuang Implemented with new APIs. 14 * 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it. 15 * 04/3/97 aliu Rewrote parsing and formatting completely, and 16 * cleaned up and debugged. Actually works now. 17 * Implemented NAN and INF handling, for both parsing 18 * and formatting. Extensive testing & debugging. 19 * 04/10/97 aliu Modified to compile on AIX. 20 * 04/16/97 aliu Rewrote to use DigitList, which has been resurrected. 21 * Changed DigitCount to int per code review. 22 * 07/09/97 helena Made ParsePosition into a class. 23 * 08/26/97 aliu Extensive changes to applyPattern; completely 24 * rewritten from the Java. 25 * 09/09/97 aliu Ported over support for exponential formats. 26 * 07/20/98 stephen JDK 1.2 sync up. 27 * Various instances of '0' replaced with 'NULL' 28 * Check for grouping size in subFormat() 29 * Brought subParse() in line with Java 1.2 30 * Added method appendAffix() 31 * 08/24/1998 srl Removed Mutex calls. This is not a thread safe class! 32 * 02/22/99 stephen Removed character literals for EBCDIC safety 33 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes 34 * 06/28/99 stephen Fixed bugs in toPattern(). 35 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad, 36 * fPadPosition 37 ******************************************************************************** 38 */ 39 40 #include "unicode/utypes.h" 41 42 #if !UCONFIG_NO_FORMATTING 43 44 #include "unicode/uniset.h" 45 #include "unicode/currpinf.h" 46 #include "unicode/plurrule.h" 47 #include "unicode/utf16.h" 48 #include "unicode/numsys.h" 49 #include "unicode/localpointer.h" 50 #include "uresimp.h" 51 #include "ucurrimp.h" 52 #include "charstr.h" 53 #include "patternprops.h" 54 #include "cstring.h" 55 #include "uassert.h" 56 #include "hash.h" 57 #include "decfmtst.h" 58 #include "plurrule_impl.h" 59 #include "decimalformatpattern.h" 60 #include "fmtableimp.h" 61 #include "decimfmtimpl.h" 62 #include "visibledigits.h" 63 64 /* 65 * On certain platforms, round is a macro defined in math.h 66 * This undefine is to avoid conflict between the macro and 67 * the function defined below. 68 */ 69 #ifdef round 70 #undef round 71 #endif 72 73 74 U_NAMESPACE_BEGIN 75 76 #ifdef FMT_DEBUG 77 #include <stdio.h> 78 static void _debugout(const char *f, int l, const UnicodeString& s) { 79 char buf[2000]; 80 s.extract((int32_t) 0, s.length(), buf, "utf-8"); 81 printf("%s:%d: %s\n", f,l, buf); 82 } 83 #define debugout(x) _debugout(__FILE__,__LINE__,x) 84 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); 85 static const UnicodeString dbg_null("<NULL>",""); 86 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) 87 #else 88 #define debugout(x) 89 #define debug(x) 90 #endif 91 92 93 /* For currency parsing purose, 94 * Need to remember all prefix patterns and suffix patterns of 95 * every currency format pattern, 96 * including the pattern of default currecny style 97 * and plural currency style. And the patterns are set through applyPattern. 98 */ 99 struct AffixPatternsForCurrency : public UMemory { 100 // negative prefix pattern 101 UnicodeString negPrefixPatternForCurrency; 102 // negative suffix pattern 103 UnicodeString negSuffixPatternForCurrency; 104 // positive prefix pattern 105 UnicodeString posPrefixPatternForCurrency; 106 // positive suffix pattern 107 UnicodeString posSuffixPatternForCurrency; 108 int8_t patternType; 109 110 AffixPatternsForCurrency(const UnicodeString& negPrefix, 111 const UnicodeString& negSuffix, 112 const UnicodeString& posPrefix, 113 const UnicodeString& posSuffix, 114 int8_t type) { 115 negPrefixPatternForCurrency = negPrefix; 116 negSuffixPatternForCurrency = negSuffix; 117 posPrefixPatternForCurrency = posPrefix; 118 posSuffixPatternForCurrency = posSuffix; 119 patternType = type; 120 } 121 #ifdef FMT_DEBUG 122 void dump() const { 123 debugout( UnicodeString("AffixPatternsForCurrency( -=\"") + 124 negPrefixPatternForCurrency + (UnicodeString)"\"/\"" + 125 negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" + 126 posPrefixPatternForCurrency + (UnicodeString)"\"/\"" + 127 posSuffixPatternForCurrency + (UnicodeString)"\" )"); 128 } 129 #endif 130 }; 131 132 /* affix for currency formatting when the currency sign in the pattern 133 * equals to 3, such as the pattern contains 3 currency sign or 134 * the formatter style is currency plural format style. 135 */ 136 struct AffixesForCurrency : public UMemory { 137 // negative prefix 138 UnicodeString negPrefixForCurrency; 139 // negative suffix 140 UnicodeString negSuffixForCurrency; 141 // positive prefix 142 UnicodeString posPrefixForCurrency; 143 // positive suffix 144 UnicodeString posSuffixForCurrency; 145 146 int32_t formatWidth; 147 148 AffixesForCurrency(const UnicodeString& negPrefix, 149 const UnicodeString& negSuffix, 150 const UnicodeString& posPrefix, 151 const UnicodeString& posSuffix) { 152 negPrefixForCurrency = negPrefix; 153 negSuffixForCurrency = negSuffix; 154 posPrefixForCurrency = posPrefix; 155 posSuffixForCurrency = posSuffix; 156 } 157 #ifdef FMT_DEBUG 158 void dump() const { 159 debugout( UnicodeString("AffixesForCurrency( -=\"") + 160 negPrefixForCurrency + (UnicodeString)"\"/\"" + 161 negSuffixForCurrency + (UnicodeString)"\" +=\"" + 162 posPrefixForCurrency + (UnicodeString)"\"/\"" + 163 posSuffixForCurrency + (UnicodeString)"\" )"); 164 } 165 #endif 166 }; 167 168 U_CDECL_BEGIN 169 170 /** 171 * @internal ICU 4.2 172 */ 173 static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2); 174 175 176 static UBool 177 U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) { 178 const AffixPatternsForCurrency* affix_1 = 179 (AffixPatternsForCurrency*)val1.pointer; 180 const AffixPatternsForCurrency* affix_2 = 181 (AffixPatternsForCurrency*)val2.pointer; 182 return affix_1->negPrefixPatternForCurrency == 183 affix_2->negPrefixPatternForCurrency && 184 affix_1->negSuffixPatternForCurrency == 185 affix_2->negSuffixPatternForCurrency && 186 affix_1->posPrefixPatternForCurrency == 187 affix_2->posPrefixPatternForCurrency && 188 affix_1->posSuffixPatternForCurrency == 189 affix_2->posSuffixPatternForCurrency && 190 affix_1->patternType == affix_2->patternType; 191 } 192 193 U_CDECL_END 194 195 196 197 198 // ***************************************************************************** 199 // class DecimalFormat 200 // ***************************************************************************** 201 202 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat) 203 204 // Constants for characters used in programmatic (unlocalized) patterns. 205 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ 206 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ 207 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ 208 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ 209 #define kPatternPerMill ((UChar)0x2030) 210 #define kPatternPercent ((UChar)0x0025) /*'%'*/ 211 #define kPatternDigit ((UChar)0x0023) /*'#'*/ 212 #define kPatternSeparator ((UChar)0x003B) /*';'*/ 213 #define kPatternExponent ((UChar)0x0045) /*'E'*/ 214 #define kPatternPlus ((UChar)0x002B) /*'+'*/ 215 #define kPatternMinus ((UChar)0x002D) /*'-'*/ 216 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/ 217 #define kQuote ((UChar)0x0027) /*'\''*/ 218 /** 219 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It 220 * is used in patterns and substitued with either the currency symbol, 221 * or if it is doubled, with the international currency symbol. If the 222 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is 223 * replaced with the monetary decimal separator. 224 */ 225 #define kCurrencySign ((UChar)0x00A4) 226 #define kDefaultPad ((UChar)0x0020) /* */ 227 228 const int32_t DecimalFormat::kDoubleIntegerDigits = 309; 229 const int32_t DecimalFormat::kDoubleFractionDigits = 340; 230 231 const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8; 232 233 /** 234 * These are the tags we expect to see in normal resource bundle files associated 235 * with a locale. 236 */ 237 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used 238 static const char fgNumberElements[]="NumberElements"; 239 static const char fgLatn[]="latn"; 240 static const char fgPatterns[]="patterns"; 241 static const char fgDecimalFormat[]="decimalFormat"; 242 static const char fgCurrencyFormat[]="currencyFormat"; 243 244 inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; } 245 inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; } 246 247 //------------------------------------------------------------------------------ 248 // Constructs a DecimalFormat instance in the default locale. 249 250 DecimalFormat::DecimalFormat(UErrorCode& status) { 251 init(); 252 UParseError parseError; 253 construct(status, parseError); 254 } 255 256 //------------------------------------------------------------------------------ 257 // Constructs a DecimalFormat instance with the specified number format 258 // pattern in the default locale. 259 260 DecimalFormat::DecimalFormat(const UnicodeString& pattern, 261 UErrorCode& status) { 262 init(); 263 UParseError parseError; 264 construct(status, parseError, &pattern); 265 } 266 267 //------------------------------------------------------------------------------ 268 // Constructs a DecimalFormat instance with the specified number format 269 // pattern and the number format symbols in the default locale. The 270 // created instance owns the symbols. 271 272 DecimalFormat::DecimalFormat(const UnicodeString& pattern, 273 DecimalFormatSymbols* symbolsToAdopt, 274 UErrorCode& status) { 275 init(); 276 UParseError parseError; 277 if (symbolsToAdopt == NULL) 278 status = U_ILLEGAL_ARGUMENT_ERROR; 279 construct(status, parseError, &pattern, symbolsToAdopt); 280 } 281 282 DecimalFormat::DecimalFormat( const UnicodeString& pattern, 283 DecimalFormatSymbols* symbolsToAdopt, 284 UParseError& parseErr, 285 UErrorCode& status) { 286 init(); 287 if (symbolsToAdopt == NULL) 288 status = U_ILLEGAL_ARGUMENT_ERROR; 289 construct(status,parseErr, &pattern, symbolsToAdopt); 290 } 291 292 //------------------------------------------------------------------------------ 293 // Constructs a DecimalFormat instance with the specified number format 294 // pattern and the number format symbols in the default locale. The 295 // created instance owns the clone of the symbols. 296 297 DecimalFormat::DecimalFormat(const UnicodeString& pattern, 298 const DecimalFormatSymbols& symbols, 299 UErrorCode& status) { 300 init(); 301 UParseError parseError; 302 construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols)); 303 } 304 305 //------------------------------------------------------------------------------ 306 // Constructs a DecimalFormat instance with the specified number format 307 // pattern, the number format symbols, and the number format style. 308 // The created instance owns the clone of the symbols. 309 310 DecimalFormat::DecimalFormat(const UnicodeString& pattern, 311 DecimalFormatSymbols* symbolsToAdopt, 312 UNumberFormatStyle style, 313 UErrorCode& status) { 314 init(); 315 fStyle = style; 316 UParseError parseError; 317 construct(status, parseError, &pattern, symbolsToAdopt); 318 } 319 320 //----------------------------------------------------------------------------- 321 // Common DecimalFormat initialization. 322 // Put all fields of an uninitialized object into a known state. 323 // Common code, shared by all constructors. 324 // Can not fail. Leave the object in good enough shape that the destructor 325 // or assignment operator can run successfully. 326 void 327 DecimalFormat::init() { 328 fBoolFlags.clear(); 329 fStyle = UNUM_DECIMAL; 330 fAffixPatternsForCurrency = NULL; 331 fCurrencyPluralInfo = NULL; 332 #if UCONFIG_HAVE_PARSEALLINPUT 333 fParseAllInput = UNUM_MAYBE; 334 #endif 335 336 fStaticSets = NULL; 337 fImpl = NULL; 338 } 339 340 //------------------------------------------------------------------------------ 341 // Constructs a DecimalFormat instance with the specified number format 342 // pattern and the number format symbols in the desired locale. The 343 // created instance owns the symbols. 344 345 void 346 DecimalFormat::construct(UErrorCode& status, 347 UParseError& parseErr, 348 const UnicodeString* pattern, 349 DecimalFormatSymbols* symbolsToAdopt) 350 { 351 LocalPointer<DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt); 352 if (U_FAILURE(status)) 353 return; 354 355 if (adoptedSymbols.isNull()) 356 { 357 adoptedSymbols.adoptInstead( 358 new DecimalFormatSymbols(Locale::getDefault(), status)); 359 if (adoptedSymbols.isNull() && U_SUCCESS(status)) { 360 status = U_MEMORY_ALLOCATION_ERROR; 361 } 362 if (U_FAILURE(status)) { 363 return; 364 } 365 } 366 fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 367 if (U_FAILURE(status)) { 368 return; 369 } 370 371 UnicodeString str; 372 // Uses the default locale's number format pattern if there isn't 373 // one specified. 374 if (pattern == NULL) 375 { 376 UErrorCode nsStatus = U_ZERO_ERROR; 377 LocalPointer<NumberingSystem> ns( 378 NumberingSystem::createInstance(nsStatus)); 379 if (U_FAILURE(nsStatus)) { 380 status = nsStatus; 381 return; 382 } 383 384 int32_t len = 0; 385 UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status); 386 387 UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status); 388 resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status); 389 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 390 const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 391 if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) { 392 status = U_ZERO_ERROR; 393 resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status); 394 resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status); 395 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); 396 resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); 397 } 398 str.setTo(TRUE, resStr, len); 399 pattern = &str; 400 ures_close(resource); 401 ures_close(top); 402 } 403 404 fImpl = new DecimalFormatImpl(this, *pattern, adoptedSymbols.getAlias(), parseErr, status); 405 if (fImpl) { 406 adoptedSymbols.orphan(); 407 } else if (U_SUCCESS(status)) { 408 status = U_MEMORY_ALLOCATION_ERROR; 409 } 410 if (U_FAILURE(status)) { 411 return; 412 } 413 414 if (U_FAILURE(status)) 415 { 416 return; 417 } 418 419 const UnicodeString* patternUsed; 420 UnicodeString currencyPluralPatternForOther; 421 // apply pattern 422 if (fStyle == UNUM_CURRENCY_PLURAL) { 423 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status); 424 if (U_FAILURE(status)) { 425 return; 426 } 427 428 // the pattern used in format is not fixed until formatting, 429 // in which, the number is known and 430 // will be used to pick the right pattern based on plural count. 431 // Here, set the pattern as the pattern of plural count == "other". 432 // For most locale, the patterns are probably the same for all 433 // plural count. If not, the right pattern need to be re-applied 434 // during format. 435 fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther); 436 // TODO(refactor): Revisit, we are setting the pattern twice. 437 fImpl->applyPatternFavorCurrencyPrecision( 438 currencyPluralPatternForOther, status); 439 patternUsed = ¤cyPluralPatternForOther; 440 441 } else { 442 patternUsed = pattern; 443 } 444 445 if (patternUsed->indexOf(kCurrencySign) != -1) { 446 // initialize for currency, not only for plural format, 447 // but also for mix parsing 448 if (fCurrencyPluralInfo == NULL) { 449 fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status); 450 if (U_FAILURE(status)) { 451 return; 452 } 453 } 454 // need it for mix parsing 455 setupCurrencyAffixPatterns(status); 456 } 457 } 458 459 static void 460 applyPatternWithNoSideEffects( 461 const UnicodeString& pattern, 462 UParseError& parseError, 463 UnicodeString &negPrefix, 464 UnicodeString &negSuffix, 465 UnicodeString &posPrefix, 466 UnicodeString &posSuffix, 467 UErrorCode& status) { 468 if (U_FAILURE(status)) 469 { 470 return; 471 } 472 DecimalFormatPatternParser patternParser; 473 DecimalFormatPattern out; 474 patternParser.applyPatternWithoutExpandAffix( 475 pattern, 476 out, 477 parseError, 478 status); 479 if (U_FAILURE(status)) { 480 return; 481 } 482 negPrefix = out.fNegPrefixPattern; 483 negSuffix = out.fNegSuffixPattern; 484 posPrefix = out.fPosPrefixPattern; 485 posSuffix = out.fPosSuffixPattern; 486 } 487 488 void 489 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) { 490 if (U_FAILURE(status)) { 491 return; 492 } 493 UParseError parseErr; 494 fAffixPatternsForCurrency = initHashForAffixPattern(status); 495 if (U_FAILURE(status)) { 496 return; 497 } 498 499 NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLocale(),status); 500 if (U_FAILURE(status)) { 501 return; 502 } 503 504 // Save the default currency patterns of this locale. 505 // Here, chose onlyApplyPatternWithoutExpandAffix without 506 // expanding the affix patterns into affixes. 507 UnicodeString currencyPattern; 508 UErrorCode error = U_ZERO_ERROR; 509 510 UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().getName(), &error); 511 UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error); 512 resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error); 513 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); 514 int32_t patLen = 0; 515 const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 516 if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) { 517 error = U_ZERO_ERROR; 518 resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error); 519 resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); 520 patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); 521 } 522 ures_close(numElements); 523 ures_close(resource); 524 delete ns; 525 526 if (U_SUCCESS(error)) { 527 UnicodeString negPrefix; 528 UnicodeString negSuffix; 529 UnicodeString posPrefix; 530 UnicodeString posSuffix; 531 applyPatternWithNoSideEffects(UnicodeString(patResStr, patLen), 532 parseErr, 533 negPrefix, negSuffix, posPrefix, posSuffix, status); 534 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 535 negPrefix, 536 negSuffix, 537 posPrefix, 538 posSuffix, 539 UCURR_SYMBOL_NAME); 540 fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status); 541 } 542 543 // save the unique currency plural patterns of this locale. 544 Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern; 545 const UHashElement* element = NULL; 546 int32_t pos = UHASH_FIRST; 547 Hashtable pluralPatternSet; 548 while ((element = pluralPtn->nextElement(pos)) != NULL) { 549 const UHashTok valueTok = element->value; 550 const UnicodeString* value = (UnicodeString*)valueTok.pointer; 551 const UHashTok keyTok = element->key; 552 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 553 if (pluralPatternSet.geti(*value) != 1) { 554 UnicodeString negPrefix; 555 UnicodeString negSuffix; 556 UnicodeString posPrefix; 557 UnicodeString posSuffix; 558 pluralPatternSet.puti(*value, 1, status); 559 applyPatternWithNoSideEffects( 560 *value, parseErr, 561 negPrefix, negSuffix, posPrefix, posSuffix, status); 562 AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( 563 negPrefix, 564 negSuffix, 565 posPrefix, 566 posSuffix, 567 UCURR_LONG_NAME); 568 fAffixPatternsForCurrency->put(*key, affixPtn, status); 569 } 570 } 571 } 572 573 574 //------------------------------------------------------------------------------ 575 576 DecimalFormat::~DecimalFormat() 577 { 578 deleteHashForAffixPattern(); 579 delete fCurrencyPluralInfo; 580 delete fImpl; 581 } 582 583 //------------------------------------------------------------------------------ 584 // copy constructor 585 586 DecimalFormat::DecimalFormat(const DecimalFormat &source) : 587 NumberFormat(source) { 588 init(); 589 *this = source; 590 } 591 592 //------------------------------------------------------------------------------ 593 // assignment operator 594 595 template <class T> 596 static void _clone_ptr(T** pdest, const T* source) { 597 delete *pdest; 598 if (source == NULL) { 599 *pdest = NULL; 600 } else { 601 *pdest = static_cast<T*>(source->clone()); 602 } 603 } 604 605 DecimalFormat& 606 DecimalFormat::operator=(const DecimalFormat& rhs) 607 { 608 if(this != &rhs) { 609 UErrorCode status = U_ZERO_ERROR; 610 NumberFormat::operator=(rhs); 611 if (fImpl == NULL) { 612 fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status); 613 } else { 614 fImpl->assign(*rhs.fImpl, status); 615 } 616 fStaticSets = DecimalFormatStaticSets::getStaticSets(status); 617 fStyle = rhs.fStyle; 618 _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo); 619 deleteHashForAffixPattern(); 620 if (rhs.fAffixPatternsForCurrency) { 621 UErrorCode status = U_ZERO_ERROR; 622 fAffixPatternsForCurrency = initHashForAffixPattern(status); 623 copyHashForAffixPattern(rhs.fAffixPatternsForCurrency, 624 fAffixPatternsForCurrency, status); 625 } 626 } 627 628 return *this; 629 } 630 631 //------------------------------------------------------------------------------ 632 633 UBool 634 DecimalFormat::operator==(const Format& that) const 635 { 636 if (this == &that) 637 return TRUE; 638 639 // NumberFormat::operator== guarantees this cast is safe 640 const DecimalFormat* other = (DecimalFormat*)&that; 641 642 return ( 643 NumberFormat::operator==(that) && 644 fBoolFlags.getAll() == other->fBoolFlags.getAll() && 645 *fImpl == *other->fImpl); 646 647 } 648 649 //------------------------------------------------------------------------------ 650 651 Format* 652 DecimalFormat::clone() const 653 { 654 return new DecimalFormat(*this); 655 } 656 657 658 FixedDecimal 659 DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const { 660 VisibleDigitsWithExponent digits; 661 initVisibleDigitsWithExponent(number, digits, status); 662 if (U_FAILURE(status)) { 663 return FixedDecimal(); 664 } 665 return FixedDecimal(digits.getMantissa()); 666 } 667 668 VisibleDigitsWithExponent & 669 DecimalFormat::initVisibleDigitsWithExponent( 670 double number, 671 VisibleDigitsWithExponent &digits, 672 UErrorCode &status) const { 673 return fImpl->initVisibleDigitsWithExponent(number, digits, status); 674 } 675 676 FixedDecimal 677 DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const { 678 VisibleDigitsWithExponent digits; 679 initVisibleDigitsWithExponent(number, digits, status); 680 if (U_FAILURE(status)) { 681 return FixedDecimal(); 682 } 683 return FixedDecimal(digits.getMantissa()); 684 } 685 686 VisibleDigitsWithExponent & 687 DecimalFormat::initVisibleDigitsWithExponent( 688 const Formattable &number, 689 VisibleDigitsWithExponent &digits, 690 UErrorCode &status) const { 691 if (U_FAILURE(status)) { 692 return digits; 693 } 694 if (!number.isNumeric()) { 695 status = U_ILLEGAL_ARGUMENT_ERROR; 696 return digits; 697 } 698 699 DigitList *dl = number.getDigitList(); 700 if (dl != NULL) { 701 DigitList dlCopy(*dl); 702 return fImpl->initVisibleDigitsWithExponent( 703 dlCopy, digits, status); 704 } 705 706 Formattable::Type type = number.getType(); 707 if (type == Formattable::kDouble || type == Formattable::kLong) { 708 return fImpl->initVisibleDigitsWithExponent( 709 number.getDouble(status), digits, status); 710 } 711 return fImpl->initVisibleDigitsWithExponent( 712 number.getInt64(), digits, status); 713 } 714 715 716 // Create a fixed decimal from a DigitList. 717 // The digit list may be modified. 718 // Internal function only. 719 FixedDecimal 720 DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const { 721 VisibleDigitsWithExponent digits; 722 initVisibleDigitsWithExponent(number, digits, status); 723 if (U_FAILURE(status)) { 724 return FixedDecimal(); 725 } 726 return FixedDecimal(digits.getMantissa()); 727 } 728 729 VisibleDigitsWithExponent & 730 DecimalFormat::initVisibleDigitsWithExponent( 731 DigitList &number, 732 VisibleDigitsWithExponent &digits, 733 UErrorCode &status) const { 734 return fImpl->initVisibleDigitsWithExponent( 735 number, digits, status); 736 } 737 738 739 //------------------------------------------------------------------------------ 740 741 UnicodeString& 742 DecimalFormat::format(int32_t number, 743 UnicodeString& appendTo, 744 FieldPosition& fieldPosition) const 745 { 746 UErrorCode status = U_ZERO_ERROR; 747 return fImpl->format(number, appendTo, fieldPosition, status); 748 } 749 750 UnicodeString& 751 DecimalFormat::format(int32_t number, 752 UnicodeString& appendTo, 753 FieldPosition& fieldPosition, 754 UErrorCode& status) const 755 { 756 return fImpl->format(number, appendTo, fieldPosition, status); 757 } 758 759 UnicodeString& 760 DecimalFormat::format(int32_t number, 761 UnicodeString& appendTo, 762 FieldPositionIterator* posIter, 763 UErrorCode& status) const 764 { 765 return fImpl->format(number, appendTo, posIter, status); 766 } 767 768 769 //------------------------------------------------------------------------------ 770 771 UnicodeString& 772 DecimalFormat::format(int64_t number, 773 UnicodeString& appendTo, 774 FieldPosition& fieldPosition) const 775 { 776 UErrorCode status = U_ZERO_ERROR; /* ignored */ 777 return fImpl->format(number, appendTo, fieldPosition, status); 778 } 779 780 UnicodeString& 781 DecimalFormat::format(int64_t number, 782 UnicodeString& appendTo, 783 FieldPosition& fieldPosition, 784 UErrorCode& status) const 785 { 786 return fImpl->format(number, appendTo, fieldPosition, status); 787 } 788 789 UnicodeString& 790 DecimalFormat::format(int64_t number, 791 UnicodeString& appendTo, 792 FieldPositionIterator* posIter, 793 UErrorCode& status) const 794 { 795 return fImpl->format(number, appendTo, posIter, status); 796 } 797 798 //------------------------------------------------------------------------------ 799 800 UnicodeString& 801 DecimalFormat::format( double number, 802 UnicodeString& appendTo, 803 FieldPosition& fieldPosition) const 804 { 805 UErrorCode status = U_ZERO_ERROR; /* ignored */ 806 return fImpl->format(number, appendTo, fieldPosition, status); 807 } 808 809 UnicodeString& 810 DecimalFormat::format( double number, 811 UnicodeString& appendTo, 812 FieldPosition& fieldPosition, 813 UErrorCode& status) const 814 { 815 return fImpl->format(number, appendTo, fieldPosition, status); 816 } 817 818 UnicodeString& 819 DecimalFormat::format( double number, 820 UnicodeString& appendTo, 821 FieldPositionIterator* posIter, 822 UErrorCode& status) const 823 { 824 return fImpl->format(number, appendTo, posIter, status); 825 } 826 827 //------------------------------------------------------------------------------ 828 829 830 UnicodeString& 831 DecimalFormat::format(const StringPiece &number, 832 UnicodeString &toAppendTo, 833 FieldPositionIterator *posIter, 834 UErrorCode &status) const 835 { 836 return fImpl->format(number, toAppendTo, posIter, status); 837 } 838 839 840 UnicodeString& 841 DecimalFormat::format(const DigitList &number, 842 UnicodeString &appendTo, 843 FieldPositionIterator *posIter, 844 UErrorCode &status) const { 845 return fImpl->format(number, appendTo, posIter, status); 846 } 847 848 849 UnicodeString& 850 DecimalFormat::format(const DigitList &number, 851 UnicodeString& appendTo, 852 FieldPosition& pos, 853 UErrorCode &status) const { 854 return fImpl->format(number, appendTo, pos, status); 855 } 856 857 UnicodeString& 858 DecimalFormat::format(const VisibleDigitsWithExponent &number, 859 UnicodeString &appendTo, 860 FieldPositionIterator *posIter, 861 UErrorCode &status) const { 862 return fImpl->format(number, appendTo, posIter, status); 863 } 864 865 866 UnicodeString& 867 DecimalFormat::format(const VisibleDigitsWithExponent &number, 868 UnicodeString& appendTo, 869 FieldPosition& pos, 870 UErrorCode &status) const { 871 return fImpl->format(number, appendTo, pos, status); 872 } 873 874 DigitList& 875 DecimalFormat::_round(const DigitList& number, DigitList& adjustedNum, UBool& isNegative, UErrorCode& status) const { 876 adjustedNum = number; 877 fImpl->round(adjustedNum, status); 878 isNegative = !adjustedNum.isPositive(); 879 return adjustedNum; 880 } 881 882 void 883 DecimalFormat::parse(const UnicodeString& text, 884 Formattable& result, 885 ParsePosition& parsePosition) const { 886 parse(text, result, parsePosition, NULL); 887 } 888 889 CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, 890 ParsePosition& pos) const { 891 Formattable parseResult; 892 int32_t start = pos.getIndex(); 893 UChar curbuf[4] = {}; 894 parse(text, parseResult, pos, curbuf); 895 if (pos.getIndex() != start) { 896 UErrorCode ec = U_ZERO_ERROR; 897 LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec), ec); 898 if (U_FAILURE(ec)) { 899 pos.setIndex(start); // indicate failure 900 } else { 901 return currAmt.orphan(); 902 } 903 } 904 return NULL; 905 } 906 907 /** 908 * Parses the given text as a number, optionally providing a currency amount. 909 * @param text the string to parse 910 * @param result output parameter for the numeric result. 911 * @param parsePosition input-output position; on input, the 912 * position within text to match; must have 0 <= pos.getIndex() < 913 * text.length(); on output, the position after the last matched 914 * character. If the parse fails, the position in unchanged upon 915 * output. 916 * @param currency if non-NULL, it should point to a 4-UChar buffer. 917 * In this case the text is parsed as a currency format, and the 918 * ISO 4217 code for the parsed currency is put into the buffer. 919 * Otherwise the text is parsed as a non-currency format. 920 */ 921 void DecimalFormat::parse(const UnicodeString& text, 922 Formattable& result, 923 ParsePosition& parsePosition, 924 UChar* currency) const { 925 int32_t startIdx, backup; 926 int32_t i = startIdx = backup = parsePosition.getIndex(); 927 928 // clear any old contents in the result. In particular, clears any DigitList 929 // that it may be holding. 930 result.setLong(0); 931 if (currency != NULL) { 932 for (int32_t ci=0; ci<4; ci++) { 933 currency[ci] = 0; 934 } 935 } 936 937 // Handle NaN as a special case: 938 int32_t formatWidth = fImpl->getOldFormatWidth(); 939 940 // Skip padding characters, if around prefix 941 if (formatWidth > 0 && ( 942 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix || 943 fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix)) { 944 i = skipPadding(text, i); 945 } 946 947 if (isLenient()) { 948 // skip any leading whitespace 949 i = backup = skipUWhiteSpace(text, i); 950 } 951 952 // If the text is composed of the representation of NaN, returns NaN.length 953 const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaNSymbol); 954 int32_t nanLen = (text.compare(i, nan->length(), *nan) 955 ? 0 : nan->length()); 956 if (nanLen) { 957 i += nanLen; 958 if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix)) { 959 i = skipPadding(text, i); 960 } 961 parsePosition.setIndex(i); 962 result.setDouble(uprv_getNaN()); 963 return; 964 } 965 966 // NaN parse failed; start over 967 i = backup; 968 parsePosition.setIndex(i); 969 970 // status is used to record whether a number is infinite. 971 UBool status[fgStatusLength]; 972 973 DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer 974 if (digits == NULL) { 975 return; // no way to report error from here. 976 } 977 978 if (fImpl->fMonetary) { 979 if (!parseForCurrency(text, parsePosition, *digits, 980 status, currency)) { 981 return; 982 } 983 } else { 984 if (!subparse(text, 985 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(), 986 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(), 987 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(), 988 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(), 989 FALSE, UCURR_SYMBOL_NAME, 990 parsePosition, *digits, status, currency)) { 991 debug("!subparse(...) - rewind"); 992 parsePosition.setIndex(startIdx); 993 return; 994 } 995 } 996 997 // Handle infinity 998 if (status[fgStatusInfinite]) { 999 double inf = uprv_getInfinity(); 1000 result.setDouble(digits->isPositive() ? inf : -inf); 1001 // TODO: set the dl to infinity, and let it fall into the code below. 1002 } 1003 1004 else { 1005 1006 if (!fImpl->fMultiplier.isZero()) { 1007 UErrorCode ec = U_ZERO_ERROR; 1008 digits->div(fImpl->fMultiplier, ec); 1009 } 1010 1011 if (fImpl->fScale != 0) { 1012 DigitList ten; 1013 ten.set((int32_t)10); 1014 if (fImpl->fScale > 0) { 1015 for (int32_t i = fImpl->fScale; i > 0; i--) { 1016 UErrorCode ec = U_ZERO_ERROR; 1017 digits->div(ten,ec); 1018 } 1019 } else { 1020 for (int32_t i = fImpl->fScale; i < 0; i++) { 1021 UErrorCode ec = U_ZERO_ERROR; 1022 digits->mult(ten,ec); 1023 } 1024 } 1025 } 1026 1027 // Negative zero special case: 1028 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable. 1029 // if not parsing integerOnly, leave as -0, which a double can represent. 1030 if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) { 1031 digits->setPositive(TRUE); 1032 } 1033 result.adoptDigitList(digits); 1034 } 1035 } 1036 1037 1038 1039 UBool 1040 DecimalFormat::parseForCurrency(const UnicodeString& text, 1041 ParsePosition& parsePosition, 1042 DigitList& digits, 1043 UBool* status, 1044 UChar* currency) const { 1045 UnicodeString positivePrefix; 1046 UnicodeString positiveSuffix; 1047 UnicodeString negativePrefix; 1048 UnicodeString negativeSuffix; 1049 fImpl->fPositivePrefixPattern.toString(positivePrefix); 1050 fImpl->fPositiveSuffixPattern.toString(positiveSuffix); 1051 fImpl->fNegativePrefixPattern.toString(negativePrefix); 1052 fImpl->fNegativeSuffixPattern.toString(negativeSuffix); 1053 1054 int origPos = parsePosition.getIndex(); 1055 int maxPosIndex = origPos; 1056 int maxErrorPos = -1; 1057 // First, parse against current pattern. 1058 // Since current pattern could be set by applyPattern(), 1059 // it could be an arbitrary pattern, and it may not be the one 1060 // defined in current locale. 1061 UBool tmpStatus[fgStatusLength]; 1062 ParsePosition tmpPos(origPos); 1063 DigitList tmpDigitList; 1064 UBool found; 1065 if (fStyle == UNUM_CURRENCY_PLURAL) { 1066 found = subparse(text, 1067 &negativePrefix, &negativeSuffix, 1068 &positivePrefix, &positiveSuffix, 1069 TRUE, UCURR_LONG_NAME, 1070 tmpPos, tmpDigitList, tmpStatus, currency); 1071 } else { 1072 found = subparse(text, 1073 &negativePrefix, &negativeSuffix, 1074 &positivePrefix, &positiveSuffix, 1075 TRUE, UCURR_SYMBOL_NAME, 1076 tmpPos, tmpDigitList, tmpStatus, currency); 1077 } 1078 if (found) { 1079 if (tmpPos.getIndex() > maxPosIndex) { 1080 maxPosIndex = tmpPos.getIndex(); 1081 for (int32_t i = 0; i < fgStatusLength; ++i) { 1082 status[i] = tmpStatus[i]; 1083 } 1084 digits = tmpDigitList; 1085 } 1086 } else { 1087 maxErrorPos = tmpPos.getErrorIndex(); 1088 } 1089 // Then, parse against affix patterns. 1090 // Those are currency patterns and currency plural patterns. 1091 int32_t pos = UHASH_FIRST; 1092 const UHashElement* element = NULL; 1093 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 1094 const UHashTok valueTok = element->value; 1095 const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer; 1096 UBool tmpStatus[fgStatusLength]; 1097 ParsePosition tmpPos(origPos); 1098 DigitList tmpDigitList; 1099 1100 #ifdef FMT_DEBUG 1101 debug("trying affix for currency.."); 1102 affixPtn->dump(); 1103 #endif 1104 1105 UBool result = subparse(text, 1106 &affixPtn->negPrefixPatternForCurrency, 1107 &affixPtn->negSuffixPatternForCurrency, 1108 &affixPtn->posPrefixPatternForCurrency, 1109 &affixPtn->posSuffixPatternForCurrency, 1110 TRUE, affixPtn->patternType, 1111 tmpPos, tmpDigitList, tmpStatus, currency); 1112 if (result) { 1113 found = true; 1114 if (tmpPos.getIndex() > maxPosIndex) { 1115 maxPosIndex = tmpPos.getIndex(); 1116 for (int32_t i = 0; i < fgStatusLength; ++i) { 1117 status[i] = tmpStatus[i]; 1118 } 1119 digits = tmpDigitList; 1120 } 1121 } else { 1122 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? 1123 tmpPos.getErrorIndex() : maxErrorPos; 1124 } 1125 } 1126 // Finally, parse against simple affix to find the match. 1127 // For example, in TestMonster suite, 1128 // if the to-be-parsed text is "-\u00A40,00". 1129 // complexAffixCompare will not find match, 1130 // since there is no ISO code matches "\u00A4", 1131 // and the parse stops at "\u00A4". 1132 // We will just use simple affix comparison (look for exact match) 1133 // to pass it. 1134 // 1135 // TODO: We should parse against simple affix first when 1136 // output currency is not requested. After the complex currency 1137 // parsing implementation was introduced, the default currency 1138 // instance parsing slowed down because of the new code flow. 1139 // I filed #10312 - Yoshito 1140 UBool tmpStatus_2[fgStatusLength]; 1141 ParsePosition tmpPos_2(origPos); 1142 DigitList tmpDigitList_2; 1143 1144 // Disable complex currency parsing and try it again. 1145 UBool result = subparse(text, 1146 &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(), 1147 &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(), 1148 &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(), 1149 &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(), 1150 FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME, 1151 tmpPos_2, tmpDigitList_2, tmpStatus_2, 1152 currency); 1153 if (result) { 1154 if (tmpPos_2.getIndex() > maxPosIndex) { 1155 maxPosIndex = tmpPos_2.getIndex(); 1156 for (int32_t i = 0; i < fgStatusLength; ++i) { 1157 status[i] = tmpStatus_2[i]; 1158 } 1159 digits = tmpDigitList_2; 1160 } 1161 found = true; 1162 } else { 1163 maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ? 1164 tmpPos_2.getErrorIndex() : maxErrorPos; 1165 } 1166 1167 if (!found) { 1168 //parsePosition.setIndex(origPos); 1169 parsePosition.setErrorIndex(maxErrorPos); 1170 } else { 1171 parsePosition.setIndex(maxPosIndex); 1172 parsePosition.setErrorIndex(-1); 1173 } 1174 return found; 1175 } 1176 1177 1178 /** 1179 * Parse the given text into a number. The text is parsed beginning at 1180 * parsePosition, until an unparseable character is seen. 1181 * @param text the string to parse. 1182 * @param negPrefix negative prefix. 1183 * @param negSuffix negative suffix. 1184 * @param posPrefix positive prefix. 1185 * @param posSuffix positive suffix. 1186 * @param complexCurrencyParsing whether it is complex currency parsing or not. 1187 * @param type the currency type to parse against, LONG_NAME only or not. 1188 * @param parsePosition The position at which to being parsing. Upon 1189 * return, the first unparsed character. 1190 * @param digits the DigitList to set to the parsed value. 1191 * @param status output param containing boolean status flags indicating 1192 * whether the value was infinite and whether it was positive. 1193 * @param currency return value for parsed currency, for generic 1194 * currency parsing mode, or NULL for normal parsing. In generic 1195 * currency parsing mode, any currency is parsed, not just the 1196 * currency that this formatter is set to. 1197 */ 1198 UBool DecimalFormat::subparse(const UnicodeString& text, 1199 const UnicodeString* negPrefix, 1200 const UnicodeString* negSuffix, 1201 const UnicodeString* posPrefix, 1202 const UnicodeString* posSuffix, 1203 UBool complexCurrencyParsing, 1204 int8_t type, 1205 ParsePosition& parsePosition, 1206 DigitList& digits, UBool* status, 1207 UChar* currency) const 1208 { 1209 // The parsing process builds up the number as char string, in the neutral format that 1210 // will be acceptable to the decNumber library, then at the end passes that string 1211 // off for conversion to a decNumber. 1212 UErrorCode err = U_ZERO_ERROR; 1213 CharString parsedNum; 1214 digits.setToZero(); 1215 1216 int32_t position = parsePosition.getIndex(); 1217 int32_t oldStart = position; 1218 int32_t textLength = text.length(); // One less pointer to follow 1219 UBool strictParse = !isLenient(); 1220 UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); 1221 const UnicodeString *groupingString = &fImpl->getConstSymbol( 1222 !fImpl->fMonetary ? 1223 DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); 1224 UChar32 groupingChar = groupingString->char32At(0); 1225 int32_t groupingStringLength = groupingString->length(); 1226 int32_t groupingCharLength = U16_LENGTH(groupingChar); 1227 UBool groupingUsed = isGroupingUsed(); 1228 #ifdef FMT_DEBUG 1229 UChar dbgbuf[300]; 1230 UnicodeString s(dbgbuf,0,300);; 1231 s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " ); 1232 #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 ")); } 1233 DBGAPPD(negPrefix); 1234 DBGAPPD(negSuffix); 1235 DBGAPPD(posPrefix); 1236 DBGAPPD(posSuffix); 1237 debugout(s); 1238 #endif 1239 1240 UBool fastParseOk = false; /* TRUE iff fast parse is OK */ 1241 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */ 1242 if((fImpl->isParseFastpath()) && !fImpl->fMonetary && 1243 text.length()>0 && 1244 text.length()<32 && 1245 (posPrefix==NULL||posPrefix->isEmpty()) && 1246 (posSuffix==NULL||posSuffix->isEmpty()) && 1247 // (negPrefix==NULL||negPrefix->isEmpty()) && 1248 // (negSuffix==NULL||(negSuffix->isEmpty()) ) && 1249 TRUE) { // optimized path 1250 int j=position; 1251 int l=text.length(); 1252 int digitCount=0; 1253 UChar32 ch = text.char32At(j); 1254 const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1255 UChar32 decimalChar = 0; 1256 UBool intOnly = FALSE; 1257 UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0; 1258 1259 int32_t decimalCount = decimalString->countChar32(0,3); 1260 if(isParseIntegerOnly()) { 1261 decimalChar = 0; // not allowed 1262 intOnly = TRUE; // Don't look for decimals. 1263 } else if(decimalCount==1) { 1264 decimalChar = decimalString->char32At(0); // Look for this decimal 1265 } else if(decimalCount==0) { 1266 decimalChar=0; // NO decimal set 1267 } else { 1268 j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation. 1269 } 1270 1271 #ifdef FMT_DEBUG 1272 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n", 1273 decimalChar, groupingChar, ch, 1274 (intOnly)?'y':'n', 1275 (strictParse)?'y':'n'); 1276 #endif 1277 if(ch==0x002D) { // '-' 1278 j=l+1;//=break - negative number. 1279 1280 /* 1281 parsedNum.append('-',err); 1282 j+=U16_LENGTH(ch); 1283 if(j<l) ch = text.char32At(j); 1284 */ 1285 } else { 1286 parsedNum.append('+',err); 1287 } 1288 while(j<l) { 1289 int32_t digit = ch - zero; 1290 if(digit >=0 && digit <= 9) { 1291 parsedNum.append((char)(digit + '0'), err); 1292 if((digitCount>0) || digit!=0 || j==(l-1)) { 1293 digitCount++; 1294 } 1295 } else if(ch == 0) { // break out 1296 digitCount=-1; 1297 break; 1298 } else if(ch == decimalChar) { 1299 parsedNum.append((char)('.'), err); 1300 decimalChar=0; // no more decimals. 1301 // fastParseHadDecimal=TRUE; 1302 } else if(ch == lookForGroup) { 1303 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep 1304 } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) { 1305 // parsing integer only and can fall through 1306 } else { 1307 digitCount=-1; // fail - fall through to slow parse 1308 break; 1309 } 1310 j+=U16_LENGTH(ch); 1311 ch = text.char32At(j); // for next 1312 } 1313 if( 1314 ((j==l)||intOnly) // end OR only parsing integer 1315 && (digitCount>0)) { // and have at least one digit 1316 fastParseOk=true; // Fast parse OK! 1317 1318 #ifdef SKIP_OPT 1319 debug("SKIP_OPT"); 1320 /* for testing, try it the slow way. also */ 1321 fastParseOk=false; 1322 parsedNum.clear(); 1323 #else 1324 parsePosition.setIndex(position=j); 1325 status[fgStatusInfinite]=false; 1326 #endif 1327 } else { 1328 // was not OK. reset, retry 1329 #ifdef FMT_DEBUG 1330 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount); 1331 #endif 1332 parsedNum.clear(); 1333 } 1334 } else { 1335 #ifdef FMT_DEBUG 1336 printf("Could not fastpath parse. "); 1337 printf("text.length()=%d ", text.length()); 1338 printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix); 1339 1340 printf("\n"); 1341 #endif 1342 } 1343 1344 UnicodeString formatPattern; 1345 toPattern(formatPattern); 1346 1347 if(!fastParseOk 1348 #if UCONFIG_HAVE_PARSEALLINPUT 1349 && fParseAllInput!=UNUM_YES 1350 #endif 1351 ) 1352 { 1353 int32_t formatWidth = fImpl->getOldFormatWidth(); 1354 // Match padding before prefix 1355 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) { 1356 position = skipPadding(text, position); 1357 } 1358 1359 // Match positive and negative prefixes; prefer longest match. 1360 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, complexCurrencyParsing, type, currency); 1361 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, complexCurrencyParsing, type, currency); 1362 if (posMatch >= 0 && negMatch >= 0) { 1363 if (posMatch > negMatch) { 1364 negMatch = -1; 1365 } else if (negMatch > posMatch) { 1366 posMatch = -1; 1367 } 1368 } 1369 if (posMatch >= 0) { 1370 position += posMatch; 1371 parsedNum.append('+', err); 1372 } else if (negMatch >= 0) { 1373 position += negMatch; 1374 parsedNum.append('-', err); 1375 } else if (strictParse){ 1376 parsePosition.setErrorIndex(position); 1377 return FALSE; 1378 } else { 1379 // Temporary set positive. This might be changed after checking suffix 1380 parsedNum.append('+', err); 1381 } 1382 1383 // Match padding before prefix 1384 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) { 1385 position = skipPadding(text, position); 1386 } 1387 1388 if (! strictParse) { 1389 position = skipUWhiteSpace(text, position); 1390 } 1391 1392 // process digits or Inf, find decimal position 1393 const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol); 1394 int32_t infLen = (text.compare(position, inf->length(), *inf) 1395 ? 0 : inf->length()); 1396 position += infLen; // infLen is non-zero when it does equal to infinity 1397 status[fgStatusInfinite] = infLen != 0; 1398 1399 if (infLen != 0) { 1400 parsedNum.append("Infinity", err); 1401 } else { 1402 // We now have a string of digits, possibly with grouping symbols, 1403 // and decimal points. We want to process these into a DigitList. 1404 // We don't want to put a bunch of leading zeros into the DigitList 1405 // though, so we keep track of the location of the decimal point, 1406 // put only significant digits into the DigitList, and adjust the 1407 // exponent as needed. 1408 1409 1410 UBool strictFail = FALSE; // did we exit with a strict parse failure? 1411 int32_t lastGroup = -1; // where did we last see a grouping separator? 1412 int32_t digitStart = position; 1413 int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping.fGrouping : fImpl->fEffGrouping.fGrouping2; 1414 1415 const UnicodeString *decimalString; 1416 if (fImpl->fMonetary) { 1417 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 1418 } else { 1419 decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 1420 } 1421 UChar32 decimalChar = decimalString->char32At(0); 1422 int32_t decimalStringLength = decimalString->length(); 1423 int32_t decimalCharLength = U16_LENGTH(decimalChar); 1424 1425 UBool sawDecimal = FALSE; 1426 UChar32 sawDecimalChar = 0xFFFF; 1427 UBool sawGrouping = FALSE; 1428 UChar32 sawGroupingChar = 0xFFFF; 1429 UBool sawDigit = FALSE; 1430 int32_t backup = -1; 1431 int32_t digit; 1432 1433 // equivalent grouping and decimal support 1434 const UnicodeSet *decimalSet = NULL; 1435 const UnicodeSet *groupingSet = NULL; 1436 1437 if (decimalCharLength == decimalStringLength) { 1438 decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse); 1439 } 1440 1441 if (groupingCharLength == groupingStringLength) { 1442 if (strictParse) { 1443 groupingSet = fStaticSets->fStrictDefaultGroupingSeparators; 1444 } else { 1445 groupingSet = fStaticSets->fDefaultGroupingSeparators; 1446 } 1447 } 1448 1449 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized. 1450 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet 1451 // If a character matches decimalSet, don't consider it to be a member of the groupingSet. 1452 1453 // We have to track digitCount ourselves, because digits.fCount will 1454 // pin when the maximum allowable digits is reached. 1455 int32_t digitCount = 0; 1456 int32_t integerDigitCount = 0; 1457 1458 for (; position < textLength; ) 1459 { 1460 UChar32 ch = text.char32At(position); 1461 1462 /* We recognize all digit ranges, not only the Latin digit range 1463 * '0'..'9'. We do so by using the Character.digit() method, 1464 * which converts a valid Unicode digit to the range 0..9. 1465 * 1466 * The character 'ch' may be a digit. If so, place its value 1467 * from 0 to 9 in 'digit'. First try using the locale digit, 1468 * which may or MAY NOT be a standard Unicode digit range. If 1469 * this fails, try using the standard Unicode digit ranges by 1470 * calling Character.digit(). If this also fails, digit will 1471 * have a value outside the range 0..9. 1472 */ 1473 digit = ch - zero; 1474 if (digit < 0 || digit > 9) 1475 { 1476 digit = u_charDigitValue(ch); 1477 } 1478 1479 // As a last resort, look through the localized digits if the zero digit 1480 // is not a "standard" Unicode digit. 1481 if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) { 1482 digit = 0; 1483 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) { 1484 break; 1485 } 1486 for (digit = 1 ; digit < 10 ; digit++ ) { 1487 if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) { 1488 break; 1489 } 1490 } 1491 } 1492 1493 if (digit >= 0 && digit <= 9) 1494 { 1495 if (strictParse && backup != -1) { 1496 // comma followed by digit, so group before comma is a 1497 // secondary group. If there was a group separator 1498 // before that, the group must == the secondary group 1499 // length, else it can be <= the the secondary group 1500 // length. 1501 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) || 1502 (lastGroup == -1 && position - digitStart - 1 > gs2)) { 1503 strictFail = TRUE; 1504 break; 1505 } 1506 1507 lastGroup = backup; 1508 } 1509 1510 // Cancel out backup setting (see grouping handler below) 1511 backup = -1; 1512 sawDigit = TRUE; 1513 1514 // Note: this will append leading zeros 1515 parsedNum.append((char)(digit + '0'), err); 1516 1517 // count any digit that's not a leading zero 1518 if (digit > 0 || digitCount > 0 || sawDecimal) { 1519 digitCount += 1; 1520 1521 // count any integer digit that's not a leading zero 1522 if (! sawDecimal) { 1523 integerDigitCount += 1; 1524 } 1525 } 1526 1527 position += U16_LENGTH(ch); 1528 } 1529 else if (groupingStringLength > 0 && 1530 matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet, 1531 decimalChar, decimalSet, 1532 ch) && groupingUsed) 1533 { 1534 if (sawDecimal) { 1535 break; 1536 } 1537 1538 if (strictParse) { 1539 if ((!sawDigit || backup != -1)) { 1540 // leading group, or two group separators in a row 1541 strictFail = TRUE; 1542 break; 1543 } 1544 } 1545 1546 // Ignore grouping characters, if we are using them, but require 1547 // that they be followed by a digit. Otherwise we backup and 1548 // reprocess them. 1549 backup = position; 1550 position += groupingStringLength; 1551 sawGrouping=TRUE; 1552 // Once we see a grouping character, we only accept that grouping character from then on. 1553 sawGroupingChar=ch; 1554 } 1555 else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch)) 1556 { 1557 if (strictParse) { 1558 if (backup != -1 || 1559 (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1)) { 1560 strictFail = TRUE; 1561 break; 1562 } 1563 } 1564 1565 // If we're only parsing integers, or if we ALREADY saw the 1566 // decimal, then don't parse this one. 1567 if (isParseIntegerOnly() || sawDecimal) { 1568 break; 1569 } 1570 1571 parsedNum.append('.', err); 1572 position += decimalStringLength; 1573 sawDecimal = TRUE; 1574 // Once we see a decimal character, we only accept that decimal character from then on. 1575 sawDecimalChar=ch; 1576 // decimalSet is considered to consist of (ch,ch) 1577 } 1578 else { 1579 1580 if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless.. 1581 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways 1582 const UnicodeString *tmp; 1583 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); 1584 // TODO: CASE 1585 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit 1586 { 1587 // Parse sign, if present 1588 int32_t pos = position + tmp->length(); 1589 char exponentSign = '+'; 1590 1591 if (pos < textLength) 1592 { 1593 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 1594 if (!text.compare(pos, tmp->length(), *tmp)) 1595 { 1596 pos += tmp->length(); 1597 } 1598 else { 1599 tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 1600 if (!text.compare(pos, tmp->length(), *tmp)) 1601 { 1602 exponentSign = '-'; 1603 pos += tmp->length(); 1604 } 1605 } 1606 } 1607 1608 UBool sawExponentDigit = FALSE; 1609 while (pos < textLength) { 1610 ch = text[(int32_t)pos]; 1611 digit = ch - zero; 1612 1613 if (digit < 0 || digit > 9) { 1614 digit = u_charDigitValue(ch); 1615 } 1616 if (0 <= digit && digit <= 9) { 1617 if (!sawExponentDigit) { 1618 parsedNum.append('E', err); 1619 parsedNum.append(exponentSign, err); 1620 sawExponentDigit = TRUE; 1621 } 1622 ++pos; 1623 parsedNum.append((char)(digit + '0'), err); 1624 } else { 1625 break; 1626 } 1627 } 1628 1629 if (sawExponentDigit) { 1630 position = pos; // Advance past the exponent 1631 } 1632 1633 break; // Whether we fail or succeed, we exit this loop 1634 } else { 1635 break; 1636 } 1637 } else { // not parsing exponent 1638 break; 1639 } 1640 } 1641 } 1642 1643 // if we didn't see a decimal and it is required, check to see if the pattern had one 1644 if(!sawDecimal && isDecimalPatternMatchRequired()) 1645 { 1646 if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0) 1647 { 1648 parsePosition.setIndex(oldStart); 1649 parsePosition.setErrorIndex(position); 1650 debug("decimal point match required fail!"); 1651 return FALSE; 1652 } 1653 } 1654 1655 if (backup != -1) 1656 { 1657 position = backup; 1658 } 1659 1660 if (strictParse && !sawDecimal) { 1661 if (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1) { 1662 strictFail = TRUE; 1663 } 1664 } 1665 1666 if (strictFail) { 1667 // only set with strictParse and a grouping separator error 1668 1669 parsePosition.setIndex(oldStart); 1670 parsePosition.setErrorIndex(position); 1671 debug("strictFail!"); 1672 return FALSE; 1673 } 1674 1675 // If there was no decimal point we have an integer 1676 1677 // If none of the text string was recognized. For example, parse 1678 // "x" with pattern "#0.00" (return index and error index both 0) 1679 // parse "$" with pattern "$#0.00". (return index 0 and error index 1680 // 1). 1681 if (!sawDigit && digitCount == 0) { 1682 #ifdef FMT_DEBUG 1683 debug("none of text rec"); 1684 printf("position=%d\n",position); 1685 #endif 1686 parsePosition.setIndex(oldStart); 1687 parsePosition.setErrorIndex(oldStart); 1688 return FALSE; 1689 } 1690 } 1691 1692 // Match padding before suffix 1693 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) { 1694 position = skipPadding(text, position); 1695 } 1696 1697 int32_t posSuffixMatch = -1, negSuffixMatch = -1; 1698 1699 // Match positive and negative suffixes; prefer longest match. 1700 if (posMatch >= 0 || (!strictParse && negMatch < 0)) { 1701 posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency); 1702 } 1703 if (negMatch >= 0) { 1704 negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency); 1705 } 1706 if (posSuffixMatch >= 0 && negSuffixMatch >= 0) { 1707 if (posSuffixMatch > negSuffixMatch) { 1708 negSuffixMatch = -1; 1709 } else if (negSuffixMatch > posSuffixMatch) { 1710 posSuffixMatch = -1; 1711 } 1712 } 1713 1714 // Fail if neither or both 1715 if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) { 1716 parsePosition.setErrorIndex(position); 1717 debug("neither or both"); 1718 return FALSE; 1719 } 1720 1721 position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0)); 1722 1723 // Match padding before suffix 1724 if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) { 1725 position = skipPadding(text, position); 1726 } 1727 1728 parsePosition.setIndex(position); 1729 1730 parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-'; 1731 #ifdef FMT_DEBUG 1732 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err)); 1733 #endif 1734 } /* end SLOW parse */ 1735 if(parsePosition.getIndex() == oldStart) 1736 { 1737 #ifdef FMT_DEBUG 1738 printf(" PP didnt move, err\n"); 1739 #endif 1740 parsePosition.setErrorIndex(position); 1741 return FALSE; 1742 } 1743 #if UCONFIG_HAVE_PARSEALLINPUT 1744 else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength) 1745 { 1746 #ifdef FMT_DEBUG 1747 printf(" PP didnt consume all (UNUM_YES), err\n"); 1748 #endif 1749 parsePosition.setErrorIndex(position); 1750 return FALSE; 1751 } 1752 #endif 1753 // uint32_t bits = (fastParseOk?kFastpathOk:0) | 1754 // (fastParseHadDecimal?0:kNoDecimal); 1755 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits); 1756 digits.set(parsedNum.toStringPiece(), 1757 err, 1758 0//bits 1759 ); 1760 1761 if (U_FAILURE(err)) { 1762 #ifdef FMT_DEBUG 1763 printf(" err setting %s\n", u_errorName(err)); 1764 #endif 1765 parsePosition.setErrorIndex(position); 1766 return FALSE; 1767 } 1768 1769 // check if we missed a required decimal point 1770 if(fastParseOk && isDecimalPatternMatchRequired()) 1771 { 1772 if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0) 1773 { 1774 parsePosition.setIndex(oldStart); 1775 parsePosition.setErrorIndex(position); 1776 debug("decimal point match required fail!"); 1777 return FALSE; 1778 } 1779 } 1780 1781 1782 return TRUE; 1783 } 1784 1785 /** 1786 * Starting at position, advance past a run of pad characters, if any. 1787 * Return the index of the first character after position that is not a pad 1788 * character. Result is >= position. 1789 */ 1790 int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const { 1791 int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar); 1792 while (position < text.length() && 1793 text.char32At(position) == fImpl->fAffixes.fPadChar) { 1794 position += padLen; 1795 } 1796 return position; 1797 } 1798 1799 /** 1800 * Return the length matched by the given affix, or -1 if none. 1801 * Runs of white space in the affix, match runs of white space in 1802 * the input. Pattern white space and input white space are 1803 * determined differently; see code. 1804 * @param text input text 1805 * @param pos offset into input at which to begin matching 1806 * @param isNegative 1807 * @param isPrefix 1808 * @param affixPat affix pattern used for currency affix comparison. 1809 * @param complexCurrencyParsing whether it is currency parsing or not 1810 * @param type the currency type to parse against, LONG_NAME only or not. 1811 * @param currency return value for parsed currency, for generic 1812 * currency parsing mode, or null for normal parsing. In generic 1813 * currency parsing mode, any currency is parsed, not just the 1814 * currency that this formatter is set to. 1815 * @return length of input that matches, or -1 if match failure 1816 */ 1817 int32_t DecimalFormat::compareAffix(const UnicodeString& text, 1818 int32_t pos, 1819 UBool isNegative, 1820 UBool isPrefix, 1821 const UnicodeString* affixPat, 1822 UBool complexCurrencyParsing, 1823 int8_t type, 1824 UChar* currency) const 1825 { 1826 const UnicodeString *patternToCompare; 1827 if (currency != NULL || 1828 (fImpl->fMonetary && complexCurrencyParsing)) { 1829 1830 if (affixPat != NULL) { 1831 return compareComplexAffix(*affixPat, text, pos, type, currency); 1832 } 1833 } 1834 1835 if (isNegative) { 1836 if (isPrefix) { 1837 patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(); 1838 } 1839 else { 1840 patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(); 1841 } 1842 } 1843 else { 1844 if (isPrefix) { 1845 patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(); 1846 } 1847 else { 1848 patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(); 1849 } 1850 } 1851 return compareSimpleAffix(*patternToCompare, text, pos, isLenient()); 1852 } 1853 1854 UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const { 1855 if (lhs == rhs) { 1856 return TRUE; 1857 } 1858 U_ASSERT(fStaticSets != NULL); // should already be loaded 1859 const UnicodeSet *minusSigns = fStaticSets->fMinusSigns; 1860 const UnicodeSet *plusSigns = fStaticSets->fPlusSigns; 1861 return (minusSigns->contains(lhs) && minusSigns->contains(rhs)) || 1862 (plusSigns->contains(lhs) && plusSigns->contains(rhs)); 1863 } 1864 1865 // check for LRM 0x200E, RLM 0x200F, ALM 0x061C 1866 #define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C) 1867 1868 #define TRIM_BUFLEN 32 1869 UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix) { 1870 UChar trimBuf[TRIM_BUFLEN]; 1871 int32_t affixLen = affix.length(); 1872 int32_t affixPos, trimLen = 0; 1873 1874 for (affixPos = 0; affixPos < affixLen; affixPos++) { 1875 UChar c = affix.charAt(affixPos); 1876 if (!IS_BIDI_MARK(c)) { 1877 if (trimLen < TRIM_BUFLEN) { 1878 trimBuf[trimLen++] = c; 1879 } else { 1880 trimLen = 0; 1881 break; 1882 } 1883 } 1884 } 1885 return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix); 1886 } 1887 1888 /** 1889 * Return the length matched by the given affix, or -1 if none. 1890 * Runs of white space in the affix, match runs of white space in 1891 * the input. Pattern white space and input white space are 1892 * determined differently; see code. 1893 * @param affix pattern string, taken as a literal 1894 * @param input input text 1895 * @param pos offset into input at which to begin matching 1896 * @return length of input that matches, or -1 if match failure 1897 */ 1898 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix, 1899 const UnicodeString& input, 1900 int32_t pos, 1901 UBool lenient) const { 1902 int32_t start = pos; 1903 UnicodeString trimmedAffix; 1904 // For more efficiency we should keep lazily-created trimmed affixes around in 1905 // instance variables instead of trimming each time they are used (the next step) 1906 trimMarksFromAffix(affix, trimmedAffix); 1907 UChar32 affixChar = trimmedAffix.char32At(0); 1908 int32_t affixLength = trimmedAffix.length(); 1909 int32_t inputLength = input.length(); 1910 int32_t affixCharLength = U16_LENGTH(affixChar); 1911 UnicodeSet *affixSet; 1912 UErrorCode status = U_ZERO_ERROR; 1913 1914 U_ASSERT(fStaticSets != NULL); // should already be loaded 1915 1916 if (U_FAILURE(status)) { 1917 return -1; 1918 } 1919 if (!lenient) { 1920 affixSet = fStaticSets->fStrictDashEquivalents; 1921 1922 // If the trimmedAffix is exactly one character long and that character 1923 // is in the dash set and the very next input character is also 1924 // in the dash set, return a match. 1925 if (affixCharLength == affixLength && affixSet->contains(affixChar)) { 1926 UChar32 ic = input.char32At(pos); 1927 if (affixSet->contains(ic)) { 1928 pos += U16_LENGTH(ic); 1929 pos = skipBidiMarks(input, pos); // skip any trailing bidi marks 1930 return pos - start; 1931 } 1932 } 1933 1934 for (int32_t i = 0; i < affixLength; ) { 1935 UChar32 c = trimmedAffix.char32At(i); 1936 int32_t len = U16_LENGTH(c); 1937 if (PatternProps::isWhiteSpace(c)) { 1938 // We may have a pattern like: \u200F \u0020 1939 // and input text like: \u200F \u0020 1940 // Note that U+200F and U+0020 are Pattern_White_Space but only 1941 // U+0020 is UWhiteSpace. So we have to first do a direct 1942 // match of the run of Pattern_White_Space in the pattern, 1943 // then match any extra characters. 1944 UBool literalMatch = FALSE; 1945 while (pos < inputLength) { 1946 UChar32 ic = input.char32At(pos); 1947 if (ic == c) { 1948 literalMatch = TRUE; 1949 i += len; 1950 pos += len; 1951 if (i == affixLength) { 1952 break; 1953 } 1954 c = trimmedAffix.char32At(i); 1955 len = U16_LENGTH(c); 1956 if (!PatternProps::isWhiteSpace(c)) { 1957 break; 1958 } 1959 } else if (IS_BIDI_MARK(ic)) { 1960 pos ++; // just skip over this input text 1961 } else { 1962 break; 1963 } 1964 } 1965 1966 // Advance over run in pattern 1967 i = skipPatternWhiteSpace(trimmedAffix, i); 1968 1969 // Advance over run in input text 1970 // Must see at least one white space char in input, 1971 // unless we've already matched some characters literally. 1972 int32_t s = pos; 1973 pos = skipUWhiteSpace(input, pos); 1974 if (pos == s && !literalMatch) { 1975 return -1; 1976 } 1977 1978 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern. 1979 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that 1980 // is also in the trimmedAffix. 1981 i = skipUWhiteSpace(trimmedAffix, i); 1982 } else { 1983 UBool match = FALSE; 1984 while (pos < inputLength) { 1985 UChar32 ic = input.char32At(pos); 1986 if (!match && ic == c) { 1987 i += len; 1988 pos += len; 1989 match = TRUE; 1990 } else if (IS_BIDI_MARK(ic)) { 1991 pos++; // just skip over this input text 1992 } else { 1993 break; 1994 } 1995 } 1996 if (!match) { 1997 return -1; 1998 } 1999 } 2000 } 2001 } else { 2002 UBool match = FALSE; 2003 2004 affixSet = fStaticSets->fDashEquivalents; 2005 2006 if (affixCharLength == affixLength && affixSet->contains(affixChar)) { 2007 pos = skipUWhiteSpaceAndMarks(input, pos); 2008 UChar32 ic = input.char32At(pos); 2009 2010 if (affixSet->contains(ic)) { 2011 pos += U16_LENGTH(ic); 2012 pos = skipBidiMarks(input, pos); 2013 return pos - start; 2014 } 2015 } 2016 2017 for (int32_t i = 0; i < affixLength; ) 2018 { 2019 //i = skipRuleWhiteSpace(trimmedAffix, i); 2020 i = skipUWhiteSpace(trimmedAffix, i); 2021 pos = skipUWhiteSpaceAndMarks(input, pos); 2022 2023 if (i >= affixLength || pos >= inputLength) { 2024 break; 2025 } 2026 2027 UChar32 c = trimmedAffix.char32At(i); 2028 UChar32 ic = input.char32At(pos); 2029 2030 if (!equalWithSignCompatibility(ic, c)) { 2031 return -1; 2032 } 2033 2034 match = TRUE; 2035 i += U16_LENGTH(c); 2036 pos += U16_LENGTH(ic); 2037 pos = skipBidiMarks(input, pos); 2038 } 2039 2040 if (affixLength > 0 && ! match) { 2041 return -1; 2042 } 2043 } 2044 return pos - start; 2045 } 2046 2047 /** 2048 * Skip over a run of zero or more Pattern_White_Space characters at 2049 * pos in text. 2050 */ 2051 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) { 2052 const UChar* s = text.getBuffer(); 2053 return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s); 2054 } 2055 2056 /** 2057 * Skip over a run of zero or more isUWhiteSpace() characters at pos 2058 * in text. 2059 */ 2060 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) { 2061 while (pos < text.length()) { 2062 UChar32 c = text.char32At(pos); 2063 if (!u_isUWhiteSpace(c)) { 2064 break; 2065 } 2066 pos += U16_LENGTH(c); 2067 } 2068 return pos; 2069 } 2070 2071 /** 2072 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos 2073 * in text. 2074 */ 2075 int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos) { 2076 while (pos < text.length()) { 2077 UChar32 c = text.char32At(pos); 2078 if (!u_isUWhiteSpace(c) && !IS_BIDI_MARK(c)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM 2079 break; 2080 } 2081 pos += U16_LENGTH(c); 2082 } 2083 return pos; 2084 } 2085 2086 /** 2087 * Skip over a run of zero or more bidi marks at pos in text. 2088 */ 2089 int32_t DecimalFormat::skipBidiMarks(const UnicodeString& text, int32_t pos) { 2090 while (pos < text.length()) { 2091 UChar c = text.charAt(pos); 2092 if (!IS_BIDI_MARK(c)) { 2093 break; 2094 } 2095 pos++; 2096 } 2097 return pos; 2098 } 2099 2100 /** 2101 * Return the length matched by the given affix, or -1 if none. 2102 * @param affixPat pattern string 2103 * @param input input text 2104 * @param pos offset into input at which to begin matching 2105 * @param type the currency type to parse against, LONG_NAME only or not. 2106 * @param currency return value for parsed currency, for generic 2107 * currency parsing mode, or null for normal parsing. In generic 2108 * currency parsing mode, any currency is parsed, not just the 2109 * currency that this formatter is set to. 2110 * @return length of input that matches, or -1 if match failure 2111 */ 2112 int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat, 2113 const UnicodeString& text, 2114 int32_t pos, 2115 int8_t type, 2116 UChar* currency) const 2117 { 2118 int32_t start = pos; 2119 U_ASSERT(currency != NULL || fImpl->fMonetary); 2120 2121 for (int32_t i=0; 2122 i<affixPat.length() && pos >= 0; ) { 2123 UChar32 c = affixPat.char32At(i); 2124 i += U16_LENGTH(c); 2125 2126 if (c == kQuote) { 2127 U_ASSERT(i <= affixPat.length()); 2128 c = affixPat.char32At(i); 2129 i += U16_LENGTH(c); 2130 2131 const UnicodeString* affix = NULL; 2132 2133 switch (c) { 2134 case kCurrencySign: { 2135 // since the currency names in choice format is saved 2136 // the same way as other currency names, 2137 // do not need to do currency choice parsing here. 2138 // the general currency parsing parse against all names, 2139 // including names in choice format. 2140 UBool intl = i<affixPat.length() && 2141 affixPat.char32At(i) == kCurrencySign; 2142 if (intl) { 2143 ++i; 2144 } 2145 UBool plural = i<affixPat.length() && 2146 affixPat.char32At(i) == kCurrencySign; 2147 if (plural) { 2148 ++i; 2149 intl = FALSE; 2150 } 2151 // Parse generic currency -- anything for which we 2152 // have a display name, or any 3-letter ISO code. 2153 // Try to parse display name for our locale; first 2154 // determine our locale. 2155 const char* loc = fCurrencyPluralInfo->getLocale().getName(); 2156 ParsePosition ppos(pos); 2157 UChar curr[4]; 2158 UErrorCode ec = U_ZERO_ERROR; 2159 // Delegate parse of display name => ISO code to Currency 2160 uprv_parseCurrency(loc, text, ppos, type, curr, ec); 2161 2162 // If parse succeeds, populate currency[0] 2163 if (U_SUCCESS(ec) && ppos.getIndex() != pos) { 2164 if (currency) { 2165 u_strcpy(currency, curr); 2166 } else { 2167 // The formatter is currency-style but the client has not requested 2168 // the value of the parsed currency. In this case, if that value does 2169 // not match the formatter's current value, then the parse fails. 2170 UChar effectiveCurr[4]; 2171 getEffectiveCurrency(effectiveCurr, ec); 2172 if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) { 2173 pos = -1; 2174 continue; 2175 } 2176 } 2177 pos = ppos.getIndex(); 2178 } else if (!isLenient()){ 2179 pos = -1; 2180 } 2181 continue; 2182 } 2183 case kPatternPercent: 2184 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSymbol); 2185 break; 2186 case kPatternPerMill: 2187 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); 2188 break; 2189 case kPatternPlus: 2190 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); 2191 break; 2192 case kPatternMinus: 2193 affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); 2194 break; 2195 default: 2196 // fall through to affix!=0 test, which will fail 2197 break; 2198 } 2199 2200 if (affix != NULL) { 2201 pos = match(text, pos, *affix); 2202 continue; 2203 } 2204 } 2205 2206 pos = match(text, pos, c); 2207 if (PatternProps::isWhiteSpace(c)) { 2208 i = skipPatternWhiteSpace(affixPat, i); 2209 } 2210 } 2211 return pos - start; 2212 } 2213 2214 /** 2215 * Match a single character at text[pos] and return the index of the 2216 * next character upon success. Return -1 on failure. If 2217 * ch is a Pattern_White_Space then match a run of white space in text. 2218 */ 2219 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) { 2220 if (PatternProps::isWhiteSpace(ch)) { 2221 // Advance over run of white space in input text 2222 // Must see at least one white space char in input 2223 int32_t s = pos; 2224 pos = skipPatternWhiteSpace(text, pos); 2225 if (pos == s) { 2226 return -1; 2227 } 2228 return pos; 2229 } 2230 return (pos >= 0 && text.char32At(pos) == ch) ? 2231 (pos + U16_LENGTH(ch)) : -1; 2232 } 2233 2234 /** 2235 * Match a string at text[pos] and return the index of the next 2236 * character upon success. Return -1 on failure. Match a run of 2237 * white space in str with a run of white space in text. 2238 */ 2239 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) { 2240 for (int32_t i=0; i<str.length() && pos >= 0; ) { 2241 UChar32 ch = str.char32At(i); 2242 i += U16_LENGTH(ch); 2243 if (PatternProps::isWhiteSpace(ch)) { 2244 i = skipPatternWhiteSpace(str, i); 2245 } 2246 pos = match(text, pos, ch); 2247 } 2248 return pos; 2249 } 2250 2251 UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol, 2252 UnicodeSet *sset, UChar32 schar) 2253 { 2254 if (sset != NULL) { 2255 return sset->contains(schar); 2256 } 2257 2258 return text.compare(position, length, symbol) == 0; 2259 } 2260 2261 UBool DecimalFormat::matchDecimal(UChar32 symbolChar, 2262 UBool sawDecimal, UChar32 sawDecimalChar, 2263 const UnicodeSet *sset, UChar32 schar) { 2264 if(sawDecimal) { 2265 return schar==sawDecimalChar; 2266 } else if(schar==symbolChar) { 2267 return TRUE; 2268 } else if(sset!=NULL) { 2269 return sset->contains(schar); 2270 } else { 2271 return FALSE; 2272 } 2273 } 2274 2275 UBool DecimalFormat::matchGrouping(UChar32 groupingChar, 2276 UBool sawGrouping, UChar32 sawGroupingChar, 2277 const UnicodeSet *sset, 2278 UChar32 /*decimalChar*/, const UnicodeSet *decimalSet, 2279 UChar32 schar) { 2280 if(sawGrouping) { 2281 return schar==sawGroupingChar; // previously found 2282 } else if(schar==groupingChar) { 2283 return TRUE; // char from symbols 2284 } else if(sset!=NULL) { 2285 return sset->contains(schar) && // in groupingSet but... 2286 ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet 2287 } else { 2288 return FALSE; 2289 } 2290 } 2291 2292 2293 2294 //------------------------------------------------------------------------------ 2295 // Gets the pointer to the localized decimal format symbols 2296 2297 const DecimalFormatSymbols* 2298 DecimalFormat::getDecimalFormatSymbols() const 2299 { 2300 return &fImpl->getDecimalFormatSymbols(); 2301 } 2302 2303 //------------------------------------------------------------------------------ 2304 // De-owning the current localized symbols and adopt the new symbols. 2305 2306 void 2307 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) 2308 { 2309 if (symbolsToAdopt == NULL) { 2310 return; // do not allow caller to set fSymbols to NULL 2311 } 2312 fImpl->adoptDecimalFormatSymbols(symbolsToAdopt); 2313 } 2314 //------------------------------------------------------------------------------ 2315 // Setting the symbols is equlivalent to adopting a newly created localized 2316 // symbols. 2317 2318 void 2319 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) 2320 { 2321 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); 2322 } 2323 2324 2325 const CurrencyPluralInfo* 2326 DecimalFormat::getCurrencyPluralInfo(void) const 2327 { 2328 return fCurrencyPluralInfo; 2329 } 2330 2331 2332 void 2333 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) 2334 { 2335 if (toAdopt != NULL) { 2336 delete fCurrencyPluralInfo; 2337 fCurrencyPluralInfo = toAdopt; 2338 // re-set currency affix patterns and currency affixes. 2339 if (fImpl->fMonetary) { 2340 UErrorCode status = U_ZERO_ERROR; 2341 if (fAffixPatternsForCurrency) { 2342 deleteHashForAffixPattern(); 2343 } 2344 setupCurrencyAffixPatterns(status); 2345 } 2346 } 2347 } 2348 2349 void 2350 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) 2351 { 2352 adoptCurrencyPluralInfo(info.clone()); 2353 } 2354 2355 2356 //------------------------------------------------------------------------------ 2357 // Gets the positive prefix of the number pattern. 2358 2359 UnicodeString& 2360 DecimalFormat::getPositivePrefix(UnicodeString& result) const 2361 { 2362 return fImpl->getPositivePrefix(result); 2363 } 2364 2365 //------------------------------------------------------------------------------ 2366 // Sets the positive prefix of the number pattern. 2367 2368 void 2369 DecimalFormat::setPositivePrefix(const UnicodeString& newValue) 2370 { 2371 fImpl->setPositivePrefix(newValue); 2372 } 2373 2374 //------------------------------------------------------------------------------ 2375 // Gets the negative prefix of the number pattern. 2376 2377 UnicodeString& 2378 DecimalFormat::getNegativePrefix(UnicodeString& result) const 2379 { 2380 return fImpl->getNegativePrefix(result); 2381 } 2382 2383 //------------------------------------------------------------------------------ 2384 // Gets the negative prefix of the number pattern. 2385 2386 void 2387 DecimalFormat::setNegativePrefix(const UnicodeString& newValue) 2388 { 2389 fImpl->setNegativePrefix(newValue); 2390 } 2391 2392 //------------------------------------------------------------------------------ 2393 // Gets the positive suffix of the number pattern. 2394 2395 UnicodeString& 2396 DecimalFormat::getPositiveSuffix(UnicodeString& result) const 2397 { 2398 return fImpl->getPositiveSuffix(result); 2399 } 2400 2401 //------------------------------------------------------------------------------ 2402 // Sets the positive suffix of the number pattern. 2403 2404 void 2405 DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) 2406 { 2407 fImpl->setPositiveSuffix(newValue); 2408 } 2409 2410 //------------------------------------------------------------------------------ 2411 // Gets the negative suffix of the number pattern. 2412 2413 UnicodeString& 2414 DecimalFormat::getNegativeSuffix(UnicodeString& result) const 2415 { 2416 return fImpl->getNegativeSuffix(result); 2417 } 2418 2419 //------------------------------------------------------------------------------ 2420 // Sets the negative suffix of the number pattern. 2421 2422 void 2423 DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) 2424 { 2425 fImpl->setNegativeSuffix(newValue); 2426 } 2427 2428 //------------------------------------------------------------------------------ 2429 // Gets the multiplier of the number pattern. 2430 // Multipliers are stored as decimal numbers (DigitLists) because that 2431 // is the most convenient for muliplying or dividing the numbers to be formatted. 2432 // A NULL multiplier implies one, and the scaling operations are skipped. 2433 2434 int32_t 2435 DecimalFormat::getMultiplier() const 2436 { 2437 return fImpl->getMultiplier(); 2438 } 2439 2440 //------------------------------------------------------------------------------ 2441 // Sets the multiplier of the number pattern. 2442 void 2443 DecimalFormat::setMultiplier(int32_t newValue) 2444 { 2445 fImpl->setMultiplier(newValue); 2446 } 2447 2448 /** 2449 * Get the rounding increment. 2450 * @return A positive rounding increment, or 0.0 if rounding 2451 * is not in effect. 2452 * @see #setRoundingIncrement 2453 * @see #getRoundingMode 2454 * @see #setRoundingMode 2455 */ 2456 double DecimalFormat::getRoundingIncrement() const { 2457 return fImpl->getRoundingIncrement(); 2458 } 2459 2460 /** 2461 * Set the rounding increment. This method also controls whether 2462 * rounding is enabled. 2463 * @param newValue A positive rounding increment, or 0.0 to disable rounding. 2464 * Negative increments are equivalent to 0.0. 2465 * @see #getRoundingIncrement 2466 * @see #getRoundingMode 2467 * @see #setRoundingMode 2468 */ 2469 void DecimalFormat::setRoundingIncrement(double newValue) { 2470 fImpl->setRoundingIncrement(newValue); 2471 } 2472 2473 /** 2474 * Get the rounding mode. 2475 * @return A rounding mode 2476 * @see #setRoundingIncrement 2477 * @see #getRoundingIncrement 2478 * @see #setRoundingMode 2479 */ 2480 DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const { 2481 return fImpl->getRoundingMode(); 2482 } 2483 2484 /** 2485 * Set the rounding mode. This has no effect unless the rounding 2486 * increment is greater than zero. 2487 * @param roundingMode A rounding mode 2488 * @see #setRoundingIncrement 2489 * @see #getRoundingIncrement 2490 * @see #getRoundingMode 2491 */ 2492 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) { 2493 fImpl->setRoundingMode(roundingMode); 2494 } 2495 2496 /** 2497 * Get the width to which the output of <code>format()</code> is padded. 2498 * @return the format width, or zero if no padding is in effect 2499 * @see #setFormatWidth 2500 * @see #getPadCharacter 2501 * @see #setPadCharacter 2502 * @see #getPadPosition 2503 * @see #setPadPosition 2504 */ 2505 int32_t DecimalFormat::getFormatWidth() const { 2506 return fImpl->getFormatWidth(); 2507 } 2508 2509 /** 2510 * Set the width to which the output of <code>format()</code> is padded. 2511 * This method also controls whether padding is enabled. 2512 * @param width the width to which to pad the result of 2513 * <code>format()</code>, or zero to disable padding. A negative 2514 * width is equivalent to 0. 2515 * @see #getFormatWidth 2516 * @see #getPadCharacter 2517 * @see #setPadCharacter 2518 * @see #getPadPosition 2519 * @see #setPadPosition 2520 */ 2521 void DecimalFormat::setFormatWidth(int32_t width) { 2522 int32_t formatWidth = (width > 0) ? width : 0; 2523 fImpl->setFormatWidth(formatWidth); 2524 } 2525 2526 UnicodeString DecimalFormat::getPadCharacterString() const { 2527 return UnicodeString(fImpl->getPadCharacter()); 2528 } 2529 2530 void DecimalFormat::setPadCharacter(const UnicodeString &padChar) { 2531 UChar pad; 2532 if (padChar.length() > 0) { 2533 pad = padChar.char32At(0); 2534 } 2535 else { 2536 pad = kDefaultPad; 2537 } 2538 fImpl->setPadCharacter(pad); 2539 } 2540 2541 static DecimalFormat::EPadPosition fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos) { 2542 switch (padPos) { 2543 case DigitAffixesAndPadding::kPadBeforePrefix: 2544 return DecimalFormat::kPadBeforePrefix; 2545 case DigitAffixesAndPadding::kPadAfterPrefix: 2546 return DecimalFormat::kPadAfterPrefix; 2547 case DigitAffixesAndPadding::kPadBeforeSuffix: 2548 return DecimalFormat::kPadBeforeSuffix; 2549 case DigitAffixesAndPadding::kPadAfterSuffix: 2550 return DecimalFormat::kPadAfterSuffix; 2551 default: 2552 U_ASSERT(FALSE); 2553 break; 2554 } 2555 return DecimalFormat::kPadBeforePrefix; 2556 } 2557 2558 /** 2559 * Get the position at which padding will take place. This is the location 2560 * at which padding will be inserted if the result of <code>format()</code> 2561 * is shorter than the format width. 2562 * @return the pad position, one of <code>kPadBeforePrefix</code>, 2563 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 2564 * <code>kPadAfterSuffix</code>. 2565 * @see #setFormatWidth 2566 * @see #getFormatWidth 2567 * @see #setPadCharacter 2568 * @see #getPadCharacter 2569 * @see #setPadPosition 2570 * @see #kPadBeforePrefix 2571 * @see #kPadAfterPrefix 2572 * @see #kPadBeforeSuffix 2573 * @see #kPadAfterSuffix 2574 */ 2575 DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const { 2576 return fromPadPosition(fImpl->getPadPosition()); 2577 } 2578 2579 static DigitAffixesAndPadding::EPadPosition toPadPosition(DecimalFormat::EPadPosition padPos) { 2580 switch (padPos) { 2581 case DecimalFormat::kPadBeforePrefix: 2582 return DigitAffixesAndPadding::kPadBeforePrefix; 2583 case DecimalFormat::kPadAfterPrefix: 2584 return DigitAffixesAndPadding::kPadAfterPrefix; 2585 case DecimalFormat::kPadBeforeSuffix: 2586 return DigitAffixesAndPadding::kPadBeforeSuffix; 2587 case DecimalFormat::kPadAfterSuffix: 2588 return DigitAffixesAndPadding::kPadAfterSuffix; 2589 default: 2590 U_ASSERT(FALSE); 2591 break; 2592 } 2593 return DigitAffixesAndPadding::kPadBeforePrefix; 2594 } 2595 2596 /** 2597 * <strong><font face=helvetica color=red>NEW</font></strong> 2598 * Set the position at which padding will take place. This is the location 2599 * at which padding will be inserted if the result of <code>format()</code> 2600 * is shorter than the format width. This has no effect unless padding is 2601 * enabled. 2602 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>, 2603 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or 2604 * <code>kPadAfterSuffix</code>. 2605 * @see #setFormatWidth 2606 * @see #getFormatWidth 2607 * @see #setPadCharacter 2608 * @see #getPadCharacter 2609 * @see #getPadPosition 2610 * @see #kPadBeforePrefix 2611 * @see #kPadAfterPrefix 2612 * @see #kPadBeforeSuffix 2613 * @see #kPadAfterSuffix 2614 */ 2615 void DecimalFormat::setPadPosition(EPadPosition padPos) { 2616 fImpl->setPadPosition(toPadPosition(padPos)); 2617 } 2618 2619 /** 2620 * Return whether or not scientific notation is used. 2621 * @return TRUE if this object formats and parses scientific notation 2622 * @see #setScientificNotation 2623 * @see #getMinimumExponentDigits 2624 * @see #setMinimumExponentDigits 2625 * @see #isExponentSignAlwaysShown 2626 * @see #setExponentSignAlwaysShown 2627 */ 2628 UBool DecimalFormat::isScientificNotation() const { 2629 return fImpl->isScientificNotation(); 2630 } 2631 2632 /** 2633 * Set whether or not scientific notation is used. 2634 * @param useScientific TRUE if this object formats and parses scientific 2635 * notation 2636 * @see #isScientificNotation 2637 * @see #getMinimumExponentDigits 2638 * @see #setMinimumExponentDigits 2639 * @see #isExponentSignAlwaysShown 2640 * @see #setExponentSignAlwaysShown 2641 */ 2642 void DecimalFormat::setScientificNotation(UBool useScientific) { 2643 fImpl->setScientificNotation(useScientific); 2644 } 2645 2646 /** 2647 * Return the minimum exponent digits that will be shown. 2648 * @return the minimum exponent digits that will be shown 2649 * @see #setScientificNotation 2650 * @see #isScientificNotation 2651 * @see #setMinimumExponentDigits 2652 * @see #isExponentSignAlwaysShown 2653 * @see #setExponentSignAlwaysShown 2654 */ 2655 int8_t DecimalFormat::getMinimumExponentDigits() const { 2656 return fImpl->getMinimumExponentDigits(); 2657 } 2658 2659 /** 2660 * Set the minimum exponent digits that will be shown. This has no 2661 * effect unless scientific notation is in use. 2662 * @param minExpDig a value >= 1 indicating the fewest exponent digits 2663 * that will be shown. Values less than 1 will be treated as 1. 2664 * @see #setScientificNotation 2665 * @see #isScientificNotation 2666 * @see #getMinimumExponentDigits 2667 * @see #isExponentSignAlwaysShown 2668 * @see #setExponentSignAlwaysShown 2669 */ 2670 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) { 2671 int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1); 2672 fImpl->setMinimumExponentDigits(minExponentDigits); 2673 } 2674 2675 /** 2676 * Return whether the exponent sign is always shown. 2677 * @return TRUE if the exponent is always prefixed with either the 2678 * localized minus sign or the localized plus sign, false if only negative 2679 * exponents are prefixed with the localized minus sign. 2680 * @see #setScientificNotation 2681 * @see #isScientificNotation 2682 * @see #setMinimumExponentDigits 2683 * @see #getMinimumExponentDigits 2684 * @see #setExponentSignAlwaysShown 2685 */ 2686 UBool DecimalFormat::isExponentSignAlwaysShown() const { 2687 return fImpl->isExponentSignAlwaysShown(); 2688 } 2689 2690 /** 2691 * Set whether the exponent sign is always shown. This has no effect 2692 * unless scientific notation is in use. 2693 * @param expSignAlways TRUE if the exponent is always prefixed with either 2694 * the localized minus sign or the localized plus sign, false if only 2695 * negative exponents are prefixed with the localized minus sign. 2696 * @see #setScientificNotation 2697 * @see #isScientificNotation 2698 * @see #setMinimumExponentDigits 2699 * @see #getMinimumExponentDigits 2700 * @see #isExponentSignAlwaysShown 2701 */ 2702 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { 2703 fImpl->setExponentSignAlwaysShown(expSignAlways); 2704 } 2705 2706 //------------------------------------------------------------------------------ 2707 // Gets the grouping size of the number pattern. For example, thousand or 10 2708 // thousand groupings. 2709 2710 int32_t 2711 DecimalFormat::getGroupingSize() const 2712 { 2713 return fImpl->getGroupingSize(); 2714 } 2715 2716 //------------------------------------------------------------------------------ 2717 // Gets the grouping size of the number pattern. 2718 2719 void 2720 DecimalFormat::setGroupingSize(int32_t newValue) 2721 { 2722 fImpl->setGroupingSize(newValue); 2723 } 2724 2725 //------------------------------------------------------------------------------ 2726 2727 int32_t 2728 DecimalFormat::getSecondaryGroupingSize() const 2729 { 2730 return fImpl->getSecondaryGroupingSize(); 2731 } 2732 2733 //------------------------------------------------------------------------------ 2734 2735 void 2736 DecimalFormat::setSecondaryGroupingSize(int32_t newValue) 2737 { 2738 fImpl->setSecondaryGroupingSize(newValue); 2739 } 2740 2741 //------------------------------------------------------------------------------ 2742 2743 int32_t 2744 DecimalFormat::getMinimumGroupingDigits() const 2745 { 2746 return fImpl->getMinimumGroupingDigits(); 2747 } 2748 2749 //------------------------------------------------------------------------------ 2750 2751 void 2752 DecimalFormat::setMinimumGroupingDigits(int32_t newValue) 2753 { 2754 fImpl->setMinimumGroupingDigits(newValue); 2755 } 2756 2757 //------------------------------------------------------------------------------ 2758 // Checks if to show the decimal separator. 2759 2760 UBool 2761 DecimalFormat::isDecimalSeparatorAlwaysShown() const 2762 { 2763 return fImpl->isDecimalSeparatorAlwaysShown(); 2764 } 2765 2766 //------------------------------------------------------------------------------ 2767 // Sets to always show the decimal separator. 2768 2769 void 2770 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) 2771 { 2772 fImpl->setDecimalSeparatorAlwaysShown(newValue); 2773 } 2774 2775 //------------------------------------------------------------------------------ 2776 // Checks if decimal point pattern match is required 2777 UBool 2778 DecimalFormat::isDecimalPatternMatchRequired(void) const 2779 { 2780 return fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED); 2781 } 2782 2783 //------------------------------------------------------------------------------ 2784 // Checks if decimal point pattern match is required 2785 2786 void 2787 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) 2788 { 2789 fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue); 2790 } 2791 2792 2793 //------------------------------------------------------------------------------ 2794 // Emits the pattern of this DecimalFormat instance. 2795 2796 UnicodeString& 2797 DecimalFormat::toPattern(UnicodeString& result) const 2798 { 2799 return fImpl->toPattern(result); 2800 } 2801 2802 //------------------------------------------------------------------------------ 2803 // Emits the localized pattern this DecimalFormat instance. 2804 2805 UnicodeString& 2806 DecimalFormat::toLocalizedPattern(UnicodeString& result) const 2807 { 2808 // toLocalizedPattern is deprecated, so we just make it the same as 2809 // toPattern. 2810 return fImpl->toPattern(result); 2811 } 2812 2813 //------------------------------------------------------------------------------ 2814 2815 void 2816 DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) 2817 { 2818 fImpl->applyPattern(pattern, status); 2819 } 2820 2821 //------------------------------------------------------------------------------ 2822 2823 void 2824 DecimalFormat::applyPattern(const UnicodeString& pattern, 2825 UParseError& parseError, 2826 UErrorCode& status) 2827 { 2828 fImpl->applyPattern(pattern, parseError, status); 2829 } 2830 //------------------------------------------------------------------------------ 2831 2832 void 2833 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status) 2834 { 2835 fImpl->applyLocalizedPattern(pattern, status); 2836 } 2837 2838 //------------------------------------------------------------------------------ 2839 2840 void 2841 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, 2842 UParseError& parseError, 2843 UErrorCode& status) 2844 { 2845 fImpl->applyLocalizedPattern(pattern, parseError, status); 2846 } 2847 2848 //------------------------------------------------------------------------------ 2849 2850 /** 2851 * Sets the maximum number of digits allowed in the integer portion of a 2852 * number. 2853 * @see NumberFormat#setMaximumIntegerDigits 2854 */ 2855 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) { 2856 newValue = _min(newValue, gDefaultMaxIntegerDigits); 2857 NumberFormat::setMaximumIntegerDigits(newValue); 2858 fImpl->updatePrecision(); 2859 } 2860 2861 /** 2862 * Sets the minimum number of digits allowed in the integer portion of a 2863 * number. This override limits the integer digit count to 309. 2864 * @see NumberFormat#setMinimumIntegerDigits 2865 */ 2866 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) { 2867 newValue = _min(newValue, kDoubleIntegerDigits); 2868 NumberFormat::setMinimumIntegerDigits(newValue); 2869 fImpl->updatePrecision(); 2870 } 2871 2872 /** 2873 * Sets the maximum number of digits allowed in the fraction portion of a 2874 * number. This override limits the fraction digit count to 340. 2875 * @see NumberFormat#setMaximumFractionDigits 2876 */ 2877 void DecimalFormat::setMaximumFractionDigits(int32_t newValue) { 2878 newValue = _min(newValue, kDoubleFractionDigits); 2879 NumberFormat::setMaximumFractionDigits(newValue); 2880 fImpl->updatePrecision(); 2881 } 2882 2883 /** 2884 * Sets the minimum number of digits allowed in the fraction portion of a 2885 * number. This override limits the fraction digit count to 340. 2886 * @see NumberFormat#setMinimumFractionDigits 2887 */ 2888 void DecimalFormat::setMinimumFractionDigits(int32_t newValue) { 2889 newValue = _min(newValue, kDoubleFractionDigits); 2890 NumberFormat::setMinimumFractionDigits(newValue); 2891 fImpl->updatePrecision(); 2892 } 2893 2894 int32_t DecimalFormat::getMinimumSignificantDigits() const { 2895 return fImpl->getMinimumSignificantDigits(); 2896 } 2897 2898 int32_t DecimalFormat::getMaximumSignificantDigits() const { 2899 return fImpl->getMaximumSignificantDigits(); 2900 } 2901 2902 void DecimalFormat::setMinimumSignificantDigits(int32_t min) { 2903 if (min < 1) { 2904 min = 1; 2905 } 2906 // pin max sig dig to >= min 2907 int32_t max = _max(fImpl->fMaxSigDigits, min); 2908 fImpl->setMinMaxSignificantDigits(min, max); 2909 } 2910 2911 void DecimalFormat::setMaximumSignificantDigits(int32_t max) { 2912 if (max < 1) { 2913 max = 1; 2914 } 2915 // pin min sig dig to 1..max 2916 U_ASSERT(fImpl->fMinSigDigits >= 1); 2917 int32_t min = _min(fImpl->fMinSigDigits, max); 2918 fImpl->setMinMaxSignificantDigits(min, max); 2919 } 2920 2921 UBool DecimalFormat::areSignificantDigitsUsed() const { 2922 return fImpl->areSignificantDigitsUsed(); 2923 } 2924 2925 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) { 2926 fImpl->setSignificantDigitsUsed(useSignificantDigits); 2927 } 2928 2929 void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { 2930 // set the currency before compute affixes to get the right currency names 2931 NumberFormat::setCurrency(theCurrency, ec); 2932 fImpl->updateCurrency(ec); 2933 } 2934 2935 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){ 2936 fImpl->setCurrencyUsage(newContext, *ec); 2937 } 2938 2939 UCurrencyUsage DecimalFormat::getCurrencyUsage() const { 2940 return fImpl->getCurrencyUsage(); 2941 } 2942 2943 // Deprecated variant with no UErrorCode parameter 2944 void DecimalFormat::setCurrency(const UChar* theCurrency) { 2945 UErrorCode ec = U_ZERO_ERROR; 2946 setCurrency(theCurrency, ec); 2947 } 2948 2949 void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { 2950 if (fImpl->fSymbols == NULL) { 2951 ec = U_MEMORY_ALLOCATION_ERROR; 2952 return; 2953 } 2954 ec = U_ZERO_ERROR; 2955 const UChar* c = getCurrency(); 2956 if (*c == 0) { 2957 const UnicodeString &intl = 2958 fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 2959 c = intl.getBuffer(); // ok for intl to go out of scope 2960 } 2961 u_strncpy(result, c, 3); 2962 result[3] = 0; 2963 } 2964 2965 Hashtable* 2966 DecimalFormat::initHashForAffixPattern(UErrorCode& status) { 2967 if ( U_FAILURE(status) ) { 2968 return NULL; 2969 } 2970 Hashtable* hTable; 2971 if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 2972 status = U_MEMORY_ALLOCATION_ERROR; 2973 return NULL; 2974 } 2975 if ( U_FAILURE(status) ) { 2976 delete hTable; 2977 return NULL; 2978 } 2979 hTable->setValueComparator(decimfmtAffixPatternValueComparator); 2980 return hTable; 2981 } 2982 2983 void 2984 DecimalFormat::deleteHashForAffixPattern() 2985 { 2986 if ( fAffixPatternsForCurrency == NULL ) { 2987 return; 2988 } 2989 int32_t pos = UHASH_FIRST; 2990 const UHashElement* element = NULL; 2991 while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { 2992 const UHashTok valueTok = element->value; 2993 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; 2994 delete value; 2995 } 2996 delete fAffixPatternsForCurrency; 2997 fAffixPatternsForCurrency = NULL; 2998 } 2999 3000 3001 void 3002 DecimalFormat::copyHashForAffixPattern(const Hashtable* source, 3003 Hashtable* target, 3004 UErrorCode& status) { 3005 if ( U_FAILURE(status) ) { 3006 return; 3007 } 3008 int32_t pos = UHASH_FIRST; 3009 const UHashElement* element = NULL; 3010 if ( source ) { 3011 while ( (element = source->nextElement(pos)) != NULL ) { 3012 const UHashTok keyTok = element->key; 3013 const UnicodeString* key = (UnicodeString*)keyTok.pointer; 3014 const UHashTok valueTok = element->value; 3015 const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; 3016 AffixPatternsForCurrency* copy = new AffixPatternsForCurrency( 3017 value->negPrefixPatternForCurrency, 3018 value->negSuffixPatternForCurrency, 3019 value->posPrefixPatternForCurrency, 3020 value->posSuffixPatternForCurrency, 3021 value->patternType); 3022 target->put(UnicodeString(*key), copy, status); 3023 if ( U_FAILURE(status) ) { 3024 return; 3025 } 3026 } 3027 } 3028 } 3029 3030 void 3031 DecimalFormat::setGroupingUsed(UBool newValue) { 3032 NumberFormat::setGroupingUsed(newValue); 3033 fImpl->updateGrouping(); 3034 } 3035 3036 void 3037 DecimalFormat::setParseIntegerOnly(UBool newValue) { 3038 NumberFormat::setParseIntegerOnly(newValue); 3039 } 3040 3041 void 3042 DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) { 3043 NumberFormat::setContext(value, status); 3044 } 3045 3046 DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, 3047 int32_t newValue, 3048 UErrorCode &status) { 3049 if(U_FAILURE(status)) return *this; 3050 3051 switch(attr) { 3052 case UNUM_LENIENT_PARSE: 3053 setLenient(newValue!=0); 3054 break; 3055 3056 case UNUM_PARSE_INT_ONLY: 3057 setParseIntegerOnly(newValue!=0); 3058 break; 3059 3060 case UNUM_GROUPING_USED: 3061 setGroupingUsed(newValue!=0); 3062 break; 3063 3064 case UNUM_DECIMAL_ALWAYS_SHOWN: 3065 setDecimalSeparatorAlwaysShown(newValue!=0); 3066 break; 3067 3068 case UNUM_MAX_INTEGER_DIGITS: 3069 setMaximumIntegerDigits(newValue); 3070 break; 3071 3072 case UNUM_MIN_INTEGER_DIGITS: 3073 setMinimumIntegerDigits(newValue); 3074 break; 3075 3076 case UNUM_INTEGER_DIGITS: 3077 setMinimumIntegerDigits(newValue); 3078 setMaximumIntegerDigits(newValue); 3079 break; 3080 3081 case UNUM_MAX_FRACTION_DIGITS: 3082 setMaximumFractionDigits(newValue); 3083 break; 3084 3085 case UNUM_MIN_FRACTION_DIGITS: 3086 setMinimumFractionDigits(newValue); 3087 break; 3088 3089 case UNUM_FRACTION_DIGITS: 3090 setMinimumFractionDigits(newValue); 3091 setMaximumFractionDigits(newValue); 3092 break; 3093 3094 case UNUM_SIGNIFICANT_DIGITS_USED: 3095 setSignificantDigitsUsed(newValue!=0); 3096 break; 3097 3098 case UNUM_MAX_SIGNIFICANT_DIGITS: 3099 setMaximumSignificantDigits(newValue); 3100 break; 3101 3102 case UNUM_MIN_SIGNIFICANT_DIGITS: 3103 setMinimumSignificantDigits(newValue); 3104 break; 3105 3106 case UNUM_MULTIPLIER: 3107 setMultiplier(newValue); 3108 break; 3109 3110 case UNUM_GROUPING_SIZE: 3111 setGroupingSize(newValue); 3112 break; 3113 3114 case UNUM_ROUNDING_MODE: 3115 setRoundingMode((DecimalFormat::ERoundingMode)newValue); 3116 break; 3117 3118 case UNUM_FORMAT_WIDTH: 3119 setFormatWidth(newValue); 3120 break; 3121 3122 case UNUM_PADDING_POSITION: 3123 /** The position at which padding will take place. */ 3124 setPadPosition((DecimalFormat::EPadPosition)newValue); 3125 break; 3126 3127 case UNUM_SECONDARY_GROUPING_SIZE: 3128 setSecondaryGroupingSize(newValue); 3129 break; 3130 3131 #if UCONFIG_HAVE_PARSEALLINPUT 3132 case UNUM_PARSE_ALL_INPUT: 3133 setParseAllInput((UNumberFormatAttributeValue)newValue); 3134 break; 3135 #endif 3136 3137 /* These are stored in fBoolFlags */ 3138 case UNUM_PARSE_NO_EXPONENT: 3139 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 3140 case UNUM_PARSE_DECIMAL_MARK_REQUIRED: 3141 if(!fBoolFlags.isValidValue(newValue)) { 3142 status = U_ILLEGAL_ARGUMENT_ERROR; 3143 } else { 3144 if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) { 3145 fImpl->setFailIfMoreThanMaxDigits((UBool) newValue); 3146 } 3147 fBoolFlags.set(attr, newValue); 3148 } 3149 break; 3150 3151 case UNUM_SCALE: 3152 fImpl->setScale(newValue); 3153 break; 3154 3155 case UNUM_CURRENCY_USAGE: 3156 setCurrencyUsage((UCurrencyUsage)newValue, &status); 3157 break; 3158 3159 case UNUM_MINIMUM_GROUPING_DIGITS: 3160 setMinimumGroupingDigits(newValue); 3161 break; 3162 3163 default: 3164 status = U_UNSUPPORTED_ERROR; 3165 break; 3166 } 3167 return *this; 3168 } 3169 3170 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr, 3171 UErrorCode &status ) const { 3172 if(U_FAILURE(status)) return -1; 3173 switch(attr) { 3174 case UNUM_LENIENT_PARSE: 3175 return isLenient(); 3176 3177 case UNUM_PARSE_INT_ONLY: 3178 return isParseIntegerOnly(); 3179 3180 case UNUM_GROUPING_USED: 3181 return isGroupingUsed(); 3182 3183 case UNUM_DECIMAL_ALWAYS_SHOWN: 3184 return isDecimalSeparatorAlwaysShown(); 3185 3186 case UNUM_MAX_INTEGER_DIGITS: 3187 return getMaximumIntegerDigits(); 3188 3189 case UNUM_MIN_INTEGER_DIGITS: 3190 return getMinimumIntegerDigits(); 3191 3192 case UNUM_INTEGER_DIGITS: 3193 // TBD: what should this return? 3194 return getMinimumIntegerDigits(); 3195 3196 case UNUM_MAX_FRACTION_DIGITS: 3197 return getMaximumFractionDigits(); 3198 3199 case UNUM_MIN_FRACTION_DIGITS: 3200 return getMinimumFractionDigits(); 3201 3202 case UNUM_FRACTION_DIGITS: 3203 // TBD: what should this return? 3204 return getMinimumFractionDigits(); 3205 3206 case UNUM_SIGNIFICANT_DIGITS_USED: 3207 return areSignificantDigitsUsed(); 3208 3209 case UNUM_MAX_SIGNIFICANT_DIGITS: 3210 return getMaximumSignificantDigits(); 3211 3212 case UNUM_MIN_SIGNIFICANT_DIGITS: 3213 return getMinimumSignificantDigits(); 3214 3215 case UNUM_MULTIPLIER: 3216 return getMultiplier(); 3217 3218 case UNUM_GROUPING_SIZE: 3219 return getGroupingSize(); 3220 3221 case UNUM_ROUNDING_MODE: 3222 return getRoundingMode(); 3223 3224 case UNUM_FORMAT_WIDTH: 3225 return getFormatWidth(); 3226 3227 case UNUM_PADDING_POSITION: 3228 return getPadPosition(); 3229 3230 case UNUM_SECONDARY_GROUPING_SIZE: 3231 return getSecondaryGroupingSize(); 3232 3233 /* These are stored in fBoolFlags */ 3234 case UNUM_PARSE_NO_EXPONENT: 3235 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: 3236 case UNUM_PARSE_DECIMAL_MARK_REQUIRED: 3237 return fBoolFlags.get(attr); 3238 3239 case UNUM_SCALE: 3240 return fImpl->fScale; 3241 3242 case UNUM_CURRENCY_USAGE: 3243 return fImpl->getCurrencyUsage(); 3244 3245 case UNUM_MINIMUM_GROUPING_DIGITS: 3246 return getMinimumGroupingDigits(); 3247 3248 default: 3249 status = U_UNSUPPORTED_ERROR; 3250 break; 3251 } 3252 3253 return -1; /* undefined */ 3254 } 3255 3256 #if UCONFIG_HAVE_PARSEALLINPUT 3257 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { 3258 fParseAllInput = value; 3259 } 3260 #endif 3261 3262 U_NAMESPACE_END 3263 3264 #endif /* #if !UCONFIG_NO_FORMATTING */ 3265 3266 //eof 3267