2 *******************************************************************************
3 * Copyright (C) 1997-2006, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
9 * Modification History:
11 * Date Name Description
12 * 02/19/97 aliu Converted from java.
13 * 03/20/97 clhuang Implemented with new APIs.
14 * 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it.
15 * 04/3/97 aliu Rewrote parsing and formatting completely, and
16 * cleaned up and debugged. Actually works now.
17 * Implemented NAN and INF handling, for both parsing
18 * and formatting. Extensive testing & debugging.
19 * 04/10/97 aliu Modified to compile on AIX.
20 * 04/16/97 aliu Rewrote to use DigitList, which has been resurrected.
21 * Changed DigitCount to int per code review.
22 * 07/09/97 helena Made ParsePosition into a class.
23 * 08/26/97 aliu Extensive changes to applyPattern; completely
24 * rewritten from the Java.
25 * 09/09/97 aliu Ported over support for exponential formats.
26 * 07/20/98 stephen JDK 1.2 sync up.
27 * Various instances of '0' replaced with 'NULL'
28 * Check for grouping size in subFormat()
29 * Brought subParse() in line with Java 1.2
30 * Added method appendAffix()
31 * 08/24/1998 srl Removed Mutex calls. This is not a thread safe class!
32 * 02/22/99 stephen Removed character literals for EBCDIC safety
33 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
34 * 06/28/99 stephen Fixed bugs in toPattern().
35 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
37 ********************************************************************************
40 #include "unicode/utypes.h"
42 #if !UCONFIG_NO_FORMATTING
44 #include "unicode/decimfmt.h"
45 #include "unicode/choicfmt.h"
46 #include "unicode/ucurr.h"
47 #include "unicode/ustring.h"
48 #include "unicode/dcfmtsym.h"
49 #include "unicode/ures.h"
50 #include "unicode/uchar.h"
51 #include "unicode/curramt.h"
67 static void debugout(UnicodeString s) {
69 s.extract((int32_t) 0, s.length(), buf);
72 #define debug(x) printf("%s", x);
78 // *****************************************************************************
79 // class DecimalFormat
80 // *****************************************************************************
82 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
84 // Constants for characters used in programmatic (unlocalized) patterns.
85 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
86 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
87 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
88 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
89 #define kPatternPerMill ((UChar)0x2030)
90 #define kPatternPercent ((UChar)0x0025) /*'%'*/
91 #define kPatternDigit ((UChar)0x0023) /*'#'*/
92 #define kPatternSeparator ((UChar)0x003B) /*';'*/
93 #define kPatternExponent ((UChar)0x0045) /*'E'*/
94 #define kPatternPlus ((UChar)0x002B) /*'+'*/
95 #define kPatternMinus ((UChar)0x002D) /*'-'*/
96 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
97 #define kQuote ((UChar)0x0027) /*'\''*/
99 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
100 * is used in patterns and substitued with either the currency symbol,
101 * or if it is doubled, with the international currency symbol. If the
102 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
103 * replaced with the monetary decimal separator.
105 #define kCurrencySign ((UChar)0x00A4)
106 #define kDefaultPad ((UChar)0x0020) /* */
108 const int32_t DecimalFormat::kDoubleIntegerDigits = 309;
109 const int32_t DecimalFormat::kDoubleFractionDigits = 340;
111 const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8;
114 * These are the tags we expect to see in normal resource bundle files associated
117 const char DecimalFormat::fgNumberPatterns[]="NumberPatterns";
119 inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
120 inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
122 //------------------------------------------------------------------------------
123 // Constructs a DecimalFormat instance in the default locale.
125 DecimalFormat::DecimalFormat(UErrorCode& status)
127 fPosPrefixPattern(0),
128 fPosSuffixPattern(0),
129 fNegPrefixPattern(0),
130 fNegSuffixPattern(0),
136 fUseSignificantDigits(FALSE),
137 fMinSignificantDigits(1),
138 fMaxSignificantDigits(6),
139 fMinExponentDigits(0),
140 fRoundingIncrement(0),
144 UParseError parseError;
145 construct(status, parseError);
148 //------------------------------------------------------------------------------
149 // Constructs a DecimalFormat instance with the specified number format
150 // pattern in the default locale.
152 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
155 fPosPrefixPattern(0),
156 fPosSuffixPattern(0),
157 fNegPrefixPattern(0),
158 fNegSuffixPattern(0),
164 fUseSignificantDigits(FALSE),
165 fMinSignificantDigits(1),
166 fMaxSignificantDigits(6),
167 fMinExponentDigits(0),
168 fRoundingIncrement(0),
172 UParseError parseError;
173 construct(status, parseError, &pattern);
176 //------------------------------------------------------------------------------
177 // Constructs a DecimalFormat instance with the specified number format
178 // pattern and the number format symbols in the default locale. The
179 // created instance owns the symbols.
181 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
182 DecimalFormatSymbols* symbolsToAdopt,
185 fPosPrefixPattern(0),
186 fPosSuffixPattern(0),
187 fNegPrefixPattern(0),
188 fNegSuffixPattern(0),
194 fUseSignificantDigits(FALSE),
195 fMinSignificantDigits(1),
196 fMaxSignificantDigits(6),
197 fMinExponentDigits(0),
198 fRoundingIncrement(0),
202 UParseError parseError;
203 if (symbolsToAdopt == NULL)
204 status = U_ILLEGAL_ARGUMENT_ERROR;
205 construct(status, parseError, &pattern, symbolsToAdopt);
208 DecimalFormat::DecimalFormat( const UnicodeString& pattern,
209 DecimalFormatSymbols* symbolsToAdopt,
210 UParseError& parseErr,
213 fPosPrefixPattern(0),
214 fPosSuffixPattern(0),
215 fNegPrefixPattern(0),
216 fNegSuffixPattern(0),
222 fUseSignificantDigits(FALSE),
223 fMinSignificantDigits(1),
224 fMaxSignificantDigits(6),
225 fMinExponentDigits(0),
226 fRoundingIncrement(0),
230 if (symbolsToAdopt == NULL)
231 status = U_ILLEGAL_ARGUMENT_ERROR;
232 construct(status,parseErr, &pattern, symbolsToAdopt);
234 //------------------------------------------------------------------------------
235 // Constructs a DecimalFormat instance with the specified number format
236 // pattern and the number format symbols in the default locale. The
237 // created instance owns the clone of the symbols.
239 DecimalFormat::DecimalFormat(const UnicodeString& pattern,
240 const DecimalFormatSymbols& symbols,
243 fPosPrefixPattern(0),
244 fPosSuffixPattern(0),
245 fNegPrefixPattern(0),
246 fNegSuffixPattern(0),
252 fUseSignificantDigits(FALSE),
253 fMinSignificantDigits(1),
254 fMaxSignificantDigits(6),
255 fMinExponentDigits(0),
256 fRoundingIncrement(0),
260 UParseError parseError;
261 construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
264 //------------------------------------------------------------------------------
265 // Constructs a DecimalFormat instance with the specified number format
266 // pattern and the number format symbols in the desired locale. The
267 // created instance owns the symbols.
270 DecimalFormat::construct(UErrorCode& status,
271 UParseError& parseErr,
272 const UnicodeString* pattern,
273 DecimalFormatSymbols* symbolsToAdopt)
275 fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!!
276 // fDigitList = new DigitList(); // Do this BEFORE aborting on status failure!!!
277 fRoundingIncrement = NULL;
278 fRoundingDouble = 0.0;
279 fRoundingMode = kRoundHalfEven;
280 fPad = kPatternPadEscape;
281 fPadPosition = kPadBeforePrefix;
282 if (U_FAILURE(status))
285 fPosPrefixPattern = fPosSuffixPattern = NULL;
286 fNegPrefixPattern = fNegSuffixPattern = NULL;
290 fDecimalSeparatorAlwaysShown = FALSE;
291 fIsCurrencyFormat = FALSE;
292 fUseExponentialNotation = FALSE;
293 fMinExponentDigits = 0;
295 if (fSymbols == NULL)
297 fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
300 status = U_MEMORY_ALLOCATION_ERROR;
306 // Uses the default locale's number format pattern if there isn't
311 UResourceBundle *resource = ures_open(NULL, Locale::getDefault().getName(), &status);
313 resource = ures_getByKey(resource, fgNumberPatterns, resource, &status);
314 const UChar *resStr = ures_getStringByIndex(resource, (int32_t)0, &len, &status);
315 str.setTo(TRUE, resStr, len);
317 ures_close(resource);
320 if (U_FAILURE(status))
325 if (pattern->indexOf((UChar)kCurrencySign) >= 0) {
326 // If it looks like we are going to use a currency pattern
327 // then do the time consuming lookup.
328 if (symbolsToAdopt == NULL) {
329 setCurrencyForLocale(uloc_getDefault(), status);
331 setCurrencyForSymbols();
334 setCurrency(NULL, status);
337 applyPattern(*pattern, FALSE /*not localized*/,parseErr, status);
339 // If it was a currency format, apply the appropriate rounding by
340 // resetting the currency. NOTE: this copies fCurrency on top of itself.
341 if (fIsCurrencyFormat) {
342 setCurrency(getCurrency(), status);
347 * Sets our currency to be the default currency for the given locale.
349 void DecimalFormat::setCurrencyForLocale(const char* locale, UErrorCode& ec) {
350 const UChar* c = NULL;
352 // Trap an error in mapping locale to currency. If we can't
353 // map, then don't fail and set the currency to "".
354 UErrorCode ec2 = U_ZERO_ERROR;
356 ucurr_forLocale(locale, c, 4, &ec2);
361 //------------------------------------------------------------------------------
363 DecimalFormat::~DecimalFormat()
365 // delete fDigitList;
366 delete fPosPrefixPattern;
367 delete fPosSuffixPattern;
368 delete fNegPrefixPattern;
369 delete fNegSuffixPattern;
370 delete fCurrencyChoice;
372 delete fRoundingIncrement;
375 //------------------------------------------------------------------------------
378 DecimalFormat::DecimalFormat(const DecimalFormat &source)
379 : NumberFormat(source),
381 fPosPrefixPattern(NULL),
382 fPosSuffixPattern(NULL),
383 fNegPrefixPattern(NULL),
384 fNegSuffixPattern(NULL),
385 fCurrencyChoice(NULL),
387 fRoundingIncrement(NULL)
392 //------------------------------------------------------------------------------
393 // assignment operator
394 // Note that fDigitList is not considered a significant part of the
395 // DecimalFormat because it's used as a buffer to process the numbers.
397 static void _copy_us_ptr(UnicodeString** pdest, const UnicodeString* source) {
398 if (source == NULL) {
401 } else if (*pdest == NULL) {
402 *pdest = new UnicodeString(*source);
409 DecimalFormat::operator=(const DecimalFormat& rhs)
412 NumberFormat::operator=(rhs);
413 fPositivePrefix = rhs.fPositivePrefix;
414 fPositiveSuffix = rhs.fPositiveSuffix;
415 fNegativePrefix = rhs.fNegativePrefix;
416 fNegativeSuffix = rhs.fNegativeSuffix;
417 _copy_us_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern);
418 _copy_us_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern);
419 _copy_us_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern);
420 _copy_us_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern);
421 if (rhs.fCurrencyChoice == 0) {
422 delete fCurrencyChoice;
425 fCurrencyChoice = (ChoiceFormat*) rhs.fCurrencyChoice->clone();
427 if(rhs.fRoundingIncrement == NULL) {
428 delete fRoundingIncrement;
429 fRoundingIncrement = NULL;
431 else if(fRoundingIncrement == NULL) {
432 fRoundingIncrement = new DigitList(*rhs.fRoundingIncrement);
435 *fRoundingIncrement = *rhs.fRoundingIncrement;
437 fRoundingDouble = rhs.fRoundingDouble;
438 fMultiplier = rhs.fMultiplier;
439 fGroupingSize = rhs.fGroupingSize;
440 fGroupingSize2 = rhs.fGroupingSize2;
441 fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown;
442 if(fSymbols == NULL) {
443 fSymbols = new DecimalFormatSymbols(*rhs.fSymbols);
445 *fSymbols = *rhs.fSymbols;
447 fUseExponentialNotation = rhs.fUseExponentialNotation;
448 fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown;
449 /*Bertrand A. D. Update 98.03.17*/
450 fIsCurrencyFormat = rhs.fIsCurrencyFormat;
452 fMinExponentDigits = rhs.fMinExponentDigits;
453 // if (fDigitList == NULL)
454 // fDigitList = new DigitList();
457 fFormatWidth = rhs.fFormatWidth;
459 fPadPosition = rhs.fPadPosition;
461 fMinSignificantDigits = rhs.fMinSignificantDigits;
462 fMaxSignificantDigits = rhs.fMaxSignificantDigits;
463 fUseSignificantDigits = rhs.fUseSignificantDigits;
468 //------------------------------------------------------------------------------
471 DecimalFormat::operator==(const Format& that) const
476 // NumberFormat::operator== guarantees this cast is safe
477 const DecimalFormat* other = (DecimalFormat*)&that;
480 // This code makes it easy to determine why two format objects that should
483 if (!NumberFormat::operator==(that)) {
484 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
485 debug("NumberFormat::!=");
487 if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null
488 fPositivePrefix == other->fPositivePrefix)
489 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
490 *fPosPrefixPattern == *other->fPosPrefixPattern))) {
491 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
492 debug("Pos Prefix !=");
494 if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null
495 fPositiveSuffix == other->fPositiveSuffix)
496 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
497 *fPosSuffixPattern == *other->fPosSuffixPattern))) {
498 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
499 debug("Pos Suffix !=");
501 if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null
502 fNegativePrefix == other->fNegativePrefix)
503 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
504 *fNegPrefixPattern == *other->fNegPrefixPattern))) {
505 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
506 debug("Neg Prefix ");
507 if (fNegPrefixPattern == NULL) {
509 debugout(fNegativePrefix);
512 debugout(*fNegPrefixPattern);
515 if (other->fNegPrefixPattern == NULL) {
517 debugout(other->fNegativePrefix);
520 debugout(*other->fNegPrefixPattern);
523 if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null
524 fNegativeSuffix == other->fNegativeSuffix)
525 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
526 *fNegSuffixPattern == *other->fNegSuffixPattern))) {
527 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
528 debug("Neg Suffix ");
529 if (fNegSuffixPattern == NULL) {
531 debugout(fNegativeSuffix);
534 debugout(*fNegSuffixPattern);
537 if (other->fNegSuffixPattern == NULL) {
539 debugout(other->fNegativeSuffix);
542 debugout(*other->fNegSuffixPattern);
545 if (!((fRoundingIncrement == other->fRoundingIncrement) // both null
546 || (fRoundingIncrement != NULL &&
547 other->fRoundingIncrement != NULL &&
548 *fRoundingIncrement == *other->fRoundingIncrement))) {
549 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
550 debug("Rounding Increment !=");
552 if (fMultiplier != other->fMultiplier) {
553 if (first) { printf("[ "); first = FALSE; }
554 printf("Multiplier %ld != %ld", fMultiplier, other->fMultiplier);
556 if (fGroupingSize != other->fGroupingSize) {
557 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
558 printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize);
560 if (fGroupingSize2 != other->fGroupingSize2) {
561 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
562 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGroupingSize2);
564 if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) {
565 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
566 printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown);
568 if (fUseExponentialNotation != other->fUseExponentialNotation) {
569 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
572 if (!(!fUseExponentialNotation ||
573 fMinExponentDigits != other->fMinExponentDigits)) {
574 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
575 debug("Exp Digits !=");
577 if (*fSymbols != *(other->fSymbols)) {
578 if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
581 // TODO Add debug stuff for significant digits here
582 if (!first) { printf(" ]"); }
585 return (NumberFormat::operator==(that) &&
586 ((fPosPrefixPattern == other->fPosPrefixPattern && // both null
587 fPositivePrefix == other->fPositivePrefix)
588 || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
589 *fPosPrefixPattern == *other->fPosPrefixPattern)) &&
590 ((fPosSuffixPattern == other->fPosSuffixPattern && // both null
591 fPositiveSuffix == other->fPositiveSuffix)
592 || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
593 *fPosSuffixPattern == *other->fPosSuffixPattern)) &&
594 ((fNegPrefixPattern == other->fNegPrefixPattern && // both null
595 fNegativePrefix == other->fNegativePrefix)
596 || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
597 *fNegPrefixPattern == *other->fNegPrefixPattern)) &&
598 ((fNegSuffixPattern == other->fNegSuffixPattern && // both null
599 fNegativeSuffix == other->fNegativeSuffix)
600 || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
601 *fNegSuffixPattern == *other->fNegSuffixPattern)) &&
602 ((fCurrencyChoice == other->fCurrencyChoice) // both null
603 || (fCurrencyChoice != NULL &&
604 other->fCurrencyChoice != NULL &&
605 *fCurrencyChoice == *other->fCurrencyChoice)) &&
606 ((fRoundingIncrement == other->fRoundingIncrement) // both null
607 || (fRoundingIncrement != NULL &&
608 other->fRoundingIncrement != NULL &&
609 *fRoundingIncrement == *other->fRoundingIncrement)) &&
610 fRoundingDouble == other->fRoundingDouble &&
611 fMultiplier == other->fMultiplier &&
612 fGroupingSize == other->fGroupingSize &&
613 fGroupingSize2 == other->fGroupingSize2 &&
614 fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown &&
615 fUseExponentialNotation == other->fUseExponentialNotation &&
616 (!fUseExponentialNotation ||
617 (fExponentSignAlwaysShown == other->fExponentSignAlwaysShown &&
618 fMinExponentDigits == other->fMinExponentDigits)) &&
619 *fSymbols == *(other->fSymbols) &&
620 fIsCurrencyFormat == other->fIsCurrencyFormat &&
621 fFormatWidth == other->fFormatWidth &&
622 fPad == other->fPad &&
623 fPadPosition == other->fPadPosition &&
624 fUseSignificantDigits == other->fUseSignificantDigits &&
625 (!fUseSignificantDigits ||
626 (fMinSignificantDigits == other->fMinSignificantDigits &&
627 fMaxSignificantDigits == other->fMaxSignificantDigits)));
630 //------------------------------------------------------------------------------
633 DecimalFormat::clone() const
635 return new DecimalFormat(*this);
638 //------------------------------------------------------------------------------
641 DecimalFormat::format(int32_t number,
642 UnicodeString& appendTo,
643 FieldPosition& fieldPosition) const
645 return format((int64_t)number, appendTo, fieldPosition);
648 //------------------------------------------------------------------------------
651 DecimalFormat::format(int64_t number,
652 UnicodeString& appendTo,
653 FieldPosition& fieldPosition) const
657 // Clears field positions.
658 fieldPosition.setBeginIndex(0);
659 fieldPosition.setEndIndex(0);
661 // If we are to do rounding, we need to move into the BigDecimal
662 // domain in order to do divide/multiply correctly.
664 // In general, long values always represent real finite numbers, so
665 // we don't have to check for +/- Infinity or NaN. However, there
666 // is one case we have to be careful of: The multiplier can push
667 // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
668 // check for this before multiplying, and if it happens we use doubles
669 // instead, trading off accuracy for range.
670 if (fRoundingIncrement != NULL
671 || (fMultiplier != 0 && (number > (U_INT64_MAX / fMultiplier)
672 || number < (U_INT64_MIN / fMultiplier))))
674 digits.set(((double)number) * fMultiplier,
676 !fUseExponentialNotation && !areSignificantDigitsUsed());
680 digits.set(number * fMultiplier, precision(TRUE));
683 return subformat(appendTo, fieldPosition, digits, TRUE);
686 //------------------------------------------------------------------------------
689 DecimalFormat::format( double number,
690 UnicodeString& appendTo,
691 FieldPosition& fieldPosition) const
693 // Clears field positions.
694 fieldPosition.setBeginIndex(0);
695 fieldPosition.setEndIndex(0);
697 // Special case for NaN, sets the begin and end index to be the
698 // the string length of localized name of NaN.
699 if (uprv_isNaN(number))
701 if (fieldPosition.getField() == NumberFormat::kIntegerField)
702 fieldPosition.setBeginIndex(appendTo.length());
704 appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
706 if (fieldPosition.getField() == NumberFormat::kIntegerField)
707 fieldPosition.setEndIndex(appendTo.length());
709 addPadding(appendTo, fieldPosition, 0, 0);
713 /* Detecting whether a double is negative is easy with the exception of
714 * the value -0.0. This is a double which has a zero mantissa (and
715 * exponent), but a negative sign bit. It is semantically distinct from
716 * a zero with a positive sign bit, and this distinction is important
717 * to certain kinds of computations. However, it's a little tricky to
718 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
719 * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
720 * -Infinity. Proper detection of -0.0 is needed to deal with the
721 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
723 UBool isNegative = uprv_isNegative(number);
725 // Do this BEFORE checking to see if value is infinite! Sets the
726 // begin and end index to be length of the string composed of
727 // localized name of Infinite and the positive/negative localized
730 number *= fMultiplier;
732 // Apply rounding after multiplier
733 if (fRoundingIncrement != NULL) {
734 if (isNegative) // For rounding in the correct direction
736 number = fRoundingDouble
737 * round(number / fRoundingDouble, fRoundingMode, isNegative);
742 // Special case for INFINITE,
743 if (uprv_isInfinite(number))
745 int32_t prefixLen = appendAffix(appendTo, number, isNegative, TRUE);
747 if (fieldPosition.getField() == NumberFormat::kIntegerField)
748 fieldPosition.setBeginIndex(appendTo.length());
750 appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
752 if (fieldPosition.getField() == NumberFormat::kIntegerField)
753 fieldPosition.setEndIndex(appendTo.length());
755 int32_t suffixLen = appendAffix(appendTo, number, isNegative, FALSE);
757 addPadding(appendTo, fieldPosition, prefixLen, suffixLen);
763 // This detects negativity too.
764 digits.set(number, precision(FALSE),
765 !fUseExponentialNotation && !areSignificantDigitsUsed());
767 return subformat(appendTo, fieldPosition, digits, FALSE);
771 * Round a double value to the nearest integer according to the
773 * @param a the absolute value of the number to be rounded
774 * @param mode a BigDecimal rounding mode
775 * @param isNegative true if the number to be rounded is negative
776 * @return the absolute value of the rounded result
778 double DecimalFormat::round(double a, ERoundingMode mode, UBool isNegative) {
781 return isNegative ? uprv_floor(a) : uprv_ceil(a);
783 return isNegative ? uprv_ceil(a) : uprv_floor(a);
785 return uprv_floor(a);
790 double f = uprv_floor(a);
791 if ((a - f) != 0.5) {
792 return uprv_floor(a + 0.5);
795 return (g == uprv_floor(g)) ? f : (f + 1.0);
798 return ((a - uprv_floor(a)) <= 0.5) ? uprv_floor(a) : uprv_ceil(a);
800 return ((a - uprv_floor(a)) < 0.5) ? uprv_floor(a) : uprv_ceil(a);
806 DecimalFormat::format( const Formattable& obj,
807 UnicodeString& appendTo,
808 FieldPosition& fieldPosition,
809 UErrorCode& status) const
811 return NumberFormat::format(obj, appendTo, fieldPosition, status);
815 * Return true if a grouping separator belongs at the given
816 * position, based on whether grouping is in use and the values of
817 * the primary and secondary grouping interval.
818 * @param pos the number of integer digits to the right of
819 * the current position. Zero indicates the position after the
820 * rightmost integer digit.
821 * @return true if a grouping character belongs at the current
824 UBool DecimalFormat::isGroupingPosition(int32_t pos) const {
825 UBool result = FALSE;
826 if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) {
827 if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) {
828 result = ((pos - fGroupingSize) % fGroupingSize2) == 0;
830 result = pos % fGroupingSize == 0;
836 //------------------------------------------------------------------------------
839 * Complete the formatting of a finite number. On entry, the fDigitList must
840 * be filled in with the correct digits.
843 DecimalFormat::subformat(UnicodeString& appendTo,
844 FieldPosition& fieldPosition,
846 UBool isInteger) const
848 // Gets the localized zero Unicode character.
849 UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
850 int32_t zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
851 const UnicodeString *grouping ;
852 if(fIsCurrencyFormat) {
853 grouping = &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
855 grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
857 const UnicodeString *decimal;
858 if(fIsCurrencyFormat) {
859 decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
861 decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
863 UBool useSigDig = areSignificantDigitsUsed();
864 int32_t maxIntDig = getMaximumIntegerDigits();
865 int32_t minIntDig = getMinimumIntegerDigits();
867 /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
868 * format as zero. This allows sensible computations and preserves
869 * relations such as signum(1/x) = signum(x), where x is +Infinity or
870 * -Infinity. Prior to this fix, we always formatted zero values as if
871 * they were positive. Liu 7/6/98.
875 digits.fDecimalAt = digits.fCount = 0; // Normalize
878 // Appends the prefix.
879 double doubleValue = digits.getDouble();
880 int32_t prefixLen = appendAffix(appendTo, doubleValue, !digits.fIsPositive, TRUE);
882 if (fUseExponentialNotation)
884 // Record field information for caller.
885 if (fieldPosition.getField() == NumberFormat::kIntegerField)
887 fieldPosition.setBeginIndex(appendTo.length());
888 fieldPosition.setEndIndex(-1);
890 else if (fieldPosition.getField() == NumberFormat::kFractionField)
892 fieldPosition.setBeginIndex(-1);
895 int32_t minFracDig = 0;
897 maxIntDig = minIntDig = 1;
898 minFracDig = getMinimumSignificantDigits() - 1;
900 minFracDig = getMinimumFractionDigits();
901 if (maxIntDig > kMaxScientificIntegerDigits) {
903 if (maxIntDig < minIntDig) {
904 maxIntDig = minIntDig;
907 if (maxIntDig > minIntDig) {
912 // Minimum integer digits are handled in exponential format by
913 // adjusting the exponent. For example, 0.01234 with 3 minimum
914 // integer digits is "123.4E-4".
916 // Maximum integer digits are interpreted as indicating the
917 // repeating range. This is useful for engineering notation, in
918 // which the exponent is restricted to a multiple of 3. For
919 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
920 // If maximum integer digits are defined and are larger than
921 // minimum integer digits, then minimum integer digits are
923 int32_t exponent = digits.fDecimalAt;
924 if (maxIntDig > 1 && maxIntDig != minIntDig) {
925 // A exponent increment is defined; adjust to it.
926 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
927 : (exponent / maxIntDig) - 1;
928 exponent *= maxIntDig;
930 // No exponent increment is defined; use minimum integer digits.
931 // If none is specified, as in "#E0", generate 1 integer digit.
932 exponent -= (minIntDig > 0 || minFracDig > 0)
936 // We now output a minimum number of digits, and more if there
937 // are more digits, up to the maximum number of digits. We
938 // place the decimal point after the "integer" digits, which
939 // are the first (decimalAt - exponent) digits.
940 int32_t minimumDigits = minIntDig + minFracDig;
941 // The number of integer digits is handled specially if the number
942 // is zero, since then there may be no digits.
943 int32_t integerDigits = digits.isZero() ? minIntDig :
944 digits.fDecimalAt - exponent;
945 int32_t totalDigits = digits.fCount;
946 if (minimumDigits > totalDigits)
947 totalDigits = minimumDigits;
948 if (integerDigits > totalDigits)
949 totalDigits = integerDigits;
951 // totalDigits records total number of digits needs to be processed
953 for (i=0; i<totalDigits; ++i)
955 if (i == integerDigits)
957 // Record field information for caller.
958 if (fieldPosition.getField() == NumberFormat::kIntegerField)
959 fieldPosition.setEndIndex(appendTo.length());
961 appendTo += *decimal;
963 // Record field information for caller.
964 if (fieldPosition.getField() == NumberFormat::kFractionField)
965 fieldPosition.setBeginIndex(appendTo.length());
967 // Restores the digit character or pads the buffer with zeros.
968 UChar32 c = (UChar32)((i < digits.fCount) ?
969 (digits.fDigits[i] + zeroDelta) :
974 // Record field information
975 if (fieldPosition.getField() == NumberFormat::kIntegerField)
977 if (fieldPosition.getEndIndex() < 0)
978 fieldPosition.setEndIndex(appendTo.length());
980 else if (fieldPosition.getField() == NumberFormat::kFractionField)
982 if (fieldPosition.getBeginIndex() < 0)
983 fieldPosition.setBeginIndex(appendTo.length());
984 fieldPosition.setEndIndex(appendTo.length());
987 // The exponent is output using the pattern-specified minimum
988 // exponent digits. There is no maximum limit to the exponent
989 // digits, since truncating the exponent would appendTo in an
990 // unacceptable inaccuracy.
991 appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
993 // For zero values, we force the exponent to zero. We
994 // must do this here, and not earlier, because the value
995 // is used to determine integer digit count above.
1000 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1001 } else if (fExponentSignAlwaysShown) {
1002 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1005 DigitList expDigits;
1006 expDigits.set(exponent);
1008 int expDig = fMinExponentDigits;
1009 if (fUseExponentialNotation && expDig < 1) {
1012 for (i=expDigits.fDecimalAt; i<expDig; ++i)
1015 for (i=0; i<expDigits.fDecimalAt; ++i)
1017 UChar32 c = (UChar32)((i < expDigits.fCount) ?
1018 (expDigits.fDigits[i] + zeroDelta) : zero);
1022 else // Not using exponential notation
1024 // Record field information for caller.
1025 if (fieldPosition.getField() == NumberFormat::kIntegerField)
1026 fieldPosition.setBeginIndex(appendTo.length());
1028 int32_t sigCount = 0;
1029 int32_t minSigDig = getMinimumSignificantDigits();
1030 int32_t maxSigDig = getMaximumSignificantDigits();
1033 maxSigDig = INT32_MAX;
1036 // Output the integer portion. Here 'count' is the total
1037 // number of integer digits we will display, including both
1038 // leading zeros required to satisfy getMinimumIntegerDigits,
1039 // and actual digits present in the number.
1040 int32_t count = useSigDig ?
1041 _max(1, digits.fDecimalAt) : minIntDig;
1042 if (digits.fDecimalAt > 0 && count < digits.fDecimalAt) {
1043 count = digits.fDecimalAt;
1046 // Handle the case where getMaximumIntegerDigits() is smaller
1047 // than the real number of integer digits. If this is so, we
1048 // output the least significant max integer digits. For example,
1049 // the value 1997 printed with 2 max integer digits is just "97".
1051 int32_t digitIndex = 0; // Index into digitList.fDigits[]
1052 if (count > maxIntDig && maxIntDig >= 0) {
1054 digitIndex = digits.fDecimalAt - count;
1057 int32_t sizeBeforeIntegerPart = appendTo.length();
1060 for (i=count-1; i>=0; --i)
1062 if (i < digits.fDecimalAt && digitIndex < digits.fCount &&
1063 sigCount < maxSigDig) {
1064 // Output a real digit
1065 appendTo += ((UChar32)(digits.fDigits[digitIndex++] + zeroDelta));
1070 // Output a zero (leading or trailing)
1077 // Output grouping separator if necessary.
1078 if (isGroupingPosition(i)) {
1079 appendTo.append(*grouping);
1083 // Record field information for caller.
1084 if (fieldPosition.getField() == NumberFormat::kIntegerField)
1085 fieldPosition.setEndIndex(appendTo.length());
1087 // Determine whether or not there are any printable fractional
1088 // digits. If we've used up the digits we know there aren't.
1089 UBool fractionPresent = (!isInteger && digitIndex < digits.fCount) ||
1090 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
1092 // If there is no fraction present, and we haven't printed any
1093 // integer digits, then print a zero. Otherwise we won't print
1094 // _any_ digits, and we won't be able to parse this string.
1095 if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart)
1098 // Output the decimal separator if we always do so.
1099 if (fDecimalSeparatorAlwaysShown || fractionPresent)
1100 appendTo += *decimal;
1102 // Record field information for caller.
1103 if (fieldPosition.getField() == NumberFormat::kFractionField)
1104 fieldPosition.setBeginIndex(appendTo.length());
1106 count = useSigDig ? INT32_MAX : getMaximumFractionDigits();
1107 if (useSigDig && (sigCount == maxSigDig ||
1108 (sigCount >= minSigDig && digitIndex == digits.fCount))) {
1112 for (i=0; i < count; ++i) {
1113 // Here is where we escape from the loop. We escape
1114 // if we've output the maximum fraction digits
1115 // (specified in the for expression above). We also
1116 // stop when we've output the minimum digits and
1117 // either: we have an integer, so there is no
1118 // fractional stuff to display, or we're out of
1119 // significant digits.
1120 if (!useSigDig && i >= getMinimumFractionDigits() &&
1121 (isInteger || digitIndex >= digits.fCount)) {
1125 // Output leading fractional zeros. These are zeros
1126 // that come after the decimal but before any
1127 // significant digits. These are only output if
1128 // abs(number being formatted) < 1.0.
1129 if (-1-i > (digits.fDecimalAt-1)) {
1134 // Output a digit, if we have any precision left, or a
1135 // zero if we don't. We don't want to output noise digits.
1136 if (!isInteger && digitIndex < digits.fCount) {
1137 appendTo += ((UChar32)(digits.fDigits[digitIndex++] + zeroDelta));
1142 // If we reach the maximum number of significant
1143 // digits, or if we output all the real digits and
1144 // reach the minimum, then we are done.
1147 (sigCount == maxSigDig ||
1148 (digitIndex == digits.fCount && sigCount >= minSigDig))) {
1153 // Record field information for caller.
1154 if (fieldPosition.getField() == NumberFormat::kFractionField)
1155 fieldPosition.setEndIndex(appendTo.length());
1158 int32_t suffixLen = appendAffix(appendTo, doubleValue, !digits.fIsPositive, FALSE);
1160 addPadding(appendTo, fieldPosition, prefixLen, suffixLen);
1165 * Inserts the character fPad as needed to expand result to fFormatWidth.
1166 * @param result the string to be padded
1168 void DecimalFormat::addPadding(UnicodeString& appendTo,
1169 FieldPosition& fieldPosition,
1171 int32_t suffixLen) const
1173 if (fFormatWidth > 0) {
1174 int32_t len = fFormatWidth - appendTo.length();
1176 UnicodeString padding;
1177 for (int32_t i=0; i<len; ++i) {
1180 switch (fPadPosition) {
1181 case kPadAfterPrefix:
1182 appendTo.insert(prefixLen, padding);
1184 case kPadBeforePrefix:
1185 appendTo.insert(0, padding);
1187 case kPadBeforeSuffix:
1188 appendTo.insert(appendTo.length() - suffixLen, padding);
1190 case kPadAfterSuffix:
1191 appendTo += padding;
1194 if (fPadPosition == kPadBeforePrefix ||
1195 fPadPosition == kPadAfterPrefix) {
1196 fieldPosition.setBeginIndex(len + fieldPosition.getBeginIndex());
1197 fieldPosition.setEndIndex(len + fieldPosition.getEndIndex());
1203 //------------------------------------------------------------------------------
1206 DecimalFormat::parse(const UnicodeString& text,
1207 Formattable& result,
1208 UErrorCode& status) const
1210 NumberFormat::parse(text, result, status);
1214 DecimalFormat::parse(const UnicodeString& text,
1215 Formattable& result,
1216 ParsePosition& parsePosition) const {
1217 parse(text, result, parsePosition, FALSE);
1220 Formattable& DecimalFormat::parseCurrency(const UnicodeString& text,
1221 Formattable& result,
1222 ParsePosition& pos) const {
1223 parse(text, result, pos, TRUE);
1228 * Parses the given text as either a number or a currency amount.
1229 * @param text the string to parse
1230 * @param result output parameter for the result
1231 * @param parsePosition input-output position; on input, the
1232 * position within text to match; must have 0 <= pos.getIndex() <
1233 * text.length(); on output, the position after the last matched
1234 * character. If the parse fails, the position in unchanged upon
1236 * @param parseCurrency if true, a currency amount is parsed;
1237 * otherwise a Number is parsed
1239 void DecimalFormat::parse(const UnicodeString& text,
1240 Formattable& result,
1241 ParsePosition& parsePosition,
1242 UBool parseCurrency) const {
1244 int32_t i = backup = parsePosition.getIndex();
1246 // Handle NaN as a special case:
1248 // Skip padding characters, if around prefix
1249 if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix ||
1250 fPadPosition == kPadAfterPrefix)) {
1251 i = skipPadding(text, i);
1253 // If the text is composed of the representation of NaN, returns NaN.length
1254 const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1255 int32_t nanLen = (text.compare(i, nan->length(), *nan)
1256 ? 0 : nan->length());
1259 if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix ||
1260 fPadPosition == kPadAfterSuffix)) {
1261 i = skipPadding(text, i);
1263 parsePosition.setIndex(i);
1264 result.setDouble(uprv_getNaN());
1268 // NaN parse failed; start over
1271 // status is used to record whether a number is infinite.
1272 UBool status[fgStatusLength];
1274 UChar* currency = parseCurrency ? curbuf : NULL;
1277 if (!subparse(text, parsePosition, digits, status, currency)) {
1278 parsePosition.setIndex(backup);
1283 if (status[fgStatusInfinite]) {
1284 double inf = uprv_getInfinity();
1285 result.setDouble(digits.fIsPositive ? inf : -inf);
1289 // Do as much of the multiplier conversion as possible without
1291 int32_t mult = fMultiplier; // Don't modify this.multiplier
1292 while (mult % 10 == 0) {
1294 --digits.fDecimalAt;
1297 // Handle integral values. We want to return the most
1298 // parsimonious type that will accommodate all of the result's
1299 // precision. We therefore only return a long if the result fits
1300 // entirely within a long (taking into account the multiplier) --
1301 // otherwise we fall through and return a double. When more
1302 // numeric types are supported by Formattable (e.g., 64-bit
1303 // integers, bignums) we will extend this logic to include them.
1304 if (digits.fitsIntoLong(isParseIntegerOnly())) {
1305 int32_t n = digits.getLong();
1306 if (n % mult == 0) {
1307 result.setLong(n / mult);
1309 else { // else handle the remainder
1310 result.setDouble(((double)n) / mult);
1313 else if (digits.fitsIntoInt64(isParseIntegerOnly())) {
1314 int64_t n = digits.getInt64();
1315 if (n % mult == 0) {
1316 result.setInt64(n / mult);
1318 else { // else handle the remainder
1319 result.setDouble(((double)n) / mult);
1323 // Handle non-integral or very large values
1324 // Dividing by one is okay and not that costly.
1325 result.setDouble(digits.getDouble() / mult);
1329 if (parseCurrency) {
1330 UErrorCode ec = U_ZERO_ERROR;
1331 Formattable n(result);
1332 result.adoptObject(new CurrencyAmount(n, curbuf, ec));
1333 U_ASSERT(U_SUCCESS(ec)); // should always succeed
1339 This is an old implimentation that was preparing for 64-bit numbers in ICU.
1340 It is very slow, and 64-bit numbers are not ANSI-C compatible. This code
1341 is here if we change our minds.
1343 ^^^ what is this referring to? remove? ^^^ [alan]
1347 * Parse the given text into a number. The text is parsed beginning at
1348 * parsePosition, until an unparseable character is seen.
1349 * @param text the string to parse.
1350 * @param parsePosition The position at which to being parsing. Upon
1351 * return, the first unparsed character.
1352 * @param digits the DigitList to set to the parsed value.
1353 * @param status output param containing boolean status flags indicating
1354 * whether the value was infinite and whether it was positive.
1355 * @param currency return value for parsed currency, for generic
1356 * currency parsing mode, or NULL for normal parsing. In generic
1357 * currency parsing mode, any currency is parsed, not just the
1358 * currency that this formatter is set to.
1360 UBool DecimalFormat::subparse(const UnicodeString& text, ParsePosition& parsePosition,
1361 DigitList& digits, UBool* status,
1362 UChar* currency) const
1364 int32_t position = parsePosition.getIndex();
1365 int32_t oldStart = position;
1367 // Match padding before prefix
1368 if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) {
1369 position = skipPadding(text, position);
1372 // Match positive and negative prefixes; prefer longest match.
1373 int32_t posMatch = compareAffix(text, position, FALSE, TRUE, currency);
1374 int32_t negMatch = compareAffix(text, position, TRUE, TRUE, currency);
1375 if (posMatch >= 0 && negMatch >= 0) {
1376 if (posMatch > negMatch) {
1378 } else if (negMatch > posMatch) {
1382 if (posMatch >= 0) {
1383 position += posMatch;
1384 } else if (negMatch >= 0) {
1385 position += negMatch;
1387 parsePosition.setErrorIndex(position);
1391 // Match padding before prefix
1392 if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) {
1393 position = skipPadding(text, position);
1396 // process digits or Inf, find decimal position
1397 const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
1398 int32_t infLen = (text.compare(position, inf->length(), *inf)
1399 ? 0 : inf->length());
1400 position += infLen; // infLen is non-zero when it does equal to infinity
1401 status[fgStatusInfinite] = (UBool)infLen;
1404 // We now have a string of digits, possibly with grouping symbols,
1405 // and decimal points. We want to process these into a DigitList.
1406 // We don't want to put a bunch of leading zeros into the DigitList
1407 // though, so we keep track of the location of the decimal point,
1408 // put only significant digits into the DigitList, and adjust the
1409 // exponent as needed.
1411 digits.fDecimalAt = digits.fCount = 0;
1412 UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
1414 const UnicodeString *decimal;
1415 if(fIsCurrencyFormat) {
1416 decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
1418 decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
1420 const UnicodeString *grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
1421 UBool sawDecimal = FALSE;
1422 UBool sawDigit = FALSE;
1423 int32_t backup = -1;
1425 int32_t textLength = text.length(); // One less pointer to follow
1426 int32_t groupingLen = grouping->length();
1427 int32_t decimalLen = decimal->length();
1429 // We have to track digitCount ourselves, because digits.fCount will
1430 // pin when the maximum allowable digits is reached.
1431 int32_t digitCount = 0;
1433 for (; position < textLength; )
1435 UChar32 ch = text.char32At(position);
1437 /* We recognize all digit ranges, not only the Latin digit range
1438 * '0'..'9'. We do so by using the Character.digit() method,
1439 * which converts a valid Unicode digit to the range 0..9.
1441 * The character 'ch' may be a digit. If so, place its value
1442 * from 0 to 9 in 'digit'. First try using the locale digit,
1443 * which may or MAY NOT be a standard Unicode digit range. If
1444 * this fails, try using the standard Unicode digit ranges by
1445 * calling Character.digit(). If this also fails, digit will
1446 * have a value outside the range 0..9.
1449 if (digit < 0 || digit > 9)
1451 digit = u_charDigitValue(ch);
1454 if (digit > 0 && digit <= 9)
1456 // Cancel out backup setting (see grouping handler below)
1460 // output a regular non-zero digit.
1462 digits.append((char)(digit + '0'));
1463 position += U16_LENGTH(ch);
1465 else if (digit == 0)
1467 // Cancel out backup setting (see grouping handler below)
1471 // Check for leading zeros
1472 if (digits.fCount != 0)
1474 // output a regular zero digit.
1476 digits.append((char)(digit + '0'));
1478 else if (sawDecimal)
1480 // If we have seen the decimal, but no significant digits yet,
1481 // then we account for leading zeros by decrementing the
1482 // digits.fDecimalAt into negative values.
1483 --digits.fDecimalAt;
1485 // else ignore leading zeros in integer part of number.
1486 position += U16_LENGTH(ch);
1488 else if (!text.compare(position, groupingLen, *grouping) && isGroupingUsed())
1490 // Ignore grouping characters, if we are using them, but require
1491 // that they be followed by a digit. Otherwise we backup and
1494 position += groupingLen;
1496 else if (!text.compare(position, decimalLen, *decimal) && !isParseIntegerOnly() && !sawDecimal)
1498 // If we're only parsing integers, or if we ALREADY saw the
1499 // decimal, then don't parse this one.
1501 digits.fDecimalAt = digitCount; // Not digits.fCount!
1503 position += decimalLen;
1506 const UnicodeString *tmp;
1507 tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
1508 if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit
1510 // Parse sign, if present
1511 int32_t pos = position + tmp->length();
1512 DigitList exponentDigits;
1514 if (pos < textLength)
1516 tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1517 if (!text.compare(pos, tmp->length(), *tmp))
1519 pos += tmp->length();
1522 tmp = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1523 if (!text.compare(pos, tmp->length(), *tmp))
1525 pos += tmp->length();
1526 exponentDigits.fIsPositive = FALSE;
1531 while (pos < textLength) {
1532 ch = text[(int32_t)pos];
1535 if (digit < 0 || digit > 9) {
1536 digit = u_charDigitValue(ch);
1538 if (0 <= digit && digit <= 9) {
1540 exponentDigits.append((char)(digit + '0'));
1546 if (exponentDigits.fCount > 0) {
1547 exponentDigits.fDecimalAt = exponentDigits.fCount;
1548 digits.fDecimalAt += exponentDigits.getLong();
1549 position = pos; // Advance past the exponent
1552 break; // Whether we fail or succeed, we exit this loop
1565 // If there was no decimal point we have an integer
1568 digits.fDecimalAt += digitCount; // Not digits.fCount!
1571 // If none of the text string was recognized. For example, parse
1572 // "x" with pattern "#0.00" (return index and error index both 0)
1573 // parse "$" with pattern "$#0.00". (return index 0 and error index
1575 if (!sawDigit && digitCount == 0) {
1576 parsePosition.setIndex(oldStart);
1577 parsePosition.setErrorIndex(oldStart);
1582 // Match padding before suffix
1583 if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) {
1584 position = skipPadding(text, position);
1587 // Match positive and negative suffixes; prefer longest match.
1588 if (posMatch >= 0) {
1589 posMatch = compareAffix(text, position, FALSE, FALSE, currency);
1591 if (negMatch >= 0) {
1592 negMatch = compareAffix(text, position, TRUE, FALSE, currency);
1594 if (posMatch >= 0 && negMatch >= 0) {
1595 if (posMatch > negMatch) {
1597 } else if (negMatch > posMatch) {
1602 // Fail if neither or both
1603 if ((posMatch >= 0) == (negMatch >= 0)) {
1604 parsePosition.setErrorIndex(position);
1608 position += (posMatch>=0 ? posMatch : negMatch);
1610 // Match padding before suffix
1611 if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) {
1612 position = skipPadding(text, position);
1615 parsePosition.setIndex(position);
1617 digits.fIsPositive = (posMatch >= 0);
1619 if(parsePosition.getIndex() == oldStart)
1621 parsePosition.setErrorIndex(position);
1628 * Starting at position, advance past a run of pad characters, if any.
1629 * Return the index of the first character after position that is not a pad
1630 * character. Result is >= position.
1632 int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
1633 int32_t padLen = U16_LENGTH(fPad);
1634 while (position < text.length() &&
1635 text.char32At(position) == fPad) {
1642 * Return the length matched by the given affix, or -1 if none.
1643 * Runs of white space in the affix, match runs of white space in
1644 * the input. Pattern white space and input white space are
1645 * determined differently; see code.
1646 * @param text input text
1647 * @param pos offset into input at which to begin matching
1650 * @param currency return value for parsed currency, for generic
1651 * currency parsing mode, or null for normal parsing. In generic
1652 * currency parsing mode, any currency is parsed, not just the
1653 * currency that this formatter is set to.
1654 * @return length of input that matches, or -1 if match failure
1656 int32_t DecimalFormat::compareAffix(const UnicodeString& text,
1660 UChar* currency) const {
1661 if (fCurrencyChoice != NULL || currency != NULL) {
1663 return compareComplexAffix(isNegative ? *fNegPrefixPattern : *fPosPrefixPattern,
1664 text, pos, currency);
1666 return compareComplexAffix(isNegative ? *fNegSuffixPattern : *fPosSuffixPattern,
1667 text, pos, currency);
1672 return compareSimpleAffix(isNegative ? fNegativePrefix : fPositivePrefix,
1675 return compareSimpleAffix(isNegative ? fNegativeSuffix : fPositiveSuffix,
1681 * Return the length matched by the given affix, or -1 if none.
1682 * Runs of white space in the affix, match runs of white space in
1683 * the input. Pattern white space and input white space are
1684 * determined differently; see code.
1685 * @param affix pattern string, taken as a literal
1686 * @param input input text
1687 * @param pos offset into input at which to begin matching
1688 * @return length of input that matches, or -1 if match failure
1690 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
1691 const UnicodeString& input,
1693 int32_t start = pos;
1694 for (int32_t i=0; i<affix.length(); ) {
1695 UChar32 c = affix.char32At(i);
1696 int32_t len = U16_LENGTH(c);
1697 if (uprv_isRuleWhiteSpace(c)) {
1698 // We may have a pattern like: \u200F \u0020
1699 // and input text like: \u200F \u0020
1700 // Note that U+200F and U+0020 are RuleWhiteSpace but only
1701 // U+0020 is UWhiteSpace. So we have to first do a direct
1702 // match of the run of RULE whitespace in the pattern,
1703 // then match any extra characters.
1704 UBool literalMatch = FALSE;
1705 while (pos < input.length() &&
1706 input.char32At(pos) == c) {
1707 literalMatch = TRUE;
1710 if (i == affix.length()) {
1713 c = affix.char32At(i);
1714 len = U16_LENGTH(c);
1715 if (!uprv_isRuleWhiteSpace(c)) {
1720 // Advance over run in pattern
1721 i = skipRuleWhiteSpace(affix, i);
1723 // Advance over run in input text
1724 // Must see at least one white space char in input,
1725 // unless we've already matched some characters literally.
1727 pos = skipUWhiteSpace(input, pos);
1728 if (pos == s && !literalMatch) {
1732 if (pos < input.length() &&
1733 input.char32At(pos) == c) {
1745 * Skip over a run of zero or more isRuleWhiteSpace() characters at
1748 int32_t DecimalFormat::skipRuleWhiteSpace(const UnicodeString& text, int32_t pos) {
1749 while (pos < text.length()) {
1750 UChar32 c = text.char32At(pos);
1751 if (!uprv_isRuleWhiteSpace(c)) {
1754 pos += U16_LENGTH(c);
1760 * Skip over a run of zero or more isUWhiteSpace() characters at pos
1763 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) {
1764 while (pos < text.length()) {
1765 UChar32 c = text.char32At(pos);
1766 if (!u_isUWhiteSpace(c)) {
1769 pos += U16_LENGTH(c);
1775 * Return the length matched by the given affix, or -1 if none.
1776 * @param affixPat pattern string
1777 * @param input input text
1778 * @param pos offset into input at which to begin matching
1779 * @param currency return value for parsed currency, for generic
1780 * currency parsing mode, or null for normal parsing. In generic
1781 * currency parsing mode, any currency is parsed, not just the
1782 * currency that this formatter is set to.
1783 * @return length of input that matches, or -1 if match failure
1785 int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
1786 const UnicodeString& text,
1788 UChar* currency) const
1790 int32_t start = pos;
1791 U_ASSERT(currency != NULL ||
1792 (fCurrencyChoice != NULL && *getCurrency() != 0));
1794 for (int32_t i=0; i<affixPat.length() && pos >= 0; ) {
1795 UChar32 c = affixPat.char32At(i);
1799 U_ASSERT(i <= affixPat.length());
1800 c = affixPat.char32At(i);
1803 const UnicodeString* affix = NULL;
1806 case kCurrencySign: {
1807 // If currency != null, then perform generic currency matching.
1808 // Otherwise, do currency choice parsing.
1809 UBool intl = i<affixPat.length() &&
1810 affixPat.char32At(i) == kCurrencySign;
1811 // Parse generic currency -- anything for which we
1812 // have a display name, or any 3-letter ISO code.
1813 if (currency != NULL) {
1814 // Try to parse display name for our locale; first
1815 // determine our locale.
1816 UErrorCode ec = U_ZERO_ERROR;
1817 const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
1818 if (U_FAILURE(ec) || loc == NULL || *loc == 0) {
1819 // applyPattern has been called; use the symbols
1820 loc = fSymbols->getLocale().getName();
1823 // Delegate parse of display name => ISO code to Currency
1824 ParsePosition ppos(pos);
1826 uprv_parseCurrency(loc, text, ppos, curr, ec);
1828 // If parse succeeds, populate currency[0]
1829 if (U_SUCCESS(ec) && ppos.getIndex() != pos) {
1830 u_strcpy(currency, curr);
1831 pos = ppos.getIndex();
1838 pos = match(text, pos, getCurrency());
1840 ParsePosition ppos(pos);
1842 fCurrencyChoice->parse(text, result, ppos);
1843 pos = (ppos.getIndex() == pos) ? -1 : ppos.getIndex();
1848 case kPatternPercent:
1849 affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
1851 case kPatternPerMill:
1852 affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
1855 affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
1858 affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
1861 // fall through to affix!=0 test, which will fail
1865 if (affix != NULL) {
1866 pos = match(text, pos, *affix);
1871 pos = match(text, pos, c);
1872 if (uprv_isRuleWhiteSpace(c)) {
1873 i = skipRuleWhiteSpace(affixPat, i);
1880 * Match a single character at text[pos] and return the index of the
1881 * next character upon success. Return -1 on failure. If
1882 * isRuleWhiteSpace(ch) then match a run of white space in text.
1884 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) {
1885 if (uprv_isRuleWhiteSpace(ch)) {
1886 // Advance over run of white space in input text
1887 // Must see at least one white space char in input
1889 pos = skipUWhiteSpace(text, pos);
1895 return (pos >= 0 && text.char32At(pos) == ch) ?
1896 (pos + U16_LENGTH(ch)) : -1;
1900 * Match a string at text[pos] and return the index of the next
1901 * character upon success. Return -1 on failure. Match a run of
1902 * white space in str with a run of white space in text.
1904 int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) {
1905 for (int32_t i=0; i<str.length() && pos >= 0; ) {
1906 UChar32 ch = str.char32At(i);
1907 i += U16_LENGTH(ch);
1908 if (uprv_isRuleWhiteSpace(ch)) {
1909 i = skipRuleWhiteSpace(str, i);
1911 pos = match(text, pos, ch);
1916 //------------------------------------------------------------------------------
1917 // Gets the pointer to the localized decimal format symbols
1919 const DecimalFormatSymbols*
1920 DecimalFormat::getDecimalFormatSymbols() const
1925 //------------------------------------------------------------------------------
1926 // De-owning the current localized symbols and adopt the new symbols.
1929 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
1931 if (symbolsToAdopt == NULL) {
1932 return; // do not allow caller to set fSymbols to NULL
1935 UBool sameSymbols = FALSE;
1936 if (fSymbols != NULL) {
1937 sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
1938 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
1939 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
1940 symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
1944 fSymbols = symbolsToAdopt;
1946 // If the currency symbols are the same, there is no need to recalculate.
1947 setCurrencyForSymbols();
1951 //------------------------------------------------------------------------------
1952 // Setting the symbols is equlivalent to adopting a newly created localized
1956 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
1958 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
1962 * Update the currency object to match the symbols. This method
1963 * is used only when the caller has passed in a symbols object
1964 * that may not be the default object for its locale.
1967 DecimalFormat::setCurrencyForSymbols() {
1969 Update the affix strings accroding to symbols in order to keep
1970 the affix strings up to date.
1974 // With the introduction of the Currency object, the currency
1975 // symbols in the DFS object are ignored. For backward
1976 // compatibility, we check any explicitly set DFS object. If it
1977 // is a default symbols object for its locale, we change the
1978 // currency object to one for that locale. If it is custom,
1979 // we set the currency to null.
1980 UErrorCode ec = U_ZERO_ERROR;
1981 const UChar* c = NULL;
1982 const char* loc = fSymbols->getLocale().getName();
1983 UChar intlCurrencySymbol[4];
1984 ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec);
1985 UnicodeString currencySymbol;
1987 uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec);
1989 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol
1990 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == intlCurrencySymbol)
1992 // Trap an error in mapping locale to currency. If we can't
1993 // map, then don't fail and set the currency to "".
1994 c = intlCurrencySymbol;
1996 ec = U_ZERO_ERROR; // reset local error code!
2001 //------------------------------------------------------------------------------
2002 // Gets the positive prefix of the number pattern.
2005 DecimalFormat::getPositivePrefix(UnicodeString& result) const
2007 result = fPositivePrefix;
2011 //------------------------------------------------------------------------------
2012 // Sets the positive prefix of the number pattern.
2015 DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
2017 fPositivePrefix = newValue;
2018 delete fPosPrefixPattern;
2019 fPosPrefixPattern = 0;
2022 //------------------------------------------------------------------------------
2023 // Gets the negative prefix of the number pattern.
2026 DecimalFormat::getNegativePrefix(UnicodeString& result) const
2028 result = fNegativePrefix;
2032 //------------------------------------------------------------------------------
2033 // Gets the negative prefix of the number pattern.
2036 DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
2038 fNegativePrefix = newValue;
2039 delete fNegPrefixPattern;
2040 fNegPrefixPattern = 0;
2043 //------------------------------------------------------------------------------
2044 // Gets the positive suffix of the number pattern.
2047 DecimalFormat::getPositiveSuffix(UnicodeString& result) const
2049 result = fPositiveSuffix;
2053 //------------------------------------------------------------------------------
2054 // Sets the positive suffix of the number pattern.
2057 DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
2059 fPositiveSuffix = newValue;
2060 delete fPosSuffixPattern;
2061 fPosSuffixPattern = 0;
2064 //------------------------------------------------------------------------------
2065 // Gets the negative suffix of the number pattern.
2068 DecimalFormat::getNegativeSuffix(UnicodeString& result) const
2070 result = fNegativeSuffix;
2074 //------------------------------------------------------------------------------
2075 // Sets the negative suffix of the number pattern.
2078 DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
2080 fNegativeSuffix = newValue;
2081 delete fNegSuffixPattern;
2082 fNegSuffixPattern = 0;
2085 //------------------------------------------------------------------------------
2086 // Gets the multiplier of the number pattern.
2088 int32_t DecimalFormat::getMultiplier() const
2093 //------------------------------------------------------------------------------
2094 // Sets the multiplier of the number pattern.
2096 DecimalFormat::setMultiplier(int32_t newValue)
2098 // This shouldn't be set to 0.
2099 // Due to compatibility with ICU4J we cannot set an error code and refuse 0.
2100 // So the rest of the code should ignore fMultiplier when it's 0. [grhoten]
2101 fMultiplier = newValue;
2105 * Get the rounding increment.
2106 * @return A positive rounding increment, or 0.0 if rounding
2108 * @see #setRoundingIncrement
2109 * @see #getRoundingMode
2110 * @see #setRoundingMode
2112 double DecimalFormat::getRoundingIncrement() const {
2113 return fRoundingDouble;
2117 * Set the rounding increment. This method also controls whether
2118 * rounding is enabled.
2119 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2120 * Negative increments are equivalent to 0.0.
2121 * @see #getRoundingIncrement
2122 * @see #getRoundingMode
2123 * @see #setRoundingMode
2125 void DecimalFormat::setRoundingIncrement(double newValue) {
2126 if (newValue > 0.0) {
2127 if (fRoundingIncrement == NULL) {
2128 fRoundingIncrement = new DigitList();
2130 fRoundingIncrement->set((int32_t)newValue);
2131 fRoundingDouble = newValue;
2133 delete fRoundingIncrement;
2134 fRoundingIncrement = NULL;
2135 fRoundingDouble = 0.0;
2140 * Get the rounding mode.
2141 * @return A rounding mode
2142 * @see #setRoundingIncrement
2143 * @see #getRoundingIncrement
2144 * @see #setRoundingMode
2146 DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
2147 return fRoundingMode;
2151 * Set the rounding mode. This has no effect unless the rounding
2152 * increment is greater than zero.
2153 * @param roundingMode A rounding mode
2154 * @see #setRoundingIncrement
2155 * @see #getRoundingIncrement
2156 * @see #getRoundingMode
2158 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
2159 fRoundingMode = roundingMode;
2163 * Get the width to which the output of <code>format()</code> is padded.
2164 * @return the format width, or zero if no padding is in effect
2165 * @see #setFormatWidth
2166 * @see #getPadCharacter
2167 * @see #setPadCharacter
2168 * @see #getPadPosition
2169 * @see #setPadPosition
2171 int32_t DecimalFormat::getFormatWidth() const {
2172 return fFormatWidth;
2176 * Set the width to which the output of <code>format()</code> is padded.
2177 * This method also controls whether padding is enabled.
2178 * @param width the width to which to pad the result of
2179 * <code>format()</code>, or zero to disable padding. A negative
2180 * width is equivalent to 0.
2181 * @see #getFormatWidth
2182 * @see #getPadCharacter
2183 * @see #setPadCharacter
2184 * @see #getPadPosition
2185 * @see #setPadPosition
2187 void DecimalFormat::setFormatWidth(int32_t width) {
2188 fFormatWidth = (width > 0) ? width : 0;
2191 UnicodeString DecimalFormat::getPadCharacterString() const {
2195 void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
2196 if (padChar.length() > 0) {
2197 fPad = padChar.char32At(0);
2205 * Get the position at which padding will take place. This is the location
2206 * at which padding will be inserted if the result of <code>format()</code>
2207 * is shorter than the format width.
2208 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2209 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2210 * <code>kPadAfterSuffix</code>.
2211 * @see #setFormatWidth
2212 * @see #getFormatWidth
2213 * @see #setPadCharacter
2214 * @see #getPadCharacter
2215 * @see #setPadPosition
2216 * @see #kPadBeforePrefix
2217 * @see #kPadAfterPrefix
2218 * @see #kPadBeforeSuffix
2219 * @see #kPadAfterSuffix
2221 DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
2222 return fPadPosition;
2226 * <strong><font face=helvetica color=red>NEW</font></strong>
2227 * Set the position at which padding will take place. This is the location
2228 * at which padding will be inserted if the result of <code>format()</code>
2229 * is shorter than the format width. This has no effect unless padding is
2231 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2232 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2233 * <code>kPadAfterSuffix</code>.
2234 * @see #setFormatWidth
2235 * @see #getFormatWidth
2236 * @see #setPadCharacter
2237 * @see #getPadCharacter
2238 * @see #getPadPosition
2239 * @see #kPadBeforePrefix
2240 * @see #kPadAfterPrefix
2241 * @see #kPadBeforeSuffix
2242 * @see #kPadAfterSuffix
2244 void DecimalFormat::setPadPosition(EPadPosition padPos) {
2245 fPadPosition = padPos;
2249 * Return whether or not scientific notation is used.
2250 * @return TRUE if this object formats and parses scientific notation
2251 * @see #setScientificNotation
2252 * @see #getMinimumExponentDigits
2253 * @see #setMinimumExponentDigits
2254 * @see #isExponentSignAlwaysShown
2255 * @see #setExponentSignAlwaysShown
2257 UBool DecimalFormat::isScientificNotation() {
2258 return fUseExponentialNotation;
2262 * Set whether or not scientific notation is used.
2263 * @param useScientific TRUE if this object formats and parses scientific
2265 * @see #isScientificNotation
2266 * @see #getMinimumExponentDigits
2267 * @see #setMinimumExponentDigits
2268 * @see #isExponentSignAlwaysShown
2269 * @see #setExponentSignAlwaysShown
2271 void DecimalFormat::setScientificNotation(UBool useScientific) {
2272 fUseExponentialNotation = useScientific;
2276 * Return the minimum exponent digits that will be shown.
2277 * @return the minimum exponent digits that will be shown
2278 * @see #setScientificNotation
2279 * @see #isScientificNotation
2280 * @see #setMinimumExponentDigits
2281 * @see #isExponentSignAlwaysShown
2282 * @see #setExponentSignAlwaysShown
2284 int8_t DecimalFormat::getMinimumExponentDigits() const {
2285 return fMinExponentDigits;
2289 * Set the minimum exponent digits that will be shown. This has no
2290 * effect unless scientific notation is in use.
2291 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2292 * that will be shown. Values less than 1 will be treated as 1.
2293 * @see #setScientificNotation
2294 * @see #isScientificNotation
2295 * @see #getMinimumExponentDigits
2296 * @see #isExponentSignAlwaysShown
2297 * @see #setExponentSignAlwaysShown
2299 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
2300 fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
2304 * Return whether the exponent sign is always shown.
2305 * @return TRUE if the exponent is always prefixed with either the
2306 * localized minus sign or the localized plus sign, false if only negative
2307 * exponents are prefixed with the localized minus sign.
2308 * @see #setScientificNotation
2309 * @see #isScientificNotation
2310 * @see #setMinimumExponentDigits
2311 * @see #getMinimumExponentDigits
2312 * @see #setExponentSignAlwaysShown
2314 UBool DecimalFormat::isExponentSignAlwaysShown() {
2315 return fExponentSignAlwaysShown;
2319 * Set whether the exponent sign is always shown. This has no effect
2320 * unless scientific notation is in use.
2321 * @param expSignAlways TRUE if the exponent is always prefixed with either
2322 * the localized minus sign or the localized plus sign, false if only
2323 * negative exponents are prefixed with the localized minus sign.
2324 * @see #setScientificNotation
2325 * @see #isScientificNotation
2326 * @see #setMinimumExponentDigits
2327 * @see #getMinimumExponentDigits
2328 * @see #isExponentSignAlwaysShown
2330 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
2331 fExponentSignAlwaysShown = expSignAlways;
2334 //------------------------------------------------------------------------------
2335 // Gets the grouping size of the number pattern. For example, thousand or 10
2336 // thousand groupings.
2339 DecimalFormat::getGroupingSize() const
2341 return fGroupingSize;
2344 //------------------------------------------------------------------------------
2345 // Gets the grouping size of the number pattern.
2348 DecimalFormat::setGroupingSize(int32_t newValue)
2350 fGroupingSize = newValue;
2353 //------------------------------------------------------------------------------
2356 DecimalFormat::getSecondaryGroupingSize() const
2358 return fGroupingSize2;
2361 //------------------------------------------------------------------------------
2364 DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
2366 fGroupingSize2 = newValue;
2369 //------------------------------------------------------------------------------
2370 // Checks if to show the decimal separator.
2373 DecimalFormat::isDecimalSeparatorAlwaysShown() const
2375 return fDecimalSeparatorAlwaysShown;
2378 //------------------------------------------------------------------------------
2379 // Sets to always show the decimal separator.
2382 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
2384 fDecimalSeparatorAlwaysShown = newValue;
2387 //------------------------------------------------------------------------------
2388 // Emits the pattern of this DecimalFormat instance.
2391 DecimalFormat::toPattern(UnicodeString& result) const
2393 return toPattern(result, FALSE);
2396 //------------------------------------------------------------------------------
2397 // Emits the localized pattern this DecimalFormat instance.
2400 DecimalFormat::toLocalizedPattern(UnicodeString& result) const
2402 return toPattern(result, TRUE);
2405 //------------------------------------------------------------------------------
2407 * Expand the affix pattern strings into the expanded affix strings. If any
2408 * affix pattern string is null, do not expand it. This method should be
2409 * called any time the symbols or the affix patterns change in order to keep
2410 * the expanded affix strings up to date.
2412 void DecimalFormat::expandAffixes() {
2413 if (fPosPrefixPattern != 0) {
2414 expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, FALSE);
2416 if (fPosSuffixPattern != 0) {
2417 expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, FALSE);
2419 if (fNegPrefixPattern != 0) {
2420 expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, FALSE);
2422 if (fNegSuffixPattern != 0) {
2423 expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, FALSE);
2428 .append(*fPosPrefixPattern).append("|").append(*fPosSuffixPattern)
2429 .append(";") .append(*fNegPrefixPattern).append("|").append(*fNegSuffixPattern)
2431 .append(fPositivePrefix).append("|").append(fPositiveSuffix)
2432 .append(";") .append(fNegativePrefix).append("|").append(fNegativeSuffix)
2439 * Expand an affix pattern into an affix string. All characters in the
2440 * pattern are literal unless prefixed by kQuote. The following characters
2441 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
2442 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
2443 * kCurrencySign + kCurrencySign), it is interpreted as an international
2444 * currency sign. Any other character after a kQuote represents itself.
2445 * kQuote must be followed by another character; kQuote may not occur by
2446 * itself at the end of the pattern.
2448 * This method is used in two distinct ways. First, it is used to expand
2449 * the stored affix patterns into actual affixes. For this usage, doFormat
2450 * must be false. Second, it is used to expand the stored affix patterns
2451 * given a specific number (doFormat == true), for those rare cases in
2452 * which a currency format references a ChoiceFormat (e.g., en_IN display
2453 * name for INR). The number itself is taken from digitList.
2455 * When used in the first way, this method has a side effect: It sets
2456 * currencyChoice to a ChoiceFormat object, if the currency's display name
2457 * in this locale is a ChoiceFormat pattern (very rare). It only does this
2458 * if currencyChoice is null to start with.
2460 * @param pattern the non-null, fPossibly empty pattern
2461 * @param affix string to receive the expanded equivalent of pattern.
2462 * Previous contents are deleted.
2463 * @param doFormat if false, then the pattern will be expanded, and if a
2464 * currency symbol is encountered that expands to a ChoiceFormat, the
2465 * currencyChoice member variable will be initialized if it is null. If
2466 * doFormat is true, then it is assumed that the currencyChoice has been
2467 * created, and it will be used to format the value in digitList.
2469 void DecimalFormat::expandAffix(const UnicodeString& pattern,
2470 UnicodeString& affix,
2472 UBool doFormat) const {
2474 for (int i=0; i<pattern.length(); ) {
2475 UChar32 c = pattern.char32At(i);
2478 c = pattern.char32At(i);
2481 case kCurrencySign: {
2482 // As of ICU 2.2 we use the currency object, and
2483 // ignore the currency symbols in the DFS, unless
2484 // we have a null currency object. This occurs if
2485 // resurrecting a pre-2.2 object or if the user
2486 // sets a custom DFS.
2487 UBool intl = i<pattern.length() &&
2488 pattern.char32At(i) == kCurrencySign;
2492 const UChar* currencyUChars = getCurrency();
2493 if (currencyUChars[0] != 0) {
2494 UErrorCode ec = U_ZERO_ERROR;
2496 affix += currencyUChars;
2499 UBool isChoiceFormat;
2500 const UChar* s = ucurr_getName(currencyUChars, fSymbols->getLocale().getName(),
2501 UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
2502 if (isChoiceFormat) {
2503 // Two modes here: If doFormat is false, we set up
2504 // currencyChoice. If doFormat is true, we use the
2505 // previously created currencyChoice to format the
2506 // value in digitList.
2508 // If the currency is handled by a ChoiceFormat,
2509 // then we're not going to use the expanded
2510 // patterns. Instantiate the ChoiceFormat and
2512 if (fCurrencyChoice == NULL) {
2513 // TODO Replace double-check with proper thread-safe code
2514 ChoiceFormat* fmt = new ChoiceFormat(s, ec);
2515 if (U_SUCCESS(ec)) {
2517 if (fCurrencyChoice == NULL) {
2519 ((DecimalFormat*)this)->fCurrencyChoice = fmt;
2526 // We could almost return null or "" here, since the
2527 // expanded affixes are almost not used at all
2528 // in this situation. However, one method --
2529 // toPattern() -- still does use the expanded
2530 // affixes, in order to set up a padding
2531 // pattern. We use the CURRENCY_SIGN as a
2533 affix.append(kCurrencySign);
2535 if (fCurrencyChoice != NULL) {
2536 FieldPosition pos(0); // ignored
2540 fCurrencyChoice->format(number, affix, pos);
2542 // We only arrive here if the currency choice
2543 // format in the locale data is INVALID.
2544 affix += currencyUChars;
2549 affix += UnicodeString(s, len);
2553 affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
2555 affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
2560 case kPatternPercent:
2561 affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2563 case kPatternPerMill:
2564 affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2567 affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2570 affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2584 * Append an affix to the given StringBuffer.
2585 * @param buf buffer to append to
2589 int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
2590 UBool isNegative, UBool isPrefix) const {
2591 if (fCurrencyChoice != 0) {
2592 const UnicodeString* affixPat = 0;
2594 affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern;
2596 affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern;
2598 UnicodeString affixBuf;
2599 expandAffix(*affixPat, affixBuf, number, TRUE);
2600 buf.append(affixBuf);
2601 return affixBuf.length();
2604 const UnicodeString* affix = NULL;
2606 affix = isNegative ? &fNegativePrefix : &fPositivePrefix;
2608 affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
2611 return affix->length();
2615 * Appends an affix pattern to the given StringBuffer, quoting special
2616 * characters as needed. Uses the internal affix pattern, if that exists,
2617 * or the literal affix, if the internal affix pattern is null. The
2618 * appended string will generate the same affix pattern (or literal affix)
2619 * when passed to toPattern().
2621 * @param appendTo the affix string is appended to this
2622 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
2623 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
2624 * Ignored unless affixPattern is null. If affixPattern is null, then
2625 * expAffix is appended as a literal affix.
2626 * @param localized true if the appended pattern should contain localized
2627 * pattern characters; otherwise, non-localized pattern chars are appended
2629 void DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
2630 const UnicodeString* affixPattern,
2631 const UnicodeString& expAffix,
2632 UBool localized) const {
2633 if (affixPattern == 0) {
2634 appendAffixPattern(appendTo, expAffix, localized);
2637 for (int pos=0; pos<affixPattern->length(); pos=i) {
2638 i = affixPattern->indexOf(kQuote, pos);
2641 affixPattern->extractBetween(pos, affixPattern->length(), s);
2642 appendAffixPattern(appendTo, s, localized);
2647 affixPattern->extractBetween(pos, i, s);
2648 appendAffixPattern(appendTo, s, localized);
2650 UChar32 c = affixPattern->char32At(++i);
2653 appendTo.append(c).append(c);
2654 // Fall through and append another kQuote below
2655 } else if (c == kCurrencySign &&
2656 i<affixPattern->length() &&
2657 affixPattern->char32At(i) == kCurrencySign) {
2659 appendTo.append(c).append(c);
2660 } else if (localized) {
2662 case kPatternPercent:
2663 appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
2665 case kPatternPerMill:
2666 appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
2669 appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2672 appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
2685 * Append an affix to the given StringBuffer, using quotes if
2686 * there are special characters. Single quotes themselves must be
2687 * escaped in either case.
2690 DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
2691 const UnicodeString& affix,
2692 UBool localized) const {
2695 needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0
2696 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0
2697 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0
2698 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0
2699 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0
2700 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0
2701 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0
2702 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0
2703 || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0
2704 || affix.indexOf(kCurrencySign) >= 0;
2707 needQuote = affix.indexOf(kPatternZeroDigit) >= 0
2708 || affix.indexOf(kPatternGroupingSeparator) >= 0
2709 || affix.indexOf(kPatternDecimalSeparator) >= 0
2710 || affix.indexOf(kPatternPercent) >= 0
2711 || affix.indexOf(kPatternPerMill) >= 0
2712 || affix.indexOf(kPatternDigit) >= 0
2713 || affix.indexOf(kPatternSeparator) >= 0
2714 || affix.indexOf(kPatternExponent) >= 0
2715 || affix.indexOf(kPatternPlus) >= 0
2716 || affix.indexOf(kPatternMinus) >= 0
2717 || affix.indexOf(kCurrencySign) >= 0;
2720 appendTo += (UChar)0x0027 /*'\''*/;
2721 if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0)
2724 for (int32_t j = 0; j < affix.length(); ) {
2725 UChar32 c = affix.char32At(j);
2728 if (c == 0x0027 /*'\''*/)
2733 appendTo += (UChar)0x0027 /*'\''*/;
2736 //------------------------------------------------------------------------------
2739 DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
2742 UChar32 zero, sigDigit = kPatternSignificantDigit;
2743 UnicodeString digit, group;
2745 int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits
2746 UnicodeString roundingDigits;
2747 int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1;
2748 UnicodeString padSpec;
2749 UBool useSigDig = areSignificantDigitsUsed();
2752 digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
2753 group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
2754 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
2756 sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
2760 digit.append((UChar)kPatternDigit);
2761 group.append((UChar)kPatternGroupingSeparator);
2762 zero = (UChar32)kPatternZeroDigit;
2764 if (fFormatWidth > 0) {
2766 padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
2769 padSpec.append((UChar)kPatternPadEscape);
2771 padSpec.append(fPad);
2773 if (fRoundingIncrement != NULL) {
2774 for(i=0; i<fRoundingIncrement->fCount; ++i) {
2775 roundingDigits.append((UChar)fRoundingIncrement->fDigits[i]);
2777 roundingDecimalPos = fRoundingIncrement->fDecimalAt;
2779 for (int32_t part=0; part<2; ++part) {
2780 if (padPos == kPadBeforePrefix) {
2781 result.append(padSpec);
2783 appendAffixPattern(result,
2784 (part==0 ? fPosPrefixPattern : fNegPrefixPattern),
2785 (part==0 ? fPositivePrefix : fNegativePrefix),
2787 if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) {
2788 result.append(padSpec);
2790 int32_t sub0Start = result.length();
2791 int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0;
2792 if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
2793 g += fGroupingSize2;
2795 int32_t maxDig = 0, minDig = 0, maxSigDig = 0;
2797 minDig = getMinimumSignificantDigits();
2798 maxDig = maxSigDig = getMaximumSignificantDigits();
2800 minDig = getMinimumIntegerDigits();
2801 maxDig = getMaximumIntegerDigits();
2803 if (fUseExponentialNotation) {
2804 if (maxDig > kMaxScientificIntegerDigits) {
2807 } else if (useSigDig) {
2808 maxDig = _max(maxDig, g+1);
2810 maxDig = _max(_max(g, getMinimumIntegerDigits()),
2811 roundingDecimalPos) + 1;
2813 for (i = maxDig; i > 0; --i) {
2814 if (!fUseExponentialNotation && i<maxDig &&
2815 isGroupingPosition(i)) {
2816 result.append(group);
2819 // #@,@### (maxSigDig == 5, minSigDig == 2)
2820 // 65 4321 (1-based pos, count from the right)
2821 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
2822 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
2823 if (maxSigDig >= i && i > (maxSigDig - minDig)) {
2824 result.append(sigDigit);
2826 result.append(digit);
2829 if (! roundingDigits.isEmpty()) {
2830 int32_t pos = roundingDecimalPos - i;
2831 if (pos >= 0 && pos < roundingDigits.length()) {
2832 result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
2837 result.append(zero);
2839 result.append(digit);
2844 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) {
2846 result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
2849 result.append((UChar)kPatternDecimalSeparator);
2852 int32_t pos = roundingDecimalPos;
2853 for (i = 0; i < getMaximumFractionDigits(); ++i) {
2854 if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) {
2856 result.append(zero);
2859 result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
2864 if (i<getMinimumFractionDigits()) {
2865 result.append(zero);
2868 result.append(digit);
2872 if (fUseExponentialNotation) {
2874 result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
2877 result.append((UChar)kPatternExponent);
2879 if (fExponentSignAlwaysShown) {
2881 result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
2884 result.append((UChar)kPatternPlus);
2887 for (i=0; i<fMinExponentDigits; ++i) {
2888 result.append(zero);
2891 if (! padSpec.isEmpty() && !fUseExponentialNotation) {
2892 int32_t add = fFormatWidth - result.length() + sub0Start
2894 ? fPositivePrefix.length() + fPositiveSuffix.length()
2895 : fNegativePrefix.length() + fNegativeSuffix.length());
2897 result.insert(sub0Start, digit);
2900 // Only add a grouping separator if we have at least
2901 // 2 additional characters to be added, so we don't
2902 // end up with ",###".
2903 if (add>1 && isGroupingPosition(maxDig)) {
2904 result.insert(sub0Start, group);
2909 if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) {
2910 result.append(padSpec);
2913 appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized);
2914 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
2915 result.append(padSpec);
2917 UBool isDefault = FALSE;
2918 if ((fNegSuffixPattern == fPosSuffixPattern && // both null
2919 fNegativeSuffix == fPositiveSuffix)
2920 || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 &&
2921 *fNegSuffixPattern == *fPosSuffixPattern))
2923 if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL)
2925 int32_t length = fPosPrefixPattern->length();
2926 isDefault = fNegPrefixPattern->length() == (length+2) &&
2927 (*fNegPrefixPattern)[(int32_t)0] == kQuote &&
2928 (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus &&
2929 fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0;
2932 fNegPrefixPattern == NULL && fPosPrefixPattern == NULL)
2934 int32_t length = fPositivePrefix.length();
2935 isDefault = fNegativePrefix.length() == (length+1) &&
2936 fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 &&
2937 fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0;
2941 break; // Don't output default negative subpattern
2944 result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
2947 result.append((UChar)kPatternSeparator);
2951 appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized);
2952 if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
2953 result.append(padSpec);
2961 //------------------------------------------------------------------------------
2964 DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
2966 UParseError parseError;
2967 applyPattern(pattern, FALSE, parseError, status);
2970 //------------------------------------------------------------------------------
2973 DecimalFormat::applyPattern(const UnicodeString& pattern,
2974 UParseError& parseError,
2977 applyPattern(pattern, FALSE, parseError, status);
2979 //------------------------------------------------------------------------------
2982 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
2984 UParseError parseError;
2985 applyPattern(pattern, TRUE,parseError,status);
2988 //------------------------------------------------------------------------------
2991 DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
2992 UParseError& parseError,
2995 applyPattern(pattern, TRUE,parseError,status);
2998 //------------------------------------------------------------------------------
3001 DecimalFormat::applyPattern(const UnicodeString& pattern,
3003 UParseError& parseError,
3006 if (U_FAILURE(status))
3010 // Clear error struct
3011 parseError.offset = -1;
3012 parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
3014 // Set the significant pattern symbols
3015 UChar32 zeroDigit = kPatternZeroDigit; // '0'
3016 UChar32 sigDigit = kPatternSignificantDigit; // '@'
3017 UnicodeString groupingSeparator ((UChar)kPatternGroupingSeparator);
3018 UnicodeString decimalSeparator ((UChar)kPatternDecimalSeparator);
3019 UnicodeString percent ((UChar)kPatternPercent);
3020 UnicodeString perMill ((UChar)kPatternPerMill);
3021 UnicodeString digit ((UChar)kPatternDigit); // '#'
3022 UnicodeString separator ((UChar)kPatternSeparator);
3023 UnicodeString exponent ((UChar)kPatternExponent);
3024 UnicodeString plus ((UChar)kPatternPlus);
3025 UnicodeString minus ((UChar)kPatternMinus);
3026 UnicodeString padEscape ((UChar)kPatternPadEscape);
3027 // Substitute with the localized symbols if necessary
3029 zeroDigit = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
3030 sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
3031 groupingSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
3032 decimalSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol));
3033 percent. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
3034 perMill. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
3035 digit. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
3036 separator. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
3037 exponent. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol));
3038 plus. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol));
3039 minus. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
3040 padEscape. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
3042 UChar nineDigit = (UChar)(zeroDigit + 9);
3043 int32_t digitLen = digit.length();
3044 int32_t groupSepLen = groupingSeparator.length();
3045 int32_t decimalSepLen = decimalSeparator.length();
3048 int32_t patLen = pattern.length();
3049 // Part 0 is the positive pattern. Part 1, if present, is the negative
3051 for (int32_t part=0; part<2 && pos<patLen; ++part) {
3052 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
3053 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
3054 // between the prefix and suffix, and consists of pattern
3055 // characters. In the prefix and suffix, percent, perMill, and
3056 // currency symbols are recognized and translated.
3057 int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
3059 // It's important that we don't change any fields of this object
3060 // prematurely. We set the following variables for the multiplier,
3061 // grouping, etc., and then only change the actual object fields if
3062 // everything parses correctly. This also lets us register
3063 // the data from part 0 and ignore the part 1, except for the
3064 // prefix and suffix.
3065 UnicodeString prefix;
3066 UnicodeString suffix;
3067 int32_t decimalPos = -1;
3068 int32_t multiplier = 1;
3069 int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
3070 int8_t groupingCount = -1;
3071 int8_t groupingCount2 = -1;
3072 int32_t padPos = -1;
3073 UChar32 padChar = 0;
3074 int32_t roundingPos = -1;
3075 DigitList roundingInc;
3076 int8_t expDigits = -1;
3077 UBool expSignAlways = FALSE;
3078 UBool isCurrency = FALSE;
3080 // The affix is either the prefix or the suffix.
3081 UnicodeString* affix = &prefix;
3083 int32_t start = pos;
3084 UBool isPartDone = FALSE;
3087 for (; !isPartDone && pos < patLen; ) {
3088 // Todo: account for surrogate pairs
3089 ch = pattern.char32At(pos);
3091 case 0: // Pattern proper subpart (between prefix & suffix)
3092 // Process the digits, decimal, and grouping characters. We
3093 // record five pieces of information. We expect the digits
3094 // to occur in the pattern ####00.00####, and we record the
3095 // number of left digits, zero (central) digits, and right
3096 // digits. The position of the last grouping character is
3097 // recorded (should be somewhere within the first two blocks
3098 // of characters), as is the position of the decimal point,
3099 // if any (should be in the zero digits). If there is no
3100 // decimal point, then there should be no right digits.
3101 if (pattern.compare(pos, digitLen, digit) == 0) {
3102 if (zeroDigitCount > 0 || sigDigitCount > 0) {
3107 if (groupingCount >= 0 && decimalPos < 0) {
3111 } else if ((ch >= zeroDigit && ch <= nineDigit) ||
3113 if (digitRightCount > 0) {
3115 debug("Unexpected '0'")
3116 status = U_UNEXPECTED_TOKEN;
3117 syntaxError(pattern,pos,parseError);
3120 if (ch == sigDigit) {
3124 if (ch != zeroDigit && roundingPos < 0) {
3125 roundingPos = digitLeftCount + zeroDigitCount;
3127 if (roundingPos >= 0) {
3128 roundingInc.append((char)(ch - zeroDigit + '0'));
3131 if (groupingCount >= 0 && decimalPos < 0) {
3134 pos += U16_LENGTH(ch);
3135 } else if (pattern.compare(pos, groupSepLen, groupingSeparator) == 0) {
3136 if (decimalPos >= 0) {
3137 // Grouping separator after decimal
3138 debug("Grouping separator after decimal")
3139 status = U_UNEXPECTED_TOKEN;
3140 syntaxError(pattern,pos,parseError);
3143 groupingCount2 = groupingCount;
3146 } else if (pattern.compare(pos, decimalSepLen, decimalSeparator) == 0) {
3147 if (decimalPos >= 0) {
3148 // Multiple decimal separators
3149 debug("Multiple decimal separators")
3150 status = U_MULTIPLE_DECIMAL_SEPARATORS;
3151 syntaxError(pattern,pos,parseError);
3154 // Intentionally incorporate the digitRightCount,
3155 // even though it is illegal for this to be > 0
3156 // at this point. We check pattern syntax below.
3157 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
3158 pos += decimalSepLen;
3160 if (pattern.compare(pos, exponent.length(), exponent) == 0) {
3161 if (expDigits >= 0) {
3162 // Multiple exponential symbols
3163 debug("Multiple exponential symbols")
3164 status = U_MULTIPLE_EXPONENTIAL_SYMBOLS;
3165 syntaxError(pattern,pos,parseError);
3168 if (groupingCount >= 0) {
3169 // Grouping separator in exponential pattern
3170 debug("Grouping separator in exponential pattern")
3171 status = U_MALFORMED_EXPONENTIAL_PATTERN;
3172 syntaxError(pattern,pos,parseError);
3175 pos += exponent.length();
3176 // Check for positive prefix
3178 && pattern.compare(pos, plus.length(), plus) == 0) {
3179 expSignAlways = TRUE;
3180 pos += plus.length();
3182 // Use lookahead to parse out the exponential part of the
3183 // pattern, then jump into suffix subpart.
3185 while (pos < patLen &&
3186 pattern.char32At(pos) == zeroDigit) {
3188 pos += U16_LENGTH(zeroDigit);
3191 // 1. Require at least one mantissa pattern digit
3192 // 2. Disallow "#+ @" in mantissa
3193 // 3. Require at least one exponent pattern digit
3194 if (((digitLeftCount + zeroDigitCount) < 1 &&
3195 (sigDigitCount + digitRightCount) < 1) ||
3196 (sigDigitCount > 0 && digitLeftCount > 0) ||
3198 // Malformed exponential pattern
3199 debug("Malformed exponential pattern")
3200 status = U_MALFORMED_EXPONENTIAL_PATTERN;
3201 syntaxError(pattern,pos,parseError);
3205 // Transition to suffix subpart
3206 subpart = 2; // suffix subpart
3212 case 1: // Prefix subpart
3213 case 2: // Suffix subpart
3214 // Process the prefix / suffix characters
3215 // Process unquoted characters seen in prefix or suffix
3218 // Several syntax characters implicitly begins the
3219 // next subpart if we are in the prefix; otherwise
3220 // they are illegal if unquoted.
3221 if (!pattern.compare(pos, digitLen, digit) ||
3222 !pattern.compare(pos, groupSepLen, groupingSeparator) ||
3223 !pattern.compare(pos, decimalSepLen, decimalSeparator) ||
3224 (ch >= zeroDigit && ch <= nineDigit) ||
3226 if (subpart == 1) { // prefix subpart
3227 subpart = 0; // pattern proper subpart
3228 sub0Start = pos; // Reprocess this character
3231 status = U_UNQUOTED_SPECIAL;
3232 syntaxError(pattern,pos,parseError);
3235 } else if (ch == kCurrencySign) {
3236 affix->append(kQuote); // Encode currency
3237 // Use lookahead to determine if the currency sign is
3239 U_ASSERT(U16_LENGTH(kCurrencySign) == 1);
3240 if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) {
3241 affix->append(kCurrencySign);
3242 ++pos; // Skip over the doubled character
3245 // Fall through to append(ch)
3246 } else if (ch == kQuote) {
3247 // A quote outside quotes indicates either the opening
3248 // quote or two quotes, which is a quote literal. That is,
3249 // we have the first quote in 'do' or o''clock.
3250 U_ASSERT(U16_LENGTH(kQuote) == 1);
3252 if (pos < pattern.length() && pattern[pos] == kQuote) {
3253 affix->append(kQuote); // Encode quote
3254 // Fall through to append(ch)
3256 subpart += 2; // open quote
3259 } else if (pattern.compare(pos, separator.length(), separator) == 0) {
3260 // Don't allow separators in the prefix, and don't allow
3261 // separators in the second pattern (part == 1).
3262 if (subpart == 1 || part == 1) {
3263 // Unexpected separator
3264 debug("Unexpected separator")
3265 status = U_UNEXPECTED_TOKEN;
3266 syntaxError(pattern,pos,parseError);
3270 isPartDone = TRUE; // Go to next part
3271 pos += separator.length();
3273 } else if (pattern.compare(pos, percent.length(), percent) == 0) {
3274 // Next handle characters which are appended directly.
3275 if (multiplier != 1) {
3276 // Too many percent/perMill characters
3277 debug("Too many percent characters")
3278 status = U_MULTIPLE_PERCENT_SYMBOLS;
3279 syntaxError(pattern,pos,parseError);
3282 affix->append(kQuote); // Encode percent/perMill
3283 affix->append(kPatternPercent); // Use unlocalized pattern char
3285 pos += percent.length();
3287 } else if (pattern.compare(pos, perMill.length(), perMill) == 0) {
3288 // Next handle characters which are appended directly.
3289 if (multiplier != 1) {
3290 // Too many percent/perMill characters
3291 debug("Too many perMill characters")
3292 status = U_MULTIPLE_PERMILL_SYMBOLS;
3293 syntaxError(pattern,pos,parseError);
3296 affix->append(kQuote); // Encode percent/perMill
3297 affix->append(kPatternPerMill); // Use unlocalized pattern char
3299 pos += perMill.length();
3301 } else if (pattern.compare(pos, padEscape.length(), padEscape) == 0) {
3302 if (padPos >= 0 || // Multiple pad specifiers
3303 (pos+1) == pattern.length()) { // Nothing after padEscape
3304 debug("Multiple pad specifiers")
3305 status = U_MULTIPLE_PAD_SPECIFIERS;
3306 syntaxError(pattern,pos,parseError);
3310 pos += padEscape.length();
3311 padChar = pattern.char32At(pos);
3312 pos += U16_LENGTH(padChar);
3314 } else if (pattern.compare(pos, minus.length(), minus) == 0) {
3315 affix->append(kQuote); // Encode minus
3316 affix->append(kPatternMinus);
3317 pos += minus.length();
3319 } else if (pattern.compare(pos, plus.length(), plus) == 0) {
3320 affix->append(kQuote); // Encode plus
3321 affix->append(kPatternPlus);
3322 pos += plus.length();
3325 // Unquoted, non-special characters fall through to here, as
3326 // well as other code which needs to append something to the
3329 pos += U16_LENGTH(ch);
3331 case 3: // Prefix subpart, in quote
3332 case 4: // Suffix subpart, in quote
3333 // A quote within quotes indicates either the closing
3334 // quote or two quotes, which is a quote literal. That is,
3335 // we have the second quote in 'do' or 'don''t'.
3338 if (pos < pattern.length() && pattern[pos] == kQuote) {
3339 affix->append(kQuote); // Encode quote
3340 // Fall through to append(ch)
3342 subpart -= 2; // close quote
3347 pos += U16_LENGTH(ch);
3352 if (sub0Limit == 0) {
3353 sub0Limit = pattern.length();
3356 if (sub2Limit == 0) {
3357 sub2Limit = pattern.length();
3360 /* Handle patterns with no '0' pattern character. These patterns
3361 * are legal, but must be recodified to make sense. "##.###" ->
3362 * "#0.###". ".###" -> ".0##".
3364 * We allow patterns of the form "####" to produce a zeroDigitCount
3365 * of zero (got that?); although this seems like it might make it
3366 * possible for format() to produce empty strings, format() checks
3367 * for this condition and outputs a zero digit in this situation.
3368 * Having a zeroDigitCount of zero yields a minimum integer digits
3369 * of zero, which allows proper round-trip patterns. We don't want
3370 * "#" to become "#0" when toPattern() is called (even though that's
3371 * what it really is, semantically).
3373 if (zeroDigitCount == 0 && sigDigitCount == 0 &&
3374 digitLeftCount > 0 && decimalPos >= 0) {
3375 // Handle "###.###" and "###." and ".###"
3378 ++n; // Handle ".###"
3379 digitRightCount = digitLeftCount - n;
3380 digitLeftCount = n - 1;
3384 // Do syntax checking on the digits, decimal points, and quotes.
3385 if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
3387 (sigDigitCount > 0 ||
3388 decimalPos < digitLeftCount ||
3389 decimalPos > (digitLeftCount + zeroDigitCount))) ||
3390 groupingCount == 0 || groupingCount2 == 0 ||
3391 (sigDigitCount > 0 && zeroDigitCount > 0) ||
3393 { // subpart > 2 == unmatched quote
3394 debug("Syntax error")
3395 status = U_PATTERN_SYNTAX_ERROR;
3396 syntaxError(pattern,pos,parseError);
3400 // Make sure pad is at legal position before or after affix.
3402 if (padPos == start) {
3403 padPos = kPadBeforePrefix;
3404 } else if (padPos+2 == sub0Start) {
3405 padPos = kPadAfterPrefix;
3406 } else if (padPos == sub0Limit) {
3407 padPos = kPadBeforeSuffix;
3408 } else if (padPos+2 == sub2Limit) {
3409 padPos = kPadAfterSuffix;
3411 // Illegal pad position
3412 debug("Illegal pad position")
3413 status = U_ILLEGAL_PAD_POSITION;
3414 syntaxError(pattern,pos,parseError);
3420 delete fPosPrefixPattern;
3421 delete fPosSuffixPattern;
3422 delete fNegPrefixPattern;
3423 delete fNegSuffixPattern;
3424 fPosPrefixPattern = new UnicodeString(prefix);
3426 if (fPosPrefixPattern == 0) {
3427 status = U_MEMORY_ALLOCATION_ERROR;
3430 fPosSuffixPattern = new UnicodeString(suffix);
3432 if (fPosSuffixPattern == 0) {
3433 status = U_MEMORY_ALLOCATION_ERROR;
3434 delete fPosPrefixPattern;
3437 fNegPrefixPattern = 0;
3438 fNegSuffixPattern = 0;
3440 fUseExponentialNotation = (expDigits >= 0);
3441 if (fUseExponentialNotation) {
3442 fMinExponentDigits = expDigits;
3444 fExponentSignAlwaysShown = expSignAlways;
3445 fIsCurrencyFormat = isCurrency;
3446 int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
3447 // The effectiveDecimalPos is the position the decimal is at or
3448 // would be at if there is no decimal. Note that if
3449 // decimalPos<0, then digitTotalCount == digitLeftCount +
3451 int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
3452 UBool isSigDig = (sigDigitCount > 0);
3453 setSignificantDigitsUsed(isSigDig);
3455 setMinimumSignificantDigits(sigDigitCount);
3456 setMaximumSignificantDigits(sigDigitCount + digitRightCount);
3458 int32_t minInt = effectiveDecimalPos - digitLeftCount;
3459 setMinimumIntegerDigits(minInt);
3460 setMaximumIntegerDigits(fUseExponentialNotation
3461 ? digitLeftCount + getMinimumIntegerDigits()
3462 : kDoubleIntegerDigits);
3463 setMaximumFractionDigits(decimalPos >= 0
3464 ? (digitTotalCount - decimalPos) : 0);
3465 setMinimumFractionDigits(decimalPos >= 0
3466 ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
3468 setGroupingUsed(groupingCount > 0);
3469 fGroupingSize = (groupingCount > 0) ? groupingCount : 0;
3470 fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
3471 ? groupingCount2 : 0;
3472 fMultiplier = multiplier;
3473 setDecimalSeparatorAlwaysShown(decimalPos == 0
3474 || decimalPos == digitTotalCount);
3476 fPadPosition = (EPadPosition) padPos;
3477 // To compute the format width, first set up sub0Limit -
3478 // sub0Start. Add in prefix/suffix length later.
3480 // fFormatWidth = prefix.length() + suffix.length() +
3481 // sub0Limit - sub0Start;
3482 fFormatWidth = sub0Limit - sub0Start;
3487 if (roundingPos >= 0) {
3488 roundingInc.fDecimalAt = effectiveDecimalPos - roundingPos;
3489 if (fRoundingIncrement != NULL) {
3490 *fRoundingIncrement = roundingInc;
3492 fRoundingIncrement = new DigitList(roundingInc);
3494 if (fRoundingIncrement == 0) {
3495 status = U_MEMORY_ALLOCATION_ERROR;
3496 delete fPosPrefixPattern;
3497 delete fPosSuffixPattern;
3501 fRoundingDouble = fRoundingIncrement->getDouble();
3502 fRoundingMode = kRoundHalfEven;
3504 setRoundingIncrement(0.0);
3507 fNegPrefixPattern = new UnicodeString(prefix);
3509 if (fNegPrefixPattern == 0) {
3510 status = U_MEMORY_ALLOCATION_ERROR;
3513 fNegSuffixPattern = new UnicodeString(suffix);
3515 if (fNegSuffixPattern == 0) {
3516 delete fNegPrefixPattern;
3517 status = U_MEMORY_ALLOCATION_ERROR;
3523 if (pattern.length() == 0) {
3524 delete fNegPrefixPattern;
3525 delete fNegSuffixPattern;
3526 fNegPrefixPattern = NULL;
3527 fNegSuffixPattern = NULL;
3528 if (fPosPrefixPattern != NULL) {
3529 fPosPrefixPattern->remove();
3531 fPosPrefixPattern = new UnicodeString();
3533 if (fPosPrefixPattern == 0) {
3534 status = U_MEMORY_ALLOCATION_ERROR;
3538 if (fPosSuffixPattern != NULL) {
3539 fPosSuffixPattern->remove();
3541 fPosSuffixPattern = new UnicodeString();
3543 if (fPosSuffixPattern == 0) {
3544 delete fPosPrefixPattern;
3545 status = U_MEMORY_ALLOCATION_ERROR;
3550 setMinimumIntegerDigits(0);
3551 setMaximumIntegerDigits(kDoubleIntegerDigits);
3552 setMinimumFractionDigits(0);
3553 setMaximumFractionDigits(kDoubleFractionDigits);
3555 fUseExponentialNotation = FALSE;
3556 fIsCurrencyFormat = FALSE;
3557 setGroupingUsed(FALSE);
3561 setDecimalSeparatorAlwaysShown(FALSE);
3563 setRoundingIncrement(0.0);
3566 // If there was no negative pattern, or if the negative pattern is
3567 // identical to the positive pattern, then prepend the minus sign to the
3568 // positive pattern to form the negative pattern.
3569 if (fNegPrefixPattern == NULL ||
3570 (*fNegPrefixPattern == *fPosPrefixPattern
3571 && *fNegSuffixPattern == *fPosSuffixPattern)) {
3572 _copy_us_ptr(&fNegSuffixPattern, fPosSuffixPattern);
3573 if (fNegPrefixPattern == NULL) {
3574 fNegPrefixPattern = new UnicodeString();
3576 if (fNegPrefixPattern == 0) {
3577 status = U_MEMORY_ALLOCATION_ERROR;
3581 fNegPrefixPattern->remove();
3583 fNegPrefixPattern->append(kQuote).append(kPatternMinus)
3584 .append(*fPosPrefixPattern);
3588 s.append("\"").append(pattern).append("\"->");
3592 if (fFormatWidth > 0) {
3593 // Finish computing format width (see above)
3594 fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length();
3599 * Sets the maximum number of digits allowed in the integer portion of a
3600 * number. This override limits the integer digit count to 309.
3601 * @see NumberFormat#setMaximumIntegerDigits
3603 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
3604 NumberFormat::setMaximumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
3608 * Sets the minimum number of digits allowed in the integer portion of a
3609 * number. This override limits the integer digit count to 309.
3610 * @see NumberFormat#setMinimumIntegerDigits
3612 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
3613 NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
3617 * Sets the maximum number of digits allowed in the fraction portion of a
3618 * number. This override limits the fraction digit count to 340.
3619 * @see NumberFormat#setMaximumFractionDigits
3621 void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
3622 NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits));
3626 * Sets the minimum number of digits allowed in the fraction portion of a
3627 * number. This override limits the fraction digit count to 340.
3628 * @see NumberFormat#setMinimumFractionDigits
3630 void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
3631 NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits));
3634 int32_t DecimalFormat::getMinimumSignificantDigits() const {
3635 return fMinSignificantDigits;
3638 int32_t DecimalFormat::getMaximumSignificantDigits() const {
3639 return fMaxSignificantDigits;
3642 void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
3646 // pin max sig dig to >= min
3647 int32_t max = _max(fMaxSignificantDigits, min);
3648 fMinSignificantDigits = min;
3649 fMaxSignificantDigits = max;
3652 void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
3656 // pin min sig dig to 1..max
3657 U_ASSERT(fMinSignificantDigits >= 1);
3658 int32_t min = _min(fMinSignificantDigits, max);
3659 fMinSignificantDigits = min;
3660 fMaxSignificantDigits = max;
3663 UBool DecimalFormat::areSignificantDigitsUsed() const {
3664 return fUseSignificantDigits;
3667 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
3668 fUseSignificantDigits = useSignificantDigits;
3671 void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
3672 // If we are a currency format, then modify our affixes to
3673 // encode the currency symbol for the given currency in our
3674 // locale, and adjust the decimal digits and rounding for the
3677 // Note: The code is ordered so that this object is *not changed*
3678 // until we are sure we are going to succeed.
3680 // NULL or empty currency is *legal* and indicates no currency.
3681 UBool isCurr = (theCurrency && *theCurrency);
3683 double rounding = 0.0;
3685 if (fIsCurrencyFormat && isCurr) {
3686 rounding = ucurr_getRoundingIncrement(theCurrency, &ec);
3687 frac = ucurr_getDefaultFractionDigits(theCurrency, &ec);
3690 NumberFormat::setCurrency(theCurrency, ec);
3691 if (U_FAILURE(ec)) return;
3693 if (fIsCurrencyFormat) {
3694 // NULL or empty currency is *legal* and indicates no currency.
3696 setRoundingIncrement(rounding);
3697 setMinimumFractionDigits(frac);
3698 setMaximumFractionDigits(frac);
3704 // Deprecated variant with no UErrorCode parameter
3705 void DecimalFormat::setCurrency(const UChar* theCurrency) {
3706 UErrorCode ec = U_ZERO_ERROR;
3707 setCurrency(theCurrency, ec);
3710 void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& /*ec*/) const {
3711 const UChar* c = getCurrency();
3713 const UnicodeString &intl =
3714 fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
3715 c = intl.getBuffer(); // ok for intl to go out of scope
3717 u_strncpy(result, c, 3);
3722 * Return the number of fraction digits to display, or the total
3723 * number of digits for significant digit formats and exponential
3727 DecimalFormat::precision(UBool isIntegral) const {
3728 if (areSignificantDigitsUsed()) {
3729 return getMaximumSignificantDigits();
3730 } else if (fUseExponentialNotation) {
3731 return getMinimumIntegerDigits() + getMaximumFractionDigits();
3733 return isIntegral ? 0 : getMaximumFractionDigits();
3739 #endif /* #if !UCONFIG_NO_FORMATTING */