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