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