2 *******************************************************************************
3 * Copyright (C) 1997-2004, 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
);
341 * Sets our currency to be the default currency for the given locale.
343 void DecimalFormat::setCurrencyForLocale(const char* locale
, UErrorCode
& ec
) {
344 const UChar
* c
= NULL
;
346 // Trap an error in mapping locale to currency. If we can't
347 // map, then don't fail and set the currency to "".
348 UErrorCode ec2
= U_ZERO_ERROR
;
350 ucurr_forLocale(locale
, c
, 4, &ec2
);
355 //------------------------------------------------------------------------------
357 DecimalFormat::~DecimalFormat()
359 // delete fDigitList;
360 delete fPosPrefixPattern
;
361 delete fPosSuffixPattern
;
362 delete fNegPrefixPattern
;
363 delete fNegSuffixPattern
;
364 delete fCurrencyChoice
;
366 delete fRoundingIncrement
;
369 //------------------------------------------------------------------------------
372 DecimalFormat::DecimalFormat(const DecimalFormat
&source
)
373 : NumberFormat(source
),
375 fPosPrefixPattern(NULL
),
376 fPosSuffixPattern(NULL
),
377 fNegPrefixPattern(NULL
),
378 fNegSuffixPattern(NULL
),
379 fCurrencyChoice(NULL
),
381 fRoundingIncrement(NULL
)
386 //------------------------------------------------------------------------------
387 // assignment operator
388 // Note that fDigitList is not considered a significant part of the
389 // DecimalFormat because it's used as a buffer to process the numbers.
391 static void _copy_us_ptr(UnicodeString
** pdest
, const UnicodeString
* source
) {
392 if (source
== NULL
) {
395 } else if (*pdest
== NULL
) {
396 *pdest
= new UnicodeString(*source
);
403 DecimalFormat::operator=(const DecimalFormat
& rhs
)
406 NumberFormat::operator=(rhs
);
407 fPositivePrefix
= rhs
.fPositivePrefix
;
408 fPositiveSuffix
= rhs
.fPositiveSuffix
;
409 fNegativePrefix
= rhs
.fNegativePrefix
;
410 fNegativeSuffix
= rhs
.fNegativeSuffix
;
411 _copy_us_ptr(&fPosPrefixPattern
, rhs
.fPosPrefixPattern
);
412 _copy_us_ptr(&fPosSuffixPattern
, rhs
.fPosSuffixPattern
);
413 _copy_us_ptr(&fNegPrefixPattern
, rhs
.fNegPrefixPattern
);
414 _copy_us_ptr(&fNegSuffixPattern
, rhs
.fNegSuffixPattern
);
415 if (rhs
.fCurrencyChoice
== 0) {
416 delete fCurrencyChoice
;
419 fCurrencyChoice
= (ChoiceFormat
*) rhs
.fCurrencyChoice
->clone();
421 if(rhs
.fRoundingIncrement
== NULL
) {
422 delete fRoundingIncrement
;
423 fRoundingIncrement
= NULL
;
425 else if(fRoundingIncrement
== NULL
) {
426 fRoundingIncrement
= new DigitList(*rhs
.fRoundingIncrement
);
429 *fRoundingIncrement
= *rhs
.fRoundingIncrement
;
431 fRoundingDouble
= rhs
.fRoundingDouble
;
432 fRoundingMode
= rhs
.fRoundingMode
;
433 fMultiplier
= rhs
.fMultiplier
;
434 fGroupingSize
= rhs
.fGroupingSize
;
435 fGroupingSize2
= rhs
.fGroupingSize2
;
436 fDecimalSeparatorAlwaysShown
= rhs
.fDecimalSeparatorAlwaysShown
;
437 if(fSymbols
== NULL
) {
438 fSymbols
= new DecimalFormatSymbols(*rhs
.fSymbols
);
440 *fSymbols
= *rhs
.fSymbols
;
442 fUseExponentialNotation
= rhs
.fUseExponentialNotation
;
443 fExponentSignAlwaysShown
= rhs
.fExponentSignAlwaysShown
;
444 /*Bertrand A. D. Update 98.03.17*/
445 fIsCurrencyFormat
= rhs
.fIsCurrencyFormat
;
447 fMinExponentDigits
= rhs
.fMinExponentDigits
;
448 // if (fDigitList == NULL)
449 // fDigitList = new DigitList();
452 fFormatWidth
= rhs
.fFormatWidth
;
454 fPadPosition
= rhs
.fPadPosition
;
456 fMinSignificantDigits
= rhs
.fMinSignificantDigits
;
457 fMaxSignificantDigits
= rhs
.fMaxSignificantDigits
;
458 fUseSignificantDigits
= rhs
.fUseSignificantDigits
;
463 //------------------------------------------------------------------------------
466 DecimalFormat::operator==(const Format
& that
) const
471 // NumberFormat::operator== guarantees this cast is safe
472 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
475 // This code makes it easy to determine why two format objects that should
478 if (!NumberFormat::operator==(that
)) {
479 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
480 debug("NumberFormat::!=");
482 if (!((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
483 fPositivePrefix
== other
->fPositivePrefix
)
484 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
485 *fPosPrefixPattern
== *other
->fPosPrefixPattern
))) {
486 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
487 debug("Pos Prefix !=");
489 if (!((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
490 fPositiveSuffix
== other
->fPositiveSuffix
)
491 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
492 *fPosSuffixPattern
== *other
->fPosSuffixPattern
))) {
493 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
494 debug("Pos Suffix !=");
496 if (!((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
497 fNegativePrefix
== other
->fNegativePrefix
)
498 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
499 *fNegPrefixPattern
== *other
->fNegPrefixPattern
))) {
500 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
501 debug("Neg Prefix ");
502 if (fNegPrefixPattern
== NULL
) {
504 debugout(fNegativePrefix
);
507 debugout(*fNegPrefixPattern
);
510 if (other
->fNegPrefixPattern
== NULL
) {
512 debugout(other
->fNegativePrefix
);
515 debugout(*other
->fNegPrefixPattern
);
518 if (!((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
519 fNegativeSuffix
== other
->fNegativeSuffix
)
520 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
521 *fNegSuffixPattern
== *other
->fNegSuffixPattern
))) {
522 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
523 debug("Neg Suffix ");
524 if (fNegSuffixPattern
== NULL
) {
526 debugout(fNegativeSuffix
);
529 debugout(*fNegSuffixPattern
);
532 if (other
->fNegSuffixPattern
== NULL
) {
534 debugout(other
->fNegativeSuffix
);
537 debugout(*other
->fNegSuffixPattern
);
540 if (!((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
541 || (fRoundingIncrement
!= NULL
&&
542 other
->fRoundingIncrement
!= NULL
&&
543 *fRoundingIncrement
== *other
->fRoundingIncrement
))) {
544 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
545 debug("Rounding Increment !=");
547 if (fMultiplier
!= other
->fMultiplier
) {
548 if (first
) { printf("[ "); first
= FALSE
; }
549 printf("Multiplier %ld != %ld", fMultiplier
, other
->fMultiplier
);
551 if (fGroupingSize
!= other
->fGroupingSize
) {
552 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
553 printf("Grouping Size %ld != %ld", fGroupingSize
, other
->fGroupingSize
);
555 if (fGroupingSize2
!= other
->fGroupingSize2
) {
556 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
557 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2
, other
->fGroupingSize2
);
559 if (fDecimalSeparatorAlwaysShown
!= other
->fDecimalSeparatorAlwaysShown
) {
560 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
561 printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown
, other
->fDecimalSeparatorAlwaysShown
);
563 if (fUseExponentialNotation
!= other
->fUseExponentialNotation
) {
564 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
567 if (!(!fUseExponentialNotation
||
568 fMinExponentDigits
!= other
->fMinExponentDigits
)) {
569 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
570 debug("Exp Digits !=");
572 if (*fSymbols
!= *(other
->fSymbols
)) {
573 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
576 // TODO Add debug stuff for significant digits here
577 if (!first
) { printf(" ]"); }
580 return (NumberFormat::operator==(that
) &&
581 ((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
582 fPositivePrefix
== other
->fPositivePrefix
)
583 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
584 *fPosPrefixPattern
== *other
->fPosPrefixPattern
)) &&
585 ((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
586 fPositiveSuffix
== other
->fPositiveSuffix
)
587 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
588 *fPosSuffixPattern
== *other
->fPosSuffixPattern
)) &&
589 ((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
590 fNegativePrefix
== other
->fNegativePrefix
)
591 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
592 *fNegPrefixPattern
== *other
->fNegPrefixPattern
)) &&
593 ((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
594 fNegativeSuffix
== other
->fNegativeSuffix
)
595 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
596 *fNegSuffixPattern
== *other
->fNegSuffixPattern
)) &&
597 ((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
598 || (fRoundingIncrement
!= NULL
&&
599 other
->fRoundingIncrement
!= NULL
&&
600 *fRoundingIncrement
== *other
->fRoundingIncrement
)) &&
601 fMultiplier
== other
->fMultiplier
&&
602 fGroupingSize
== other
->fGroupingSize
&&
603 fGroupingSize2
== other
->fGroupingSize2
&&
604 fDecimalSeparatorAlwaysShown
== other
->fDecimalSeparatorAlwaysShown
&&
605 fUseExponentialNotation
== other
->fUseExponentialNotation
&&
606 (!fUseExponentialNotation
||
607 fMinExponentDigits
== other
->fMinExponentDigits
) &&
608 *fSymbols
== *(other
->fSymbols
) &&
609 fUseSignificantDigits
== other
->fUseSignificantDigits
&&
610 (!fUseSignificantDigits
||
611 (fMinSignificantDigits
== other
->fMinSignificantDigits
&&
612 fMaxSignificantDigits
== other
->fMaxSignificantDigits
)));
615 //------------------------------------------------------------------------------
618 DecimalFormat::clone() const
620 return new DecimalFormat(*this);
623 //------------------------------------------------------------------------------
626 DecimalFormat::format(int32_t number
,
627 UnicodeString
& appendTo
,
628 FieldPosition
& fieldPosition
) const
630 return format((int64_t)number
, appendTo
, fieldPosition
);
633 //------------------------------------------------------------------------------
636 DecimalFormat::format(int64_t number
,
637 UnicodeString
& appendTo
,
638 FieldPosition
& fieldPosition
) const
642 // Clears field positions.
643 fieldPosition
.setBeginIndex(0);
644 fieldPosition
.setEndIndex(0);
646 // If we are to do rounding, we need to move into the BigDecimal
647 // domain in order to do divide/multiply correctly.
649 // In general, long values always represent real finite numbers, so
650 // we don't have to check for +/- Infinity or NaN. However, there
651 // is one case we have to be careful of: The multiplier can push
652 // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
653 // check for this before multiplying, and if it happens we use doubles
654 // instead, trading off accuracy for range.
655 if (fRoundingIncrement
!= NULL
656 || (fMultiplier
!= 0 && (number
> (U_INT64_MAX
/ fMultiplier
)
657 || number
< (U_INT64_MIN
/ fMultiplier
))))
659 digits
.set(((double)number
) * fMultiplier
,
661 !fUseExponentialNotation
&& !areSignificantDigitsUsed());
665 digits
.set(number
* fMultiplier
, precision(TRUE
));
668 return subformat(appendTo
, fieldPosition
, digits
, TRUE
);
671 //------------------------------------------------------------------------------
674 DecimalFormat::format( double number
,
675 UnicodeString
& appendTo
,
676 FieldPosition
& fieldPosition
) const
678 // Clears field positions.
679 fieldPosition
.setBeginIndex(0);
680 fieldPosition
.setEndIndex(0);
682 // Special case for NaN, sets the begin and end index to be the
683 // the string length of localized name of NaN.
684 if (uprv_isNaN(number
))
686 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
687 fieldPosition
.setBeginIndex(appendTo
.length());
689 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
691 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
692 fieldPosition
.setEndIndex(appendTo
.length());
694 addPadding(appendTo
, fieldPosition
, 0, 0);
698 /* Detecting whether a double is negative is easy with the exception of
699 * the value -0.0. This is a double which has a zero mantissa (and
700 * exponent), but a negative sign bit. It is semantically distinct from
701 * a zero with a positive sign bit, and this distinction is important
702 * to certain kinds of computations. However, it's a little tricky to
703 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
704 * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
705 * -Infinity. Proper detection of -0.0 is needed to deal with the
706 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
708 UBool isNegative
= uprv_isNegative(number
);
710 // Do this BEFORE checking to see if value is infinite! Sets the
711 // begin and end index to be length of the string composed of
712 // localized name of Infinite and the positive/negative localized
715 number
*= fMultiplier
;
717 // Apply rounding after multiplier
718 if (fRoundingIncrement
!= NULL
) {
719 if (isNegative
) // For rounding in the correct direction
721 number
= fRoundingDouble
722 * round(number
/ fRoundingDouble
, fRoundingMode
, isNegative
);
727 // Special case for INFINITE,
728 if (uprv_isInfinite(number
))
730 int32_t prefixLen
= appendAffix(appendTo
, number
, isNegative
, TRUE
);
732 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
733 fieldPosition
.setBeginIndex(appendTo
.length());
735 appendTo
+= getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
737 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
738 fieldPosition
.setEndIndex(appendTo
.length());
740 int32_t suffixLen
= appendAffix(appendTo
, number
, isNegative
, FALSE
);
742 addPadding(appendTo
, fieldPosition
, prefixLen
, suffixLen
);
748 // This detects negativity too.
749 if (fRoundingIncrement
== NULL
) {
750 // If we did not round in binary space, round in decimal space
751 digits
.fRoundingMode
= fRoundingMode
;
753 digits
.set(number
, precision(FALSE
),
754 !fUseExponentialNotation
&& !areSignificantDigitsUsed());
756 return subformat(appendTo
, fieldPosition
, digits
, FALSE
);
760 * Round a double value to the nearest integer according to the
762 * @param a the absolute value of the number to be rounded
763 * @param mode a BigDecimal rounding mode
764 * @param isNegative true if the number to be rounded is negative
765 * @return the absolute value of the rounded result
767 double DecimalFormat::round(double a
, ERoundingMode mode
, UBool isNegative
) {
770 return isNegative
? uprv_floor(a
) : uprv_ceil(a
);
772 return isNegative
? uprv_ceil(a
) : uprv_floor(a
);
774 return uprv_floor(a
);
779 double f
= uprv_floor(a
);
780 if ((a
- f
) != 0.5) {
781 return uprv_floor(a
+ 0.5);
784 return (g
== uprv_floor(g
)) ? f
: (f
+ 1.0);
787 return ((a
- uprv_floor(a
)) <= 0.5) ? uprv_floor(a
) : uprv_ceil(a
);
789 return ((a
- uprv_floor(a
)) < 0.5) ? uprv_floor(a
) : uprv_ceil(a
);
795 DecimalFormat::format( const Formattable
& obj
,
796 UnicodeString
& appendTo
,
797 FieldPosition
& fieldPosition
,
798 UErrorCode
& status
) const
800 return NumberFormat::format(obj
, appendTo
, fieldPosition
, status
);
804 * Return true if a grouping separator belongs at the given
805 * position, based on whether grouping is in use and the values of
806 * the primary and secondary grouping interval.
807 * @param pos the number of integer digits to the right of
808 * the current position. Zero indicates the position after the
809 * rightmost integer digit.
810 * @return true if a grouping character belongs at the current
813 UBool
DecimalFormat::isGroupingPosition(int32_t pos
) const {
814 UBool result
= FALSE
;
815 if (isGroupingUsed() && (pos
> 0) && (fGroupingSize
> 0)) {
816 if ((fGroupingSize2
> 0) && (pos
> fGroupingSize
)) {
817 result
= ((pos
- fGroupingSize
) % fGroupingSize2
) == 0;
819 result
= pos
% fGroupingSize
== 0;
825 //------------------------------------------------------------------------------
828 * Complete the formatting of a finite number. On entry, the fDigitList must
829 * be filled in with the correct digits.
832 DecimalFormat::subformat(UnicodeString
& appendTo
,
833 FieldPosition
& fieldPosition
,
835 UBool isInteger
) const
837 // Gets the localized zero Unicode character.
838 UChar32 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
839 int32_t zeroDelta
= zero
- '0'; // '0' is the DigitList representation of zero
840 const UnicodeString
*grouping
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
841 const UnicodeString
*decimal
;
842 if(fIsCurrencyFormat
) {
843 decimal
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
845 decimal
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
847 UBool useSigDig
= areSignificantDigitsUsed();
848 int32_t maxIntDig
= getMaximumIntegerDigits();
849 int32_t minIntDig
= getMinimumIntegerDigits();
851 /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
852 * format as zero. This allows sensible computations and preserves
853 * relations such as signum(1/x) = signum(x), where x is +Infinity or
854 * -Infinity. Prior to this fix, we always formatted zero values as if
855 * they were positive. Liu 7/6/98.
859 digits
.fDecimalAt
= digits
.fCount
= 0; // Normalize
862 // Appends the prefix.
863 double doubleValue
= digits
.getDouble();
864 int32_t prefixLen
= appendAffix(appendTo
, doubleValue
, !digits
.fIsPositive
, TRUE
);
866 if (fUseExponentialNotation
)
868 // Record field information for caller.
869 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
871 fieldPosition
.setBeginIndex(appendTo
.length());
872 fieldPosition
.setEndIndex(-1);
874 else if (fieldPosition
.getField() == NumberFormat::kFractionField
)
876 fieldPosition
.setBeginIndex(-1);
879 int32_t minFracDig
= 0;
881 maxIntDig
= minIntDig
= 1;
882 minFracDig
= getMinimumSignificantDigits() - 1;
884 minFracDig
= getMinimumFractionDigits();
885 if (maxIntDig
> kMaxScientificIntegerDigits
) {
887 if (maxIntDig
< minIntDig
) {
888 maxIntDig
= minIntDig
;
891 if (maxIntDig
> minIntDig
) {
896 // Minimum integer digits are handled in exponential format by
897 // adjusting the exponent. For example, 0.01234 with 3 minimum
898 // integer digits is "123.4E-4".
900 // Maximum integer digits are interpreted as indicating the
901 // repeating range. This is useful for engineering notation, in
902 // which the exponent is restricted to a multiple of 3. For
903 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
904 // If maximum integer digits are defined and are larger than
905 // minimum integer digits, then minimum integer digits are
907 int32_t exponent
= digits
.fDecimalAt
;
908 if (maxIntDig
> 1 && maxIntDig
!= minIntDig
) {
909 // A exponent increment is defined; adjust to it.
910 exponent
= (exponent
> 0) ? (exponent
- 1) / maxIntDig
911 : (exponent
/ maxIntDig
) - 1;
912 exponent
*= maxIntDig
;
914 // No exponent increment is defined; use minimum integer digits.
915 // If none is specified, as in "#E0", generate 1 integer digit.
916 exponent
-= (minIntDig
> 0 || minFracDig
> 0)
920 // We now output a minimum number of digits, and more if there
921 // are more digits, up to the maximum number of digits. We
922 // place the decimal point after the "integer" digits, which
923 // are the first (decimalAt - exponent) digits.
924 int32_t minimumDigits
= minIntDig
+ minFracDig
;
925 // The number of integer digits is handled specially if the number
926 // is zero, since then there may be no digits.
927 int32_t integerDigits
= digits
.isZero() ? minIntDig
:
928 digits
.fDecimalAt
- exponent
;
929 int32_t totalDigits
= digits
.fCount
;
930 if (minimumDigits
> totalDigits
)
931 totalDigits
= minimumDigits
;
932 if (integerDigits
> totalDigits
)
933 totalDigits
= integerDigits
;
935 // totalDigits records total number of digits needs to be processed
937 for (i
=0; i
<totalDigits
; ++i
)
939 if (i
== integerDigits
)
941 // Record field information for caller.
942 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
943 fieldPosition
.setEndIndex(appendTo
.length());
945 appendTo
+= *decimal
;
947 // Record field information for caller.
948 if (fieldPosition
.getField() == NumberFormat::kFractionField
)
949 fieldPosition
.setBeginIndex(appendTo
.length());
951 // Restores the digit character or pads the buffer with zeros.
952 UChar32 c
= (UChar32
)((i
< digits
.fCount
) ?
953 (digits
.fDigits
[i
] + zeroDelta
) :
958 // Record field information
959 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
961 if (fieldPosition
.getEndIndex() < 0)
962 fieldPosition
.setEndIndex(appendTo
.length());
964 else if (fieldPosition
.getField() == NumberFormat::kFractionField
)
966 if (fieldPosition
.getBeginIndex() < 0)
967 fieldPosition
.setBeginIndex(appendTo
.length());
968 fieldPosition
.setEndIndex(appendTo
.length());
971 // The exponent is output using the pattern-specified minimum
972 // exponent digits. There is no maximum limit to the exponent
973 // digits, since truncating the exponent would appendTo in an
974 // unacceptable inaccuracy.
975 appendTo
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
977 // For zero values, we force the exponent to zero. We
978 // must do this here, and not earlier, because the value
979 // is used to determine integer digit count above.
984 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
985 } else if (fExponentSignAlwaysShown
) {
986 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
990 expDigits
.set(exponent
);
992 int expDig
= fMinExponentDigits
;
993 if (fUseExponentialNotation
&& expDig
< 1) {
996 for (i
=expDigits
.fDecimalAt
; i
<expDig
; ++i
)
999 for (i
=0; i
<expDigits
.fDecimalAt
; ++i
)
1001 UChar32 c
= (UChar32
)((i
< expDigits
.fCount
) ?
1002 (expDigits
.fDigits
[i
] + zeroDelta
) : zero
);
1006 else // Not using exponential notation
1008 // Record field information for caller.
1009 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
1010 fieldPosition
.setBeginIndex(appendTo
.length());
1012 int32_t sigCount
= 0;
1013 int32_t minSigDig
= getMinimumSignificantDigits();
1014 int32_t maxSigDig
= getMaximumSignificantDigits();
1017 maxSigDig
= INT32_MAX
;
1020 // Output the integer portion. Here 'count' is the total
1021 // number of integer digits we will display, including both
1022 // leading zeros required to satisfy getMinimumIntegerDigits,
1023 // and actual digits present in the number.
1024 int32_t count
= useSigDig
?
1025 _max(1, digits
.fDecimalAt
) : minIntDig
;
1026 if (digits
.fDecimalAt
> 0 && count
< digits
.fDecimalAt
) {
1027 count
= digits
.fDecimalAt
;
1030 // Handle the case where getMaximumIntegerDigits() is smaller
1031 // than the real number of integer digits. If this is so, we
1032 // output the least significant max integer digits. For example,
1033 // the value 1997 printed with 2 max integer digits is just "97".
1035 int32_t digitIndex
= 0; // Index into digitList.fDigits[]
1036 if (count
> maxIntDig
&& maxIntDig
>= 0) {
1038 digitIndex
= digits
.fDecimalAt
- count
;
1041 int32_t sizeBeforeIntegerPart
= appendTo
.length();
1044 for (i
=count
-1; i
>=0; --i
)
1046 if (i
< digits
.fDecimalAt
&& digitIndex
< digits
.fCount
&&
1047 sigCount
< maxSigDig
) {
1048 // Output a real digit
1049 appendTo
+= ((UChar32
)(digits
.fDigits
[digitIndex
++] + zeroDelta
));
1054 // Output a zero (leading or trailing)
1061 // Output grouping separator if necessary.
1062 if (isGroupingPosition(i
)) {
1063 appendTo
.append(*grouping
);
1067 // Record field information for caller.
1068 if (fieldPosition
.getField() == NumberFormat::kIntegerField
)
1069 fieldPosition
.setEndIndex(appendTo
.length());
1071 // Determine whether or not there are any printable fractional
1072 // digits. If we've used up the digits we know there aren't.
1073 UBool fractionPresent
= (!isInteger
&& digitIndex
< digits
.fCount
) ||
1074 (useSigDig
? (sigCount
< minSigDig
) : (getMinimumFractionDigits() > 0));
1076 // If there is no fraction present, and we haven't printed any
1077 // integer digits, then print a zero. Otherwise we won't print
1078 // _any_ digits, and we won't be able to parse this string.
1079 if (!fractionPresent
&& appendTo
.length() == sizeBeforeIntegerPart
)
1082 // Output the decimal separator if we always do so.
1083 if (fDecimalSeparatorAlwaysShown
|| fractionPresent
)
1084 appendTo
+= *decimal
;
1086 // Record field information for caller.
1087 if (fieldPosition
.getField() == NumberFormat::kFractionField
)
1088 fieldPosition
.setBeginIndex(appendTo
.length());
1090 count
= useSigDig
? INT32_MAX
: getMaximumFractionDigits();
1091 if (useSigDig
&& (sigCount
== maxSigDig
||
1092 (sigCount
>= minSigDig
&& digitIndex
== digits
.fCount
))) {
1096 for (i
=0; i
< count
; ++i
) {
1097 // Here is where we escape from the loop. We escape
1098 // if we've output the maximum fraction digits
1099 // (specified in the for expression above). We also
1100 // stop when we've output the minimum digits and
1101 // either: we have an integer, so there is no
1102 // fractional stuff to display, or we're out of
1103 // significant digits.
1104 if (!useSigDig
&& i
>= getMinimumFractionDigits() &&
1105 (isInteger
|| digitIndex
>= digits
.fCount
)) {
1109 // Output leading fractional zeros. These are zeros
1110 // that come after the decimal but before any
1111 // significant digits. These are only output if
1112 // abs(number being formatted) < 1.0.
1113 if (-1-i
> (digits
.fDecimalAt
-1)) {
1118 // Output a digit, if we have any precision left, or a
1119 // zero if we don't. We don't want to output noise digits.
1120 if (!isInteger
&& digitIndex
< digits
.fCount
) {
1121 appendTo
+= ((UChar32
)(digits
.fDigits
[digitIndex
++] + zeroDelta
));
1126 // If we reach the maximum number of significant
1127 // digits, or if we output all the real digits and
1128 // reach the minimum, then we are done.
1131 (sigCount
== maxSigDig
||
1132 (digitIndex
== digits
.fCount
&& sigCount
>= minSigDig
))) {
1137 // Record field information for caller.
1138 if (fieldPosition
.getField() == NumberFormat::kFractionField
)
1139 fieldPosition
.setEndIndex(appendTo
.length());
1142 int32_t suffixLen
= appendAffix(appendTo
, doubleValue
, !digits
.fIsPositive
, FALSE
);
1144 addPadding(appendTo
, fieldPosition
, prefixLen
, suffixLen
);
1149 * Inserts the character fPad as needed to expand result to fFormatWidth.
1150 * @param result the string to be padded
1152 void DecimalFormat::addPadding(UnicodeString
& appendTo
,
1153 FieldPosition
& fieldPosition
,
1155 int32_t suffixLen
) const
1157 if (fFormatWidth
> 0) {
1158 int32_t len
= fFormatWidth
- appendTo
.length();
1160 UnicodeString padding
;
1161 for (int32_t i
=0; i
<len
; ++i
) {
1164 switch (fPadPosition
) {
1165 case kPadAfterPrefix
:
1166 appendTo
.insert(prefixLen
, padding
);
1168 case kPadBeforePrefix
:
1169 appendTo
.insert(0, padding
);
1171 case kPadBeforeSuffix
:
1172 appendTo
.insert(appendTo
.length() - suffixLen
, padding
);
1174 case kPadAfterSuffix
:
1175 appendTo
+= padding
;
1178 if (fPadPosition
== kPadBeforePrefix
||
1179 fPadPosition
== kPadAfterPrefix
) {
1180 fieldPosition
.setBeginIndex(len
+ fieldPosition
.getBeginIndex());
1181 fieldPosition
.setEndIndex(len
+ fieldPosition
.getEndIndex());
1187 //------------------------------------------------------------------------------
1190 DecimalFormat::parse(const UnicodeString
& text
,
1191 Formattable
& result
,
1192 UErrorCode
& status
) const
1194 NumberFormat::parse(text
, result
, status
);
1198 DecimalFormat::parse(const UnicodeString
& text
,
1199 Formattable
& result
,
1200 ParsePosition
& parsePosition
) const {
1201 parse(text
, result
, parsePosition
, FALSE
);
1204 Formattable
& DecimalFormat::parseCurrency(const UnicodeString
& text
,
1205 Formattable
& result
,
1206 ParsePosition
& pos
) const {
1207 parse(text
, result
, pos
, TRUE
);
1212 * Parses the given text as either a number or a currency amount.
1213 * @param text the string to parse
1214 * @param result output parameter for the result
1215 * @param parsePosition input-output position; on input, the
1216 * position within text to match; must have 0 <= pos.getIndex() <
1217 * text.length(); on output, the position after the last matched
1218 * character. If the parse fails, the position in unchanged upon
1220 * @param parseCurrency if true, a currency amount is parsed;
1221 * otherwise a Number is parsed
1223 void DecimalFormat::parse(const UnicodeString
& text
,
1224 Formattable
& result
,
1225 ParsePosition
& parsePosition
,
1226 UBool parseCurrency
) const {
1228 int32_t i
= backup
= parsePosition
.getIndex();
1230 // Handle NaN as a special case:
1232 // Skip padding characters, if around prefix
1233 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforePrefix
||
1234 fPadPosition
== kPadAfterPrefix
)) {
1235 i
= skipPadding(text
, i
);
1237 // If the text is composed of the representation of NaN, returns NaN.length
1238 const UnicodeString
*nan
= &getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1239 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
1240 ? 0 : nan
->length());
1243 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforeSuffix
||
1244 fPadPosition
== kPadAfterSuffix
)) {
1245 i
= skipPadding(text
, i
);
1247 parsePosition
.setIndex(i
);
1248 result
.setDouble(uprv_getNaN());
1252 // NaN parse failed; start over
1255 // status is used to record whether a number is infinite.
1256 UBool status
[fgStatusLength
];
1258 UChar
* currency
= parseCurrency
? curbuf
: NULL
;
1261 if (!subparse(text
, parsePosition
, digits
, status
, currency
)) {
1262 parsePosition
.setIndex(backup
);
1267 if (status
[fgStatusInfinite
]) {
1268 double inf
= uprv_getInfinity();
1269 result
.setDouble(digits
.fIsPositive
? inf
: -inf
);
1273 // Do as much of the multiplier conversion as possible without
1275 int32_t mult
= fMultiplier
; // Don't modify this.multiplier
1276 while (mult
% 10 == 0) {
1278 --digits
.fDecimalAt
;
1281 // Handle integral values. We want to return the most
1282 // parsimonious type that will accommodate all of the result's
1283 // precision. We therefore only return a long if the result fits
1284 // entirely within a long (taking into account the multiplier) --
1285 // otherwise we fall through and return a double. When more
1286 // numeric types are supported by Formattable (e.g., 64-bit
1287 // integers, bignums) we will extend this logic to include them.
1288 if (digits
.fitsIntoLong(isParseIntegerOnly())) {
1289 int32_t n
= digits
.getLong();
1290 if (n
% mult
== 0) {
1291 result
.setLong(n
/ mult
);
1293 else { // else handle the remainder
1294 result
.setDouble(((double)n
) / mult
);
1297 else if (digits
.fitsIntoInt64(isParseIntegerOnly())) {
1298 int64_t n
= digits
.getInt64();
1299 if (n
% mult
== 0) {
1300 result
.setInt64(n
/ mult
);
1302 else { // else handle the remainder
1303 result
.setDouble(((double)n
) / mult
);
1307 // Handle non-integral or very large values
1308 // Dividing by one is okay and not that costly.
1309 result
.setDouble(digits
.getDouble() / mult
);
1313 if (parseCurrency
) {
1314 UErrorCode ec
= U_ZERO_ERROR
;
1315 Formattable
n(result
);
1316 result
.adoptObject(new CurrencyAmount(n
, curbuf
, ec
));
1317 U_ASSERT(U_SUCCESS(ec
)); // should always succeed
1323 This is an old implimentation that was preparing for 64-bit numbers in ICU.
1324 It is very slow, and 64-bit numbers are not ANSI-C compatible. This code
1325 is here if we change our minds.
1327 ^^^ what is this referring to? remove? ^^^ [alan]
1331 * Parse the given text into a number. The text is parsed beginning at
1332 * parsePosition, until an unparseable character is seen.
1333 * @param text the string to parse.
1334 * @param parsePosition The position at which to being parsing. Upon
1335 * return, the first unparsed character.
1336 * @param digits the DigitList to set to the parsed value.
1337 * @param status output param containing boolean status flags indicating
1338 * whether the value was infinite and whether it was positive.
1339 * @param currency return value for parsed currency, for generic
1340 * currency parsing mode, or NULL for normal parsing. In generic
1341 * currency parsing mode, any currency is parsed, not just the
1342 * currency that this formatter is set to.
1344 UBool
DecimalFormat::subparse(const UnicodeString
& text
, ParsePosition
& parsePosition
,
1345 DigitList
& digits
, UBool
* status
,
1346 UChar
* currency
) const
1348 int32_t position
= parsePosition
.getIndex();
1349 int32_t oldStart
= position
;
1351 // Match padding before prefix
1352 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforePrefix
) {
1353 position
= skipPadding(text
, position
);
1356 // Match positive and negative prefixes; prefer longest match.
1357 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, currency
);
1358 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, currency
);
1359 if (posMatch
>= 0 && negMatch
>= 0) {
1360 if (posMatch
> negMatch
) {
1362 } else if (negMatch
> posMatch
) {
1366 if (posMatch
>= 0) {
1367 position
+= posMatch
;
1368 } else if (negMatch
>= 0) {
1369 position
+= negMatch
;
1371 parsePosition
.setErrorIndex(position
);
1375 // Match padding before prefix
1376 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterPrefix
) {
1377 position
= skipPadding(text
, position
);
1380 // process digits or Inf, find decimal position
1381 const UnicodeString
*inf
= &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1382 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
1383 ? 0 : inf
->length());
1384 position
+= infLen
; // infLen is non-zero when it does equal to infinity
1385 status
[fgStatusInfinite
] = (UBool
)infLen
;
1388 // We now have a string of digits, possibly with grouping symbols,
1389 // and decimal points. We want to process these into a DigitList.
1390 // We don't want to put a bunch of leading zeros into the DigitList
1391 // though, so we keep track of the location of the decimal point,
1392 // put only significant digits into the DigitList, and adjust the
1393 // exponent as needed.
1395 digits
.fDecimalAt
= digits
.fCount
= 0;
1396 UChar32 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1398 const UnicodeString
*decimal
;
1399 if(fIsCurrencyFormat
) {
1400 decimal
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1402 decimal
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1404 const UnicodeString
*grouping
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1405 UBool sawDecimal
= FALSE
;
1406 UBool sawDigit
= FALSE
;
1407 int32_t backup
= -1;
1409 int32_t textLength
= text
.length(); // One less pointer to follow
1410 int32_t groupingLen
= grouping
->length();
1411 int32_t decimalLen
= decimal
->length();
1413 // We have to track digitCount ourselves, because digits.fCount will
1414 // pin when the maximum allowable digits is reached.
1415 int32_t digitCount
= 0;
1417 for (; position
< textLength
; )
1419 UChar32 ch
= text
.char32At(position
);
1421 /* We recognize all digit ranges, not only the Latin digit range
1422 * '0'..'9'. We do so by using the Character.digit() method,
1423 * which converts a valid Unicode digit to the range 0..9.
1425 * The character 'ch' may be a digit. If so, place its value
1426 * from 0 to 9 in 'digit'. First try using the locale digit,
1427 * which may or MAY NOT be a standard Unicode digit range. If
1428 * this fails, try using the standard Unicode digit ranges by
1429 * calling Character.digit(). If this also fails, digit will
1430 * have a value outside the range 0..9.
1433 if (digit
< 0 || digit
> 9)
1435 digit
= u_charDigitValue(ch
);
1438 if (digit
> 0 && digit
<= 9)
1440 // Cancel out backup setting (see grouping handler below)
1444 // output a regular non-zero digit.
1446 digits
.append((char)(digit
+ '0'));
1447 position
+= U16_LENGTH(ch
);
1449 else if (digit
== 0)
1451 // Cancel out backup setting (see grouping handler below)
1455 // Check for leading zeros
1456 if (digits
.fCount
!= 0)
1458 // output a regular zero digit.
1460 digits
.append((char)(digit
+ '0'));
1462 else if (sawDecimal
)
1464 // If we have seen the decimal, but no significant digits yet,
1465 // then we account for leading zeros by decrementing the
1466 // digits.fDecimalAt into negative values.
1467 --digits
.fDecimalAt
;
1469 // else ignore leading zeros in integer part of number.
1470 position
+= U16_LENGTH(ch
);
1472 else if (!text
.compare(position
, groupingLen
, *grouping
) && isGroupingUsed())
1474 // Ignore grouping characters, if we are using them, but require
1475 // that they be followed by a digit. Otherwise we backup and
1478 position
+= groupingLen
;
1480 else if (!text
.compare(position
, decimalLen
, *decimal
) && !isParseIntegerOnly() && !sawDecimal
)
1482 // If we're only parsing integers, or if we ALREADY saw the
1483 // decimal, then don't parse this one.
1485 digits
.fDecimalAt
= digitCount
; // Not digits.fCount!
1487 position
+= decimalLen
;
1490 const UnicodeString
*tmp
;
1491 tmp
= &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1492 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
1494 // Parse sign, if present
1495 int32_t pos
= position
+ tmp
->length();
1496 DigitList exponentDigits
;
1498 if (pos
< textLength
)
1500 tmp
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1501 if (!text
.compare(pos
, tmp
->length(), *tmp
))
1503 pos
+= tmp
->length();
1506 tmp
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1507 if (!text
.compare(pos
, tmp
->length(), *tmp
))
1509 pos
+= tmp
->length();
1510 exponentDigits
.fIsPositive
= FALSE
;
1515 while (pos
< textLength
) {
1516 ch
= text
[(int32_t)pos
];
1519 if (digit
< 0 || digit
> 9) {
1520 digit
= u_charDigitValue(ch
);
1522 if (0 <= digit
&& digit
<= 9) {
1524 exponentDigits
.append((char)(digit
+ '0'));
1530 if (exponentDigits
.fCount
> 0) {
1531 exponentDigits
.fDecimalAt
= exponentDigits
.fCount
;
1532 digits
.fDecimalAt
+= exponentDigits
.getLong();
1533 position
= pos
; // Advance past the exponent
1536 break; // Whether we fail or succeed, we exit this loop
1549 // If there was no decimal point we have an integer
1552 digits
.fDecimalAt
+= digitCount
; // Not digits.fCount!
1555 // If none of the text string was recognized. For example, parse
1556 // "x" with pattern "#0.00" (return index and error index both 0)
1557 // parse "$" with pattern "$#0.00". (return index 0 and error index
1559 if (!sawDigit
&& digitCount
== 0) {
1560 parsePosition
.setIndex(oldStart
);
1561 parsePosition
.setErrorIndex(oldStart
);
1566 // Match padding before suffix
1567 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforeSuffix
) {
1568 position
= skipPadding(text
, position
);
1571 // Match positive and negative suffixes; prefer longest match.
1572 if (posMatch
>= 0) {
1573 posMatch
= compareAffix(text
, position
, FALSE
, FALSE
, currency
);
1575 if (negMatch
>= 0) {
1576 negMatch
= compareAffix(text
, position
, TRUE
, FALSE
, currency
);
1578 if (posMatch
>= 0 && negMatch
>= 0) {
1579 if (posMatch
> negMatch
) {
1581 } else if (negMatch
> posMatch
) {
1586 // Fail if neither or both
1587 if ((posMatch
>= 0) == (negMatch
>= 0)) {
1588 parsePosition
.setErrorIndex(position
);
1592 position
+= (posMatch
>=0 ? posMatch
: negMatch
);
1594 // Match padding before suffix
1595 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterSuffix
) {
1596 position
= skipPadding(text
, position
);
1599 parsePosition
.setIndex(position
);
1601 digits
.fIsPositive
= (posMatch
>= 0);
1603 if(parsePosition
.getIndex() == oldStart
)
1605 parsePosition
.setErrorIndex(position
);
1612 * Starting at position, advance past a run of pad characters, if any.
1613 * Return the index of the first character after position that is not a pad
1614 * character. Result is >= position.
1616 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
1617 int32_t padLen
= U16_LENGTH(fPad
);
1618 while (position
< text
.length() &&
1619 text
.char32At(position
) == fPad
) {
1626 * Return the length matched by the given affix, or -1 if none.
1627 * Runs of white space in the affix, match runs of white space in
1628 * the input. Pattern white space and input white space are
1629 * determined differently; see code.
1630 * @param text input text
1631 * @param pos offset into input at which to begin matching
1634 * @param currency return value for parsed currency, for generic
1635 * currency parsing mode, or null for normal parsing. In generic
1636 * currency parsing mode, any currency is parsed, not just the
1637 * currency that this formatter is set to.
1638 * @return length of input that matches, or -1 if match failure
1640 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
1644 UChar
* currency
) const {
1645 if (fCurrencyChoice
!= NULL
|| currency
!= NULL
) {
1647 return compareComplexAffix(isNegative
? *fNegPrefixPattern
: *fPosPrefixPattern
,
1648 text
, pos
, currency
);
1650 return compareComplexAffix(isNegative
? *fNegSuffixPattern
: *fPosSuffixPattern
,
1651 text
, pos
, currency
);
1656 return compareSimpleAffix(isNegative
? fNegativePrefix
: fPositivePrefix
,
1659 return compareSimpleAffix(isNegative
? fNegativeSuffix
: fPositiveSuffix
,
1665 * Return the length matched by the given affix, or -1 if none.
1666 * Runs of white space in the affix, match runs of white space in
1667 * the input. Pattern white space and input white space are
1668 * determined differently; see code.
1669 * @param affix pattern string, taken as a literal
1670 * @param input input text
1671 * @param pos offset into input at which to begin matching
1672 * @return length of input that matches, or -1 if match failure
1674 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
1675 const UnicodeString
& input
,
1677 int32_t start
= pos
;
1678 for (int32_t i
=0; i
<affix
.length(); ) {
1679 UChar32 c
= affix
.char32At(i
);
1680 int32_t len
= U16_LENGTH(c
);
1681 if (uprv_isRuleWhiteSpace(c
)) {
1682 // We may have a pattern like: \u200F \u0020
1683 // and input text like: \u200F \u0020
1684 // Note that U+200F and U+0020 are RuleWhiteSpace but only
1685 // U+0020 is UWhiteSpace. So we have to first do a direct
1686 // match of the run of RULE whitespace in the pattern,
1687 // then match any extra characters.
1688 UBool literalMatch
= FALSE
;
1689 while (pos
< input
.length() &&
1690 input
.char32At(pos
) == c
) {
1691 literalMatch
= TRUE
;
1694 if (i
== affix
.length()) {
1697 c
= affix
.char32At(i
);
1698 len
= U16_LENGTH(c
);
1699 if (!uprv_isRuleWhiteSpace(c
)) {
1704 // Advance over run in pattern
1705 i
= skipRuleWhiteSpace(affix
, i
);
1707 // Advance over run in input text
1708 // Must see at least one white space char in input,
1709 // unless we've already matched some characters literally.
1711 pos
= skipUWhiteSpace(input
, pos
);
1712 if (pos
== s
&& !literalMatch
) {
1716 if (pos
< input
.length() &&
1717 input
.char32At(pos
) == c
) {
1729 * Skip over a run of zero or more isRuleWhiteSpace() characters at
1732 int32_t DecimalFormat::skipRuleWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
1733 while (pos
< text
.length()) {
1734 UChar32 c
= text
.char32At(pos
);
1735 if (!uprv_isRuleWhiteSpace(c
)) {
1738 pos
+= U16_LENGTH(c
);
1744 * Skip over a run of zero or more isUWhiteSpace() characters at pos
1747 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
1748 while (pos
< text
.length()) {
1749 UChar32 c
= text
.char32At(pos
);
1750 if (!u_isUWhiteSpace(c
)) {
1753 pos
+= U16_LENGTH(c
);
1759 * Return the length matched by the given affix, or -1 if none.
1760 * @param affixPat pattern string
1761 * @param input input text
1762 * @param pos offset into input at which to begin matching
1763 * @param currency return value for parsed currency, for generic
1764 * currency parsing mode, or null for normal parsing. In generic
1765 * currency parsing mode, any currency is parsed, not just the
1766 * currency that this formatter is set to.
1767 * @return length of input that matches, or -1 if match failure
1769 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
1770 const UnicodeString
& text
,
1772 UChar
* currency
) const {
1773 U_ASSERT(currency
!= NULL
||
1774 (fCurrencyChoice
!= NULL
&& *getCurrency() != 0));
1776 for (int32_t i
=0; i
<affixPat
.length() && pos
>= 0; ) {
1777 UChar32 c
= affixPat
.char32At(i
);
1781 U_ASSERT(i
<= affixPat
.length());
1782 c
= affixPat
.char32At(i
);
1785 const UnicodeString
* affix
= NULL
;
1788 case kCurrencySign
: {
1789 // If currency != null, then perform generic currency matching.
1790 // Otherwise, do currency choice parsing.
1791 UBool intl
= i
<affixPat
.length() &&
1792 affixPat
.char32At(i
) == kCurrencySign
;
1793 // Parse generic currency -- anything for which we
1794 // have a display name, or any 3-letter ISO code.
1795 if (currency
!= NULL
) {
1796 // Try to parse display name for our locale; first
1797 // determine our locale.
1798 UErrorCode ec
= U_ZERO_ERROR
;
1799 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
1800 if (U_FAILURE(ec
) || loc
== NULL
|| *loc
== 0) {
1801 // applyPattern has been called; use the symbols
1802 loc
= fSymbols
->getLocale().getName();
1805 // Delegate parse of display name => ISO code to Currency
1806 ParsePosition
ppos(pos
);
1808 uprv_parseCurrency(loc
, text
, ppos
, curr
, ec
);
1810 // If parse succeeds, populate currency[0]
1811 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
1812 u_strcpy(currency
, curr
);
1813 pos
= ppos
.getIndex();
1820 pos
= match(text
, pos
, getCurrency());
1822 ParsePosition
ppos(pos
);
1824 fCurrencyChoice
->parse(text
, result
, ppos
);
1825 pos
= (ppos
.getIndex() == pos
) ? -1 : ppos
.getIndex();
1830 case kPatternPercent
:
1831 affix
= &getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
1833 case kPatternPerMill
:
1834 affix
= &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
1837 affix
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1840 affix
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1843 // fall through to affix!=0 test, which will fail
1847 if (affix
!= NULL
) {
1848 pos
= match(text
, pos
, *affix
);
1853 pos
= match(text
, pos
, c
);
1854 if (uprv_isRuleWhiteSpace(c
)) {
1855 i
= skipRuleWhiteSpace(affixPat
, i
);
1862 * Match a single character at text[pos] and return the index of the
1863 * next character upon success. Return -1 on failure. If
1864 * isRuleWhiteSpace(ch) then match a run of white space in text.
1866 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
1867 if (uprv_isRuleWhiteSpace(ch
)) {
1868 // Advance over run of white space in input text
1869 // Must see at least one white space char in input
1871 pos
= skipUWhiteSpace(text
, pos
);
1877 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
1878 (pos
+ U16_LENGTH(ch
)) : -1;
1882 * Match a string at text[pos] and return the index of the next
1883 * character upon success. Return -1 on failure. Match a run of
1884 * white space in str with a run of white space in text.
1886 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
1887 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
1888 UChar32 ch
= str
.char32At(i
);
1889 i
+= U16_LENGTH(ch
);
1890 if (uprv_isRuleWhiteSpace(ch
)) {
1891 i
= skipRuleWhiteSpace(str
, i
);
1893 pos
= match(text
, pos
, ch
);
1898 //------------------------------------------------------------------------------
1899 // Gets the pointer to the localized decimal format symbols
1901 const DecimalFormatSymbols
*
1902 DecimalFormat::getDecimalFormatSymbols() const
1907 //------------------------------------------------------------------------------
1908 // De-owning the current localized symbols and adopt the new symbols.
1911 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
1913 if (symbolsToAdopt
== NULL
) {
1914 return; // do not allow caller to set fSymbols to NULL
1917 UBool sameSymbols
= FALSE
;
1918 if (fSymbols
!= NULL
) {
1919 sameSymbols
= (UBool
)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) ==
1920 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) &&
1921 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) ==
1922 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1926 fSymbols
= symbolsToAdopt
;
1928 // If the currency symbols are the same, there is no need to recalculate.
1929 setCurrencyForSymbols();
1933 //------------------------------------------------------------------------------
1934 // Setting the symbols is equlivalent to adopting a newly created localized
1938 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
1940 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
1944 * Update the currency object to match the symbols. This method
1945 * is used only when the caller has passed in a symbols object
1946 * that may not be the default object for its locale.
1949 DecimalFormat::setCurrencyForSymbols() {
1951 Update the affix strings accroding to symbols in order to keep
1952 the affix strings up to date.
1956 // With the introduction of the Currency object, the currency
1957 // symbols in the DFS object are ignored. For backward
1958 // compatibility, we check any explicitly set DFS object. If it
1959 // is a default symbols object for its locale, we change the
1960 // currency object to one for that locale. If it is custom,
1961 // we set the currency to null.
1962 UErrorCode ec
= U_ZERO_ERROR
;
1963 const UChar
* c
= NULL
;
1964 const char* loc
= fSymbols
->getLocale().getName();
1965 UChar intlCurrencySymbol
[4];
1966 ucurr_forLocale(loc
, intlCurrencySymbol
, 4, &ec
);
1967 UnicodeString currencySymbol
;
1969 uprv_getStaticCurrencyName(intlCurrencySymbol
, loc
, currencySymbol
, ec
);
1971 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) == currencySymbol
1972 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) == intlCurrencySymbol
)
1974 // Trap an error in mapping locale to currency. If we can't
1975 // map, then don't fail and set the currency to "".
1976 c
= intlCurrencySymbol
;
1978 ec
= U_ZERO_ERROR
; // reset local error code!
1983 //------------------------------------------------------------------------------
1984 // Gets the positive prefix of the number pattern.
1987 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
1989 result
= fPositivePrefix
;
1993 //------------------------------------------------------------------------------
1994 // Sets the positive prefix of the number pattern.
1997 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
1999 fPositivePrefix
= newValue
;
2000 delete fPosPrefixPattern
;
2001 fPosPrefixPattern
= 0;
2004 //------------------------------------------------------------------------------
2005 // Gets the negative prefix of the number pattern.
2008 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
2010 result
= fNegativePrefix
;
2014 //------------------------------------------------------------------------------
2015 // Gets the negative prefix of the number pattern.
2018 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
2020 fNegativePrefix
= newValue
;
2021 delete fNegPrefixPattern
;
2022 fNegPrefixPattern
= 0;
2025 //------------------------------------------------------------------------------
2026 // Gets the positive suffix of the number pattern.
2029 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
2031 result
= fPositiveSuffix
;
2035 //------------------------------------------------------------------------------
2036 // Sets the positive suffix of the number pattern.
2039 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
2041 fPositiveSuffix
= newValue
;
2042 delete fPosSuffixPattern
;
2043 fPosSuffixPattern
= 0;
2046 //------------------------------------------------------------------------------
2047 // Gets the negative suffix of the number pattern.
2050 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
2052 result
= fNegativeSuffix
;
2056 //------------------------------------------------------------------------------
2057 // Sets the negative suffix of the number pattern.
2060 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
2062 fNegativeSuffix
= newValue
;
2063 delete fNegSuffixPattern
;
2064 fNegSuffixPattern
= 0;
2067 //------------------------------------------------------------------------------
2068 // Gets the multiplier of the number pattern.
2070 int32_t DecimalFormat::getMultiplier() const
2075 //------------------------------------------------------------------------------
2076 // Sets the multiplier of the number pattern.
2078 DecimalFormat::setMultiplier(int32_t newValue
)
2080 // This shouldn't be set to 0.
2081 // Due to compatibility with ICU4J we cannot set an error code and refuse 0.
2082 // So the rest of the code should ignore fMultiplier when it's 0. [grhoten]
2083 fMultiplier
= newValue
;
2087 * Get the rounding increment.
2088 * @return A positive rounding increment, or 0.0 if rounding
2090 * @see #setRoundingIncrement
2091 * @see #getRoundingMode
2092 * @see #setRoundingMode
2094 double DecimalFormat::getRoundingIncrement() const {
2095 return fRoundingDouble
;
2099 * Set the rounding increment. This method also controls whether
2100 * rounding is enabled.
2101 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2102 * Negative increments are equivalent to 0.0.
2103 * @see #getRoundingIncrement
2104 * @see #getRoundingMode
2105 * @see #setRoundingMode
2107 void DecimalFormat::setRoundingIncrement(double newValue
) {
2108 if (newValue
> 0.0) {
2109 if (fRoundingIncrement
== NULL
) {
2110 fRoundingIncrement
= new DigitList();
2112 fRoundingIncrement
->set((int32_t)newValue
);
2113 fRoundingDouble
= newValue
;
2115 delete fRoundingIncrement
;
2116 fRoundingIncrement
= NULL
;
2117 fRoundingDouble
= 0.0;
2122 * Get the rounding mode.
2123 * @return A rounding mode
2124 * @see #setRoundingIncrement
2125 * @see #getRoundingIncrement
2126 * @see #setRoundingMode
2128 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
2129 return fRoundingMode
;
2133 * Set the rounding mode. This has no effect unless the rounding
2134 * increment is greater than zero.
2135 * @param roundingMode A rounding mode
2136 * @see #setRoundingIncrement
2137 * @see #getRoundingIncrement
2138 * @see #getRoundingMode
2140 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
2141 fRoundingMode
= roundingMode
;
2145 * Get the width to which the output of <code>format()</code> is padded.
2146 * @return the format width, or zero if no padding is in effect
2147 * @see #setFormatWidth
2148 * @see #getPadCharacter
2149 * @see #setPadCharacter
2150 * @see #getPadPosition
2151 * @see #setPadPosition
2153 int32_t DecimalFormat::getFormatWidth() const {
2154 return fFormatWidth
;
2158 * Set the width to which the output of <code>format()</code> is padded.
2159 * This method also controls whether padding is enabled.
2160 * @param width the width to which to pad the result of
2161 * <code>format()</code>, or zero to disable padding. A negative
2162 * width is equivalent to 0.
2163 * @see #getFormatWidth
2164 * @see #getPadCharacter
2165 * @see #setPadCharacter
2166 * @see #getPadPosition
2167 * @see #setPadPosition
2169 void DecimalFormat::setFormatWidth(int32_t width
) {
2170 fFormatWidth
= (width
> 0) ? width
: 0;
2173 UnicodeString
DecimalFormat::getPadCharacterString() const {
2177 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
2178 if (padChar
.length() > 0) {
2179 fPad
= padChar
.char32At(0);
2187 * Get the position at which padding will take place. This is the location
2188 * at which padding will be inserted if the result of <code>format()</code>
2189 * is shorter than the format width.
2190 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2191 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2192 * <code>kPadAfterSuffix</code>.
2193 * @see #setFormatWidth
2194 * @see #getFormatWidth
2195 * @see #setPadCharacter
2196 * @see #getPadCharacter
2197 * @see #setPadPosition
2198 * @see #kPadBeforePrefix
2199 * @see #kPadAfterPrefix
2200 * @see #kPadBeforeSuffix
2201 * @see #kPadAfterSuffix
2203 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
2204 return fPadPosition
;
2208 * <strong><font face=helvetica color=red>NEW</font></strong>
2209 * Set the position at which padding will take place. This is the location
2210 * at which padding will be inserted if the result of <code>format()</code>
2211 * is shorter than the format width. This has no effect unless padding is
2213 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2214 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2215 * <code>kPadAfterSuffix</code>.
2216 * @see #setFormatWidth
2217 * @see #getFormatWidth
2218 * @see #setPadCharacter
2219 * @see #getPadCharacter
2220 * @see #getPadPosition
2221 * @see #kPadBeforePrefix
2222 * @see #kPadAfterPrefix
2223 * @see #kPadBeforeSuffix
2224 * @see #kPadAfterSuffix
2226 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
2227 fPadPosition
= padPos
;
2231 * Return whether or not scientific notation is used.
2232 * @return TRUE if this object formats and parses scientific notation
2233 * @see #setScientificNotation
2234 * @see #getMinimumExponentDigits
2235 * @see #setMinimumExponentDigits
2236 * @see #isExponentSignAlwaysShown
2237 * @see #setExponentSignAlwaysShown
2239 UBool
DecimalFormat::isScientificNotation() {
2240 return fUseExponentialNotation
;
2244 * Set whether or not scientific notation is used.
2245 * @param useScientific TRUE if this object formats and parses scientific
2247 * @see #isScientificNotation
2248 * @see #getMinimumExponentDigits
2249 * @see #setMinimumExponentDigits
2250 * @see #isExponentSignAlwaysShown
2251 * @see #setExponentSignAlwaysShown
2253 void DecimalFormat::setScientificNotation(UBool useScientific
) {
2254 fUseExponentialNotation
= useScientific
;
2258 * Return the minimum exponent digits that will be shown.
2259 * @return the minimum exponent digits that will be shown
2260 * @see #setScientificNotation
2261 * @see #isScientificNotation
2262 * @see #setMinimumExponentDigits
2263 * @see #isExponentSignAlwaysShown
2264 * @see #setExponentSignAlwaysShown
2266 int8_t DecimalFormat::getMinimumExponentDigits() const {
2267 return fMinExponentDigits
;
2271 * Set the minimum exponent digits that will be shown. This has no
2272 * effect unless scientific notation is in use.
2273 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2274 * that will be shown. Values less than 1 will be treated as 1.
2275 * @see #setScientificNotation
2276 * @see #isScientificNotation
2277 * @see #getMinimumExponentDigits
2278 * @see #isExponentSignAlwaysShown
2279 * @see #setExponentSignAlwaysShown
2281 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
2282 fMinExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
2286 * Return whether the exponent sign is always shown.
2287 * @return TRUE if the exponent is always prefixed with either the
2288 * localized minus sign or the localized plus sign, false if only negative
2289 * exponents are prefixed with the localized minus sign.
2290 * @see #setScientificNotation
2291 * @see #isScientificNotation
2292 * @see #setMinimumExponentDigits
2293 * @see #getMinimumExponentDigits
2294 * @see #setExponentSignAlwaysShown
2296 UBool
DecimalFormat::isExponentSignAlwaysShown() {
2297 return fExponentSignAlwaysShown
;
2301 * Set whether the exponent sign is always shown. This has no effect
2302 * unless scientific notation is in use.
2303 * @param expSignAlways TRUE if the exponent is always prefixed with either
2304 * the localized minus sign or the localized plus sign, false if only
2305 * negative exponents are prefixed with the localized minus sign.
2306 * @see #setScientificNotation
2307 * @see #isScientificNotation
2308 * @see #setMinimumExponentDigits
2309 * @see #getMinimumExponentDigits
2310 * @see #isExponentSignAlwaysShown
2312 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
2313 fExponentSignAlwaysShown
= expSignAlways
;
2316 //------------------------------------------------------------------------------
2317 // Gets the grouping size of the number pattern. For example, thousand or 10
2318 // thousand groupings.
2321 DecimalFormat::getGroupingSize() const
2323 return fGroupingSize
;
2326 //------------------------------------------------------------------------------
2327 // Gets the grouping size of the number pattern.
2330 DecimalFormat::setGroupingSize(int32_t newValue
)
2332 fGroupingSize
= newValue
;
2335 //------------------------------------------------------------------------------
2338 DecimalFormat::getSecondaryGroupingSize() const
2340 return fGroupingSize2
;
2343 //------------------------------------------------------------------------------
2346 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
2348 fGroupingSize2
= newValue
;
2351 //------------------------------------------------------------------------------
2352 // Checks if to show the decimal separator.
2355 DecimalFormat::isDecimalSeparatorAlwaysShown() const
2357 return fDecimalSeparatorAlwaysShown
;
2360 //------------------------------------------------------------------------------
2361 // Sets to always show the decimal separator.
2364 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
2366 fDecimalSeparatorAlwaysShown
= newValue
;
2369 //------------------------------------------------------------------------------
2370 // Emits the pattern of this DecimalFormat instance.
2373 DecimalFormat::toPattern(UnicodeString
& result
) const
2375 return toPattern(result
, FALSE
);
2378 //------------------------------------------------------------------------------
2379 // Emits the localized pattern this DecimalFormat instance.
2382 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
2384 return toPattern(result
, TRUE
);
2387 //------------------------------------------------------------------------------
2389 * Expand the affix pattern strings into the expanded affix strings. If any
2390 * affix pattern string is null, do not expand it. This method should be
2391 * called any time the symbols or the affix patterns change in order to keep
2392 * the expanded affix strings up to date.
2394 void DecimalFormat::expandAffixes() {
2395 if (fPosPrefixPattern
!= 0) {
2396 expandAffix(*fPosPrefixPattern
, fPositivePrefix
, 0, FALSE
);
2398 if (fPosSuffixPattern
!= 0) {
2399 expandAffix(*fPosSuffixPattern
, fPositiveSuffix
, 0, FALSE
);
2401 if (fNegPrefixPattern
!= 0) {
2402 expandAffix(*fNegPrefixPattern
, fNegativePrefix
, 0, FALSE
);
2404 if (fNegSuffixPattern
!= 0) {
2405 expandAffix(*fNegSuffixPattern
, fNegativeSuffix
, 0, FALSE
);
2410 .append(*fPosPrefixPattern
).append("|").append(*fPosSuffixPattern
)
2411 .append(";") .append(*fNegPrefixPattern
).append("|").append(*fNegSuffixPattern
)
2413 .append(fPositivePrefix
).append("|").append(fPositiveSuffix
)
2414 .append(";") .append(fNegativePrefix
).append("|").append(fNegativeSuffix
)
2421 * Expand an affix pattern into an affix string. All characters in the
2422 * pattern are literal unless prefixed by kQuote. The following characters
2423 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
2424 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
2425 * kCurrencySign + kCurrencySign), it is interpreted as an international
2426 * currency sign. Any other character after a kQuote represents itself.
2427 * kQuote must be followed by another character; kQuote may not occur by
2428 * itself at the end of the pattern.
2430 * This method is used in two distinct ways. First, it is used to expand
2431 * the stored affix patterns into actual affixes. For this usage, doFormat
2432 * must be false. Second, it is used to expand the stored affix patterns
2433 * given a specific number (doFormat == true), for those rare cases in
2434 * which a currency format references a ChoiceFormat (e.g., en_IN display
2435 * name for INR). The number itself is taken from digitList.
2437 * When used in the first way, this method has a side effect: It sets
2438 * currencyChoice to a ChoiceFormat object, if the currency's display name
2439 * in this locale is a ChoiceFormat pattern (very rare). It only does this
2440 * if currencyChoice is null to start with.
2442 * @param pattern the non-null, fPossibly empty pattern
2443 * @param affix string to receive the expanded equivalent of pattern.
2444 * Previous contents are deleted.
2445 * @param doFormat if false, then the pattern will be expanded, and if a
2446 * currency symbol is encountered that expands to a ChoiceFormat, the
2447 * currencyChoice member variable will be initialized if it is null. If
2448 * doFormat is true, then it is assumed that the currencyChoice has been
2449 * created, and it will be used to format the value in digitList.
2451 void DecimalFormat::expandAffix(const UnicodeString
& pattern
,
2452 UnicodeString
& affix
,
2454 UBool doFormat
) const {
2456 for (int i
=0; i
<pattern
.length(); ) {
2457 UChar32 c
= pattern
.char32At(i
);
2460 c
= pattern
.char32At(i
);
2463 case kCurrencySign
: {
2464 // As of ICU 2.2 we use the currency object, and
2465 // ignore the currency symbols in the DFS, unless
2466 // we have a null currency object. This occurs if
2467 // resurrecting a pre-2.2 object or if the user
2468 // sets a custom DFS.
2469 UBool intl
= i
<pattern
.length() &&
2470 pattern
.char32At(i
) == kCurrencySign
;
2474 const UChar
* currencyUChars
= getCurrency();
2475 if (currencyUChars
[0] != 0) {
2476 UErrorCode ec
= U_ZERO_ERROR
;
2478 affix
+= currencyUChars
;
2481 UBool isChoiceFormat
;
2482 const UChar
* s
= ucurr_getName(currencyUChars
, fSymbols
->getLocale().getName(),
2483 UCURR_SYMBOL_NAME
, &isChoiceFormat
, &len
, &ec
);
2484 if (isChoiceFormat
) {
2485 // Two modes here: If doFormat is false, we set up
2486 // currencyChoice. If doFormat is true, we use the
2487 // previously created currencyChoice to format the
2488 // value in digitList.
2490 // If the currency is handled by a ChoiceFormat,
2491 // then we're not going to use the expanded
2492 // patterns. Instantiate the ChoiceFormat and
2494 if (fCurrencyChoice
== NULL
) {
2495 // TODO Replace double-check with proper thread-safe code
2496 ChoiceFormat
* fmt
= new ChoiceFormat(s
, ec
);
2497 if (U_SUCCESS(ec
)) {
2499 if (fCurrencyChoice
== NULL
) {
2501 ((DecimalFormat
*)this)->fCurrencyChoice
= fmt
;
2508 // We could almost return null or "" here, since the
2509 // expanded affixes are almost not used at all
2510 // in this situation. However, one method --
2511 // toPattern() -- still does use the expanded
2512 // affixes, in order to set up a padding
2513 // pattern. We use the CURRENCY_SIGN as a
2515 affix
.append(kCurrencySign
);
2517 if (fCurrencyChoice
!= NULL
) {
2518 FieldPosition
pos(0); // ignored
2522 fCurrencyChoice
->format(number
, affix
, pos
);
2524 // We only arrive here if the currency choice
2525 // format in the locale data is INVALID.
2526 affix
+= currencyUChars
;
2531 affix
+= UnicodeString(s
, len
);
2535 affix
+= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
2537 affix
+= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
2542 case kPatternPercent
:
2543 affix
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
2545 case kPatternPerMill
:
2546 affix
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
2549 affix
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2552 affix
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2566 * Append an affix to the given StringBuffer.
2567 * @param buf buffer to append to
2571 int32_t DecimalFormat::appendAffix(UnicodeString
& buf
, double number
,
2572 UBool isNegative
, UBool isPrefix
) const {
2573 if (fCurrencyChoice
!= 0) {
2574 const UnicodeString
* affixPat
= 0;
2576 affixPat
= isNegative
? fNegPrefixPattern
: fPosPrefixPattern
;
2578 affixPat
= isNegative
? fNegSuffixPattern
: fPosSuffixPattern
;
2580 UnicodeString affixBuf
;
2581 expandAffix(*affixPat
, affixBuf
, number
, TRUE
);
2582 buf
.append(affixBuf
);
2583 return affixBuf
.length();
2586 const UnicodeString
* affix
= NULL
;
2588 affix
= isNegative
? &fNegativePrefix
: &fPositivePrefix
;
2590 affix
= isNegative
? &fNegativeSuffix
: &fPositiveSuffix
;
2593 return affix
->length();
2597 * Appends an affix pattern to the given StringBuffer, quoting special
2598 * characters as needed. Uses the internal affix pattern, if that exists,
2599 * or the literal affix, if the internal affix pattern is null. The
2600 * appended string will generate the same affix pattern (or literal affix)
2601 * when passed to toPattern().
2603 * @param appendTo the affix string is appended to this
2604 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
2605 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
2606 * Ignored unless affixPattern is null. If affixPattern is null, then
2607 * expAffix is appended as a literal affix.
2608 * @param localized true if the appended pattern should contain localized
2609 * pattern characters; otherwise, non-localized pattern chars are appended
2611 void DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
2612 const UnicodeString
* affixPattern
,
2613 const UnicodeString
& expAffix
,
2614 UBool localized
) const {
2615 if (affixPattern
== 0) {
2616 appendAffixPattern(appendTo
, expAffix
, localized
);
2619 for (int pos
=0; pos
<affixPattern
->length(); pos
=i
) {
2620 i
= affixPattern
->indexOf(kQuote
, pos
);
2623 affixPattern
->extractBetween(pos
, affixPattern
->length(), s
);
2624 appendAffixPattern(appendTo
, s
, localized
);
2629 affixPattern
->extractBetween(pos
, i
, s
);
2630 appendAffixPattern(appendTo
, s
, localized
);
2632 UChar32 c
= affixPattern
->char32At(++i
);
2635 appendTo
.append(c
).append(c
);
2636 // Fall through and append another kQuote below
2637 } else if (c
== kCurrencySign
&&
2638 i
<affixPattern
->length() &&
2639 affixPattern
->char32At(i
) == kCurrencySign
) {
2641 appendTo
.append(c
).append(c
);
2642 } else if (localized
) {
2644 case kPatternPercent
:
2645 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
2647 case kPatternPerMill
:
2648 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
2651 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2654 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2667 * Append an affix to the given StringBuffer, using quotes if
2668 * there are special characters. Single quotes themselves must be
2669 * escaped in either case.
2672 DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
2673 const UnicodeString
& affix
,
2674 UBool localized
) const {
2677 needQuote
= affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
)) >= 0
2678 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
)) >= 0
2679 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
)) >= 0
2680 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
)) >= 0
2681 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
)) >= 0
2682 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
)) >= 0
2683 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
)) >= 0
2684 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
)) >= 0
2685 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) >= 0
2686 || affix
.indexOf(kCurrencySign
) >= 0;
2689 needQuote
= affix
.indexOf(kPatternZeroDigit
) >= 0
2690 || affix
.indexOf(kPatternGroupingSeparator
) >= 0
2691 || affix
.indexOf(kPatternDecimalSeparator
) >= 0
2692 || affix
.indexOf(kPatternPercent
) >= 0
2693 || affix
.indexOf(kPatternPerMill
) >= 0
2694 || affix
.indexOf(kPatternDigit
) >= 0
2695 || affix
.indexOf(kPatternSeparator
) >= 0
2696 || affix
.indexOf(kPatternExponent
) >= 0
2697 || affix
.indexOf(kPatternPlus
) >= 0
2698 || affix
.indexOf(kPatternMinus
) >= 0
2699 || affix
.indexOf(kCurrencySign
) >= 0;
2702 appendTo
+= (UChar
)0x0027 /*'\''*/;
2703 if (affix
.indexOf((UChar
)0x0027 /*'\''*/) < 0)
2706 for (int32_t j
= 0; j
< affix
.length(); ) {
2707 UChar32 c
= affix
.char32At(j
);
2710 if (c
== 0x0027 /*'\''*/)
2715 appendTo
+= (UChar
)0x0027 /*'\''*/;
2718 //------------------------------------------------------------------------------
2720 /* Tell the VC++ compiler not to spew out the warnings about integral size conversion */
2723 #pragma warning( disable : 4761 )
2728 DecimalFormat::toPattern(UnicodeString
& result
, UBool localized
) const
2731 UChar32 zero
, sigDigit
= kPatternSignificantDigit
;
2732 UnicodeString digit
, group
;
2734 int32_t roundingDecimalPos
= 0; // Pos of decimal in roundingDigits
2735 UnicodeString roundingDigits
;
2736 int32_t padPos
= (fFormatWidth
> 0) ? fPadPosition
: -1;
2737 UnicodeString padSpec
;
2738 UBool useSigDig
= areSignificantDigitsUsed();
2741 digit
.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
2742 group
.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
2743 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
2745 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
2749 digit
.append((UChar
)kPatternDigit
);
2750 group
.append((UChar
)kPatternGroupingSeparator
);
2751 zero
= (UChar32
)kPatternZeroDigit
;
2753 if (fFormatWidth
> 0) {
2755 padSpec
.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
2758 padSpec
.append((UChar
)kPatternPadEscape
);
2760 padSpec
.append(fPad
);
2762 if (fRoundingIncrement
!= NULL
) {
2763 for(i
=0; i
<fRoundingIncrement
->fCount
; ++i
) {
2764 roundingDigits
.append((UChar
)fRoundingIncrement
->fDigits
[i
]);
2766 roundingDecimalPos
= fRoundingIncrement
->fDecimalAt
;
2768 for (int32_t part
=0; part
<2; ++part
) {
2769 if (padPos
== kPadBeforePrefix
) {
2770 result
.append(padSpec
);
2772 appendAffixPattern(result
,
2773 (part
==0 ? fPosPrefixPattern
: fNegPrefixPattern
),
2774 (part
==0 ? fPositivePrefix
: fNegativePrefix
),
2776 if (padPos
== kPadAfterPrefix
&& ! padSpec
.isEmpty()) {
2777 result
.append(padSpec
);
2779 int32_t sub0Start
= result
.length();
2780 int32_t g
= isGroupingUsed() ? _max(0, fGroupingSize
) : 0;
2781 if (g
> 0 && fGroupingSize2
> 0 && fGroupingSize2
!= fGroupingSize
) {
2782 g
+= fGroupingSize2
;
2784 int32_t maxDig
= 0, minDig
= 0, maxSigDig
= 0;
2786 minDig
= getMinimumSignificantDigits();
2787 maxDig
= maxSigDig
= getMaximumSignificantDigits();
2789 minDig
= getMinimumIntegerDigits();
2790 maxDig
= getMaximumIntegerDigits();
2792 if (fUseExponentialNotation
) {
2793 if (maxDig
> kMaxScientificIntegerDigits
) {
2796 } else if (useSigDig
) {
2797 maxDig
= _max(maxDig
, g
+1);
2799 maxDig
= _max(_max(g
, getMinimumIntegerDigits()),
2800 roundingDecimalPos
) + 1;
2802 for (i
= maxDig
; i
> 0; --i
) {
2803 if (!fUseExponentialNotation
&& i
<maxDig
&&
2804 isGroupingPosition(i
)) {
2805 result
.append(group
);
2808 // #@,@### (maxSigDig == 5, minSigDig == 2)
2809 // 65 4321 (1-based pos, count from the right)
2810 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
2811 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
2812 if (maxSigDig
>= i
&& i
> (maxSigDig
- minDig
)) {
2813 result
.append(sigDigit
);
2815 result
.append(digit
);
2818 if (! roundingDigits
.isEmpty()) {
2819 int32_t pos
= roundingDecimalPos
- i
;
2820 if (pos
>= 0 && pos
< roundingDigits
.length()) {
2821 result
.append((UChar
) (roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
2826 result
.append(zero
);
2828 result
.append(digit
);
2833 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown
) {
2835 result
+= getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
2838 result
.append((UChar
)kPatternDecimalSeparator
);
2841 int32_t pos
= roundingDecimalPos
;
2842 for (i
= 0; i
< getMaximumFractionDigits(); ++i
) {
2843 if (! roundingDigits
.isEmpty() && pos
< roundingDigits
.length()) {
2845 result
.append(zero
);
2848 result
.append((UChar
)(roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
2853 if (i
<getMinimumFractionDigits()) {
2854 result
.append(zero
);
2857 result
.append(digit
);
2861 if (fUseExponentialNotation
) {
2863 result
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
2866 result
.append((UChar
)kPatternExponent
);
2868 if (fExponentSignAlwaysShown
) {
2870 result
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2873 result
.append((UChar
)kPatternPlus
);
2876 for (i
=0; i
<fMinExponentDigits
; ++i
) {
2877 result
.append(zero
);
2880 if (! padSpec
.isEmpty() && !fUseExponentialNotation
) {
2881 int32_t add
= fFormatWidth
- result
.length() + sub0Start
2883 ? fPositivePrefix
.length() + fPositiveSuffix
.length()
2884 : fNegativePrefix
.length() + fNegativeSuffix
.length());
2886 result
.insert(sub0Start
, digit
);
2889 // Only add a grouping separator if we have at least
2890 // 2 additional characters to be added, so we don't
2891 // end up with ",###".
2892 if (add
>1 && isGroupingPosition(maxDig
)) {
2893 result
.insert(sub0Start
, group
);
2898 if (fPadPosition
== kPadBeforeSuffix
&& ! padSpec
.isEmpty()) {
2899 result
.append(padSpec
);
2902 appendAffixPattern(result
, fPosSuffixPattern
, fPositiveSuffix
, localized
);
2903 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
2904 result
.append(padSpec
);
2906 UBool isDefault
= FALSE
;
2907 if ((fNegSuffixPattern
== fPosSuffixPattern
&& // both null
2908 fNegativeSuffix
== fPositiveSuffix
)
2909 || (fNegSuffixPattern
!= 0 && fPosSuffixPattern
!= 0 &&
2910 *fNegSuffixPattern
== *fPosSuffixPattern
))
2912 if (fNegPrefixPattern
!= NULL
&& fPosPrefixPattern
!= NULL
)
2914 int32_t length
= fPosPrefixPattern
->length();
2915 isDefault
= fNegPrefixPattern
->length() == (length
+2) &&
2916 (*fNegPrefixPattern
)[(int32_t)0] == kQuote
&&
2917 (*fNegPrefixPattern
)[(int32_t)1] == kPatternMinus
&&
2918 fNegPrefixPattern
->compare(2, length
, *fPosPrefixPattern
, 0, length
) == 0;
2921 fNegPrefixPattern
== NULL
&& fPosPrefixPattern
== NULL
)
2923 int32_t length
= fPositivePrefix
.length();
2924 isDefault
= fNegativePrefix
.length() == (length
+1) &&
2925 fNegativePrefix
.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) == 0 &&
2926 fNegativePrefix
.compare(1, length
, fPositivePrefix
, 0, length
) == 0;
2930 break; // Don't output default negative subpattern
2933 result
+= getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
);
2936 result
.append((UChar
)kPatternSeparator
);
2940 appendAffixPattern(result
, fNegSuffixPattern
, fNegativeSuffix
, localized
);
2941 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
2942 result
.append(padSpec
);
2950 //------------------------------------------------------------------------------
2953 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
2955 UParseError parseError
;
2956 applyPattern(pattern
, FALSE
, parseError
, status
);
2959 //------------------------------------------------------------------------------
2962 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
2963 UParseError
& parseError
,
2966 applyPattern(pattern
, FALSE
, parseError
, status
);
2968 //------------------------------------------------------------------------------
2971 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
2973 UParseError parseError
;
2974 applyPattern(pattern
, TRUE
,parseError
,status
);
2977 //------------------------------------------------------------------------------
2980 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
2981 UParseError
& parseError
,
2984 applyPattern(pattern
, TRUE
,parseError
,status
);
2987 //------------------------------------------------------------------------------
2990 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
2992 UParseError
& parseError
,
2995 if (U_FAILURE(status
))
2999 // Clear error struct
3000 parseError
.offset
= -1;
3001 parseError
.preContext
[0] = parseError
.postContext
[0] = (UChar
)0;
3003 // Set the significant pattern symbols
3004 UChar32 zeroDigit
= kPatternZeroDigit
; // '0'
3005 UChar32 sigDigit
= kPatternSignificantDigit
; // '@'
3006 UnicodeString
groupingSeparator ((UChar
)kPatternGroupingSeparator
);
3007 UnicodeString
decimalSeparator ((UChar
)kPatternDecimalSeparator
);
3008 UnicodeString
percent ((UChar
)kPatternPercent
);
3009 UnicodeString
perMill ((UChar
)kPatternPerMill
);
3010 UnicodeString
digit ((UChar
)kPatternDigit
); // '#'
3011 UnicodeString
separator ((UChar
)kPatternSeparator
);
3012 UnicodeString
exponent ((UChar
)kPatternExponent
);
3013 UnicodeString
plus ((UChar
)kPatternPlus
);
3014 UnicodeString
minus ((UChar
)kPatternMinus
);
3015 UnicodeString
padEscape ((UChar
)kPatternPadEscape
);
3016 // Substitute with the localized symbols if necessary
3018 zeroDigit
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
3019 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
3020 groupingSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
3021 decimalSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
));
3022 percent
. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
3023 perMill
. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
3024 digit
. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
3025 separator
. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
));
3026 exponent
. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
));
3027 plus
. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
));
3028 minus
. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
3029 padEscape
. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
3031 UChar nineDigit
= (UChar
)(zeroDigit
+ 9);
3032 int32_t digitLen
= digit
.length();
3033 int32_t groupSepLen
= groupingSeparator
.length();
3034 int32_t decimalSepLen
= decimalSeparator
.length();
3037 int32_t patLen
= pattern
.length();
3038 // Part 0 is the positive pattern. Part 1, if present, is the negative
3040 for (int32_t part
=0; part
<2 && pos
<patLen
; ++part
) {
3041 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
3042 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
3043 // between the prefix and suffix, and consists of pattern
3044 // characters. In the prefix and suffix, percent, perMill, and
3045 // currency symbols are recognized and translated.
3046 int32_t subpart
= 1, sub0Start
= 0, sub0Limit
= 0, sub2Limit
= 0;
3048 // It's important that we don't change any fields of this object
3049 // prematurely. We set the following variables for the multiplier,
3050 // grouping, etc., and then only change the actual object fields if
3051 // everything parses correctly. This also lets us register
3052 // the data from part 0 and ignore the part 1, except for the
3053 // prefix and suffix.
3054 UnicodeString prefix
;
3055 UnicodeString suffix
;
3056 int32_t decimalPos
= -1;
3057 int32_t multiplier
= 1;
3058 int32_t digitLeftCount
= 0, zeroDigitCount
= 0, digitRightCount
= 0, sigDigitCount
= 0;
3059 int8_t groupingCount
= -1;
3060 int8_t groupingCount2
= -1;
3061 int32_t padPos
= -1;
3062 UChar32 padChar
= 0;
3063 int32_t roundingPos
= -1;
3064 DigitList roundingInc
;
3065 int8_t expDigits
= -1;
3066 UBool expSignAlways
= FALSE
;
3067 UBool isCurrency
= FALSE
;
3069 // The affix is either the prefix or the suffix.
3070 UnicodeString
* affix
= &prefix
;
3072 int32_t start
= pos
;
3073 UBool isPartDone
= FALSE
;
3076 for (; !isPartDone
&& pos
< patLen
; ) {
3077 // Todo: account for surrogate pairs
3078 ch
= pattern
.char32At(pos
);
3080 case 0: // Pattern proper subpart (between prefix & suffix)
3081 // Process the digits, decimal, and grouping characters. We
3082 // record five pieces of information. We expect the digits
3083 // to occur in the pattern ####00.00####, and we record the
3084 // number of left digits, zero (central) digits, and right
3085 // digits. The position of the last grouping character is
3086 // recorded (should be somewhere within the first two blocks
3087 // of characters), as is the position of the decimal point,
3088 // if any (should be in the zero digits). If there is no
3089 // decimal point, then there should be no right digits.
3090 if (pattern
.compare(pos
, digitLen
, digit
) == 0) {
3091 if (zeroDigitCount
> 0 || sigDigitCount
> 0) {
3096 if (groupingCount
>= 0 && decimalPos
< 0) {
3100 } else if ((ch
>= zeroDigit
&& ch
<= nineDigit
) ||
3102 if (digitRightCount
> 0) {
3104 debug("Unexpected '0'")
3105 status
= U_UNEXPECTED_TOKEN
;
3106 syntaxError(pattern
,pos
,parseError
);
3109 if (ch
== sigDigit
) {
3113 if (ch
!= zeroDigit
&& roundingPos
< 0) {
3114 roundingPos
= digitLeftCount
+ zeroDigitCount
;
3116 if (roundingPos
>= 0) {
3117 roundingInc
.append((char)(ch
- zeroDigit
+ '0'));
3120 if (groupingCount
>= 0 && decimalPos
< 0) {
3123 pos
+= U16_LENGTH(ch
);
3124 } else if (pattern
.compare(pos
, groupSepLen
, groupingSeparator
) == 0) {
3125 if (decimalPos
>= 0) {
3126 // Grouping separator after decimal
3127 debug("Grouping separator after decimal")
3128 status
= U_UNEXPECTED_TOKEN
;
3129 syntaxError(pattern
,pos
,parseError
);
3132 groupingCount2
= groupingCount
;
3135 } else if (pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) == 0) {
3136 if (decimalPos
>= 0) {
3137 // Multiple decimal separators
3138 debug("Multiple decimal separators")
3139 status
= U_MULTIPLE_DECIMAL_SEPARATORS
;
3140 syntaxError(pattern
,pos
,parseError
);
3143 // Intentionally incorporate the digitRightCount,
3144 // even though it is illegal for this to be > 0
3145 // at this point. We check pattern syntax below.
3146 decimalPos
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
3147 pos
+= decimalSepLen
;
3149 if (pattern
.compare(pos
, exponent
.length(), exponent
) == 0) {
3150 if (expDigits
>= 0) {
3151 // Multiple exponential symbols
3152 debug("Multiple exponential symbols")
3153 status
= U_MULTIPLE_EXPONENTIAL_SYMBOLS
;
3154 syntaxError(pattern
,pos
,parseError
);
3157 if (groupingCount
>= 0) {
3158 // Grouping separator in exponential pattern
3159 debug("Grouping separator in exponential pattern")
3160 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
3161 syntaxError(pattern
,pos
,parseError
);
3164 pos
+= exponent
.length();
3165 // Check for positive prefix
3167 && pattern
.compare(pos
, plus
.length(), plus
) == 0) {
3168 expSignAlways
= TRUE
;
3169 pos
+= plus
.length();
3171 // Use lookahead to parse out the exponential part of the
3172 // pattern, then jump into suffix subpart.
3174 while (pos
< patLen
&&
3175 pattern
.char32At(pos
) == zeroDigit
) {
3177 pos
+= U16_LENGTH(zeroDigit
);
3180 // 1. Require at least one mantissa pattern digit
3181 // 2. Disallow "#+ @" in mantissa
3182 // 3. Require at least one exponent pattern digit
3183 if (((digitLeftCount
+ zeroDigitCount
) < 1 &&
3184 (sigDigitCount
+ digitRightCount
) < 1) ||
3185 (sigDigitCount
> 0 && digitLeftCount
> 0) ||
3187 // Malformed exponential pattern
3188 debug("Malformed exponential pattern")
3189 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
3190 syntaxError(pattern
,pos
,parseError
);
3194 // Transition to suffix subpart
3195 subpart
= 2; // suffix subpart
3201 case 1: // Prefix subpart
3202 case 2: // Suffix subpart
3203 // Process the prefix / suffix characters
3204 // Process unquoted characters seen in prefix or suffix
3207 // Several syntax characters implicitly begins the
3208 // next subpart if we are in the prefix; otherwise
3209 // they are illegal if unquoted.
3210 if (!pattern
.compare(pos
, digitLen
, digit
) ||
3211 !pattern
.compare(pos
, groupSepLen
, groupingSeparator
) ||
3212 !pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) ||
3213 (ch
>= zeroDigit
&& ch
<= nineDigit
) ||
3215 if (subpart
== 1) { // prefix subpart
3216 subpart
= 0; // pattern proper subpart
3217 sub0Start
= pos
; // Reprocess this character
3220 status
= U_UNQUOTED_SPECIAL
;
3221 syntaxError(pattern
,pos
,parseError
);
3224 } else if (ch
== kCurrencySign
) {
3225 affix
->append(kQuote
); // Encode currency
3226 // Use lookahead to determine if the currency sign is
3228 U_ASSERT(U16_LENGTH(kCurrencySign
) == 1);
3229 if ((pos
+1) < pattern
.length() && pattern
[pos
+1] == kCurrencySign
) {
3230 affix
->append(kCurrencySign
);
3231 ++pos
; // Skip over the doubled character
3234 // Fall through to append(ch)
3235 } else if (ch
== kQuote
) {
3236 // A quote outside quotes indicates either the opening
3237 // quote or two quotes, which is a quote literal. That is,
3238 // we have the first quote in 'do' or o''clock.
3239 U_ASSERT(U16_LENGTH(kQuote
) == 1);
3241 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
3242 affix
->append(kQuote
); // Encode quote
3243 // Fall through to append(ch)
3245 subpart
+= 2; // open quote
3248 } else if (pattern
.compare(pos
, separator
.length(), separator
) == 0) {
3249 // Don't allow separators in the prefix, and don't allow
3250 // separators in the second pattern (part == 1).
3251 if (subpart
== 1 || part
== 1) {
3252 // Unexpected separator
3253 debug("Unexpected separator")
3254 status
= U_UNEXPECTED_TOKEN
;
3255 syntaxError(pattern
,pos
,parseError
);
3259 isPartDone
= TRUE
; // Go to next part
3260 pos
+= separator
.length();
3262 } else if (pattern
.compare(pos
, percent
.length(), percent
) == 0) {
3263 // Next handle characters which are appended directly.
3264 if (multiplier
!= 1) {
3265 // Too many percent/perMill characters
3266 debug("Too many percent characters")
3267 status
= U_MULTIPLE_PERCENT_SYMBOLS
;
3268 syntaxError(pattern
,pos
,parseError
);
3271 affix
->append(kQuote
); // Encode percent/perMill
3272 affix
->append(kPatternPercent
); // Use unlocalized pattern char
3274 pos
+= percent
.length();
3276 } else if (pattern
.compare(pos
, perMill
.length(), perMill
) == 0) {
3277 // Next handle characters which are appended directly.
3278 if (multiplier
!= 1) {
3279 // Too many percent/perMill characters
3280 debug("Too many perMill characters")
3281 status
= U_MULTIPLE_PERMILL_SYMBOLS
;
3282 syntaxError(pattern
,pos
,parseError
);
3285 affix
->append(kQuote
); // Encode percent/perMill
3286 affix
->append(kPatternPerMill
); // Use unlocalized pattern char
3288 pos
+= perMill
.length();
3290 } else if (pattern
.compare(pos
, padEscape
.length(), padEscape
) == 0) {
3291 if (padPos
>= 0 || // Multiple pad specifiers
3292 (pos
+1) == pattern
.length()) { // Nothing after padEscape
3293 debug("Multiple pad specifiers")
3294 status
= U_MULTIPLE_PAD_SPECIFIERS
;
3295 syntaxError(pattern
,pos
,parseError
);
3299 pos
+= padEscape
.length();
3300 padChar
= pattern
.char32At(pos
);
3301 pos
+= U16_LENGTH(padChar
);
3303 } else if (pattern
.compare(pos
, minus
.length(), minus
) == 0) {
3304 affix
->append(kQuote
); // Encode minus
3305 affix
->append(kPatternMinus
);
3306 pos
+= minus
.length();
3308 } else if (pattern
.compare(pos
, plus
.length(), plus
) == 0) {
3309 affix
->append(kQuote
); // Encode plus
3310 affix
->append(kPatternPlus
);
3311 pos
+= plus
.length();
3314 // Unquoted, non-special characters fall through to here, as
3315 // well as other code which needs to append something to the
3318 pos
+= U16_LENGTH(ch
);
3320 case 3: // Prefix subpart, in quote
3321 case 4: // Suffix subpart, in quote
3322 // A quote within quotes indicates either the closing
3323 // quote or two quotes, which is a quote literal. That is,
3324 // we have the second quote in 'do' or 'don''t'.
3327 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
3328 affix
->append(kQuote
); // Encode quote
3329 // Fall through to append(ch)
3331 subpart
-= 2; // close quote
3336 pos
+= U16_LENGTH(ch
);
3341 if (sub0Limit
== 0) {
3342 sub0Limit
= pattern
.length();
3345 if (sub2Limit
== 0) {
3346 sub2Limit
= pattern
.length();
3349 /* Handle patterns with no '0' pattern character. These patterns
3350 * are legal, but must be recodified to make sense. "##.###" ->
3351 * "#0.###". ".###" -> ".0##".
3353 * We allow patterns of the form "####" to produce a zeroDigitCount
3354 * of zero (got that?); although this seems like it might make it
3355 * possible for format() to produce empty strings, format() checks
3356 * for this condition and outputs a zero digit in this situation.
3357 * Having a zeroDigitCount of zero yields a minimum integer digits
3358 * of zero, which allows proper round-trip patterns. We don't want
3359 * "#" to become "#0" when toPattern() is called (even though that's
3360 * what it really is, semantically).
3362 if (zeroDigitCount
== 0 && sigDigitCount
== 0 &&
3363 digitLeftCount
> 0 && decimalPos
>= 0) {
3364 // Handle "###.###" and "###." and ".###"
3367 ++n
; // Handle ".###"
3368 digitRightCount
= digitLeftCount
- n
;
3369 digitLeftCount
= n
- 1;
3373 // Do syntax checking on the digits, decimal points, and quotes.
3374 if ((decimalPos
< 0 && digitRightCount
> 0 && sigDigitCount
== 0) ||
3376 (sigDigitCount
> 0 ||
3377 decimalPos
< digitLeftCount
||
3378 decimalPos
> (digitLeftCount
+ zeroDigitCount
))) ||
3379 groupingCount
== 0 || groupingCount2
== 0 ||
3380 (sigDigitCount
> 0 && zeroDigitCount
> 0) ||
3382 { // subpart > 2 == unmatched quote
3383 debug("Syntax error")
3384 status
= U_PATTERN_SYNTAX_ERROR
;
3385 syntaxError(pattern
,pos
,parseError
);
3389 // Make sure pad is at legal position before or after affix.
3391 if (padPos
== start
) {
3392 padPos
= kPadBeforePrefix
;
3393 } else if (padPos
+2 == sub0Start
) {
3394 padPos
= kPadAfterPrefix
;
3395 } else if (padPos
== sub0Limit
) {
3396 padPos
= kPadBeforeSuffix
;
3397 } else if (padPos
+2 == sub2Limit
) {
3398 padPos
= kPadAfterSuffix
;
3400 // Illegal pad position
3401 debug("Illegal pad position")
3402 status
= U_ILLEGAL_PAD_POSITION
;
3403 syntaxError(pattern
,pos
,parseError
);
3409 delete fPosPrefixPattern
;
3410 delete fPosSuffixPattern
;
3411 delete fNegPrefixPattern
;
3412 delete fNegSuffixPattern
;
3413 fPosPrefixPattern
= new UnicodeString(prefix
);
3415 if (fPosPrefixPattern
== 0) {
3416 status
= U_MEMORY_ALLOCATION_ERROR
;
3419 fPosSuffixPattern
= new UnicodeString(suffix
);
3421 if (fPosSuffixPattern
== 0) {
3422 status
= U_MEMORY_ALLOCATION_ERROR
;
3423 delete fPosPrefixPattern
;
3426 fNegPrefixPattern
= 0;
3427 fNegSuffixPattern
= 0;
3429 fUseExponentialNotation
= (expDigits
>= 0);
3430 if (fUseExponentialNotation
) {
3431 fMinExponentDigits
= expDigits
;
3433 fExponentSignAlwaysShown
= expSignAlways
;
3434 fIsCurrencyFormat
= isCurrency
;
3435 int32_t digitTotalCount
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
3436 // The effectiveDecimalPos is the position the decimal is at or
3437 // would be at if there is no decimal. Note that if
3438 // decimalPos<0, then digitTotalCount == digitLeftCount +
3440 int32_t effectiveDecimalPos
= decimalPos
>= 0 ? decimalPos
: digitTotalCount
;
3441 UBool isSigDig
= (sigDigitCount
> 0);
3442 setSignificantDigitsUsed(isSigDig
);
3444 setMinimumSignificantDigits(sigDigitCount
);
3445 setMaximumSignificantDigits(sigDigitCount
+ digitRightCount
);
3447 int32_t minInt
= effectiveDecimalPos
- digitLeftCount
;
3448 setMinimumIntegerDigits(minInt
);
3449 setMaximumIntegerDigits(fUseExponentialNotation
3450 ? digitLeftCount
+ getMinimumIntegerDigits()
3451 : kDoubleIntegerDigits
);
3452 setMaximumFractionDigits(decimalPos
>= 0
3453 ? (digitTotalCount
- decimalPos
) : 0);
3454 setMinimumFractionDigits(decimalPos
>= 0
3455 ? (digitLeftCount
+ zeroDigitCount
- decimalPos
) : 0);
3457 setGroupingUsed(groupingCount
> 0);
3458 fGroupingSize
= (groupingCount
> 0) ? groupingCount
: 0;
3459 fGroupingSize2
= (groupingCount2
> 0 && groupingCount2
!= groupingCount
)
3460 ? groupingCount2
: 0;
3461 fMultiplier
= multiplier
;
3462 setDecimalSeparatorAlwaysShown(decimalPos
== 0
3463 || decimalPos
== digitTotalCount
);
3465 fPadPosition
= (EPadPosition
) padPos
;
3466 // To compute the format width, first set up sub0Limit -
3467 // sub0Start. Add in prefix/suffix length later.
3469 // fFormatWidth = prefix.length() + suffix.length() +
3470 // sub0Limit - sub0Start;
3471 fFormatWidth
= sub0Limit
- sub0Start
;
3476 if (roundingPos
>= 0) {
3477 roundingInc
.fDecimalAt
= effectiveDecimalPos
- roundingPos
;
3478 if (fRoundingIncrement
!= NULL
) {
3479 *fRoundingIncrement
= roundingInc
;
3481 fRoundingIncrement
= new DigitList(roundingInc
);
3483 if (fRoundingIncrement
== 0) {
3484 status
= U_MEMORY_ALLOCATION_ERROR
;
3485 delete fPosPrefixPattern
;
3486 delete fPosSuffixPattern
;
3490 fRoundingDouble
= fRoundingIncrement
->getDouble();
3491 fRoundingMode
= kRoundHalfEven
;
3493 setRoundingIncrement(0.0);
3496 fNegPrefixPattern
= new UnicodeString(prefix
);
3498 if (fNegPrefixPattern
== 0) {
3499 status
= U_MEMORY_ALLOCATION_ERROR
;
3502 fNegSuffixPattern
= new UnicodeString(suffix
);
3504 if (fNegSuffixPattern
== 0) {
3505 delete fNegPrefixPattern
;
3506 status
= U_MEMORY_ALLOCATION_ERROR
;
3512 if (pattern
.length() == 0) {
3513 delete fNegPrefixPattern
;
3514 delete fNegSuffixPattern
;
3515 fNegPrefixPattern
= NULL
;
3516 fNegSuffixPattern
= NULL
;
3517 if (fPosPrefixPattern
!= NULL
) {
3518 fPosPrefixPattern
->remove();
3520 fPosPrefixPattern
= new UnicodeString();
3522 if (fPosPrefixPattern
== 0) {
3523 status
= U_MEMORY_ALLOCATION_ERROR
;
3527 if (fPosSuffixPattern
!= NULL
) {
3528 fPosSuffixPattern
->remove();
3530 fPosSuffixPattern
= new UnicodeString();
3532 if (fPosSuffixPattern
== 0) {
3533 delete fPosPrefixPattern
;
3534 status
= U_MEMORY_ALLOCATION_ERROR
;
3539 setMinimumIntegerDigits(0);
3540 setMaximumIntegerDigits(kDoubleIntegerDigits
);
3541 setMinimumFractionDigits(0);
3542 setMaximumFractionDigits(kDoubleFractionDigits
);
3544 fUseExponentialNotation
= FALSE
;
3545 fIsCurrencyFormat
= FALSE
;
3546 setGroupingUsed(FALSE
);
3550 setDecimalSeparatorAlwaysShown(FALSE
);
3552 setRoundingIncrement(0.0);
3555 // If there was no negative pattern, or if the negative pattern is
3556 // identical to the positive pattern, then prepend the minus sign to the
3557 // positive pattern to form the negative pattern.
3558 if (fNegPrefixPattern
== NULL
||
3559 (*fNegPrefixPattern
== *fPosPrefixPattern
3560 && *fNegSuffixPattern
== *fPosSuffixPattern
)) {
3561 _copy_us_ptr(&fNegSuffixPattern
, fPosSuffixPattern
);
3562 if (fNegPrefixPattern
== NULL
) {
3563 fNegPrefixPattern
= new UnicodeString();
3565 if (fNegPrefixPattern
== 0) {
3566 status
= U_MEMORY_ALLOCATION_ERROR
;
3570 fNegPrefixPattern
->remove();
3572 fNegPrefixPattern
->append(kQuote
).append(kPatternMinus
)
3573 .append(*fPosPrefixPattern
);
3577 s
.append("\"").append(pattern
).append("\"->");
3581 if (fFormatWidth
> 0) {
3582 // Finish computing format width (see above)
3583 fFormatWidth
+= fPositivePrefix
.length() + fPositiveSuffix
.length();
3588 * Sets the maximum number of digits allowed in the integer portion of a
3589 * number. This override limits the integer digit count to 309.
3590 * @see NumberFormat#setMaximumIntegerDigits
3592 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
3593 NumberFormat::setMaximumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
3597 * Sets the minimum number of digits allowed in the integer portion of a
3598 * number. This override limits the integer digit count to 309.
3599 * @see NumberFormat#setMinimumIntegerDigits
3601 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
3602 NumberFormat::setMinimumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
3606 * Sets the maximum number of digits allowed in the fraction portion of a
3607 * number. This override limits the fraction digit count to 340.
3608 * @see NumberFormat#setMaximumFractionDigits
3610 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
3611 NumberFormat::setMaximumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
3615 * Sets the minimum number of digits allowed in the fraction portion of a
3616 * number. This override limits the fraction digit count to 340.
3617 * @see NumberFormat#setMinimumFractionDigits
3619 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
3620 NumberFormat::setMinimumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
3623 int32_t DecimalFormat::getMinimumSignificantDigits() const {
3624 return fMinSignificantDigits
;
3627 int32_t DecimalFormat::getMaximumSignificantDigits() const {
3628 return fMaxSignificantDigits
;
3631 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
3635 // pin max sig dig to >= min
3636 int32_t max
= _max(fMaxSignificantDigits
, min
);
3637 fMinSignificantDigits
= min
;
3638 fMaxSignificantDigits
= max
;
3641 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
3645 // pin min sig dig to 1..max
3646 U_ASSERT(fMinSignificantDigits
>= 1);
3647 int32_t min
= _min(fMinSignificantDigits
, max
);
3648 fMinSignificantDigits
= min
;
3649 fMaxSignificantDigits
= max
;
3652 UBool
DecimalFormat::areSignificantDigitsUsed() const {
3653 return fUseSignificantDigits
;
3656 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
3657 fUseSignificantDigits
= useSignificantDigits
;
3660 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
3661 // If we are a currency format, then modify our affixes to
3662 // encode the currency symbol for the given currency in our
3663 // locale, and adjust the decimal digits and rounding for the
3666 // Note: The code is ordered so that this object is *not changed*
3667 // until we are sure we are going to succeed.
3669 // NULL or empty currency is *legal* and indicates no currency.
3670 UBool isCurr
= (theCurrency
&& *theCurrency
);
3672 double rounding
= 0.0;
3674 if (fIsCurrencyFormat
&& isCurr
) {
3675 rounding
= ucurr_getRoundingIncrement(theCurrency
, &ec
);
3676 frac
= ucurr_getDefaultFractionDigits(theCurrency
, &ec
);
3679 NumberFormat::setCurrency(theCurrency
, ec
);
3680 if (U_FAILURE(ec
)) return;
3682 if (fIsCurrencyFormat
) {
3683 // NULL or empty currency is *legal* and indicates no currency.
3685 setRoundingIncrement(rounding
);
3686 setMinimumFractionDigits(frac
);
3687 setMaximumFractionDigits(frac
);
3693 // Deprecated variant with no UErrorCode parameter
3694 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
3695 UErrorCode ec
= U_ZERO_ERROR
;
3696 setCurrency(theCurrency
, ec
);
3699 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& /*ec*/) const {
3700 const UChar
* c
= getCurrency();
3702 const UnicodeString
&intl
=
3703 fSymbols
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3704 c
= intl
.getBuffer(); // ok for intl to go out of scope
3706 u_strncpy(result
, c
, 3);
3711 * Return the number of fraction digits to display, or the total
3712 * number of digits for significant digit formats and exponential
3716 DecimalFormat::precision(UBool isIntegral
) const {
3717 if (areSignificantDigitsUsed()) {
3718 return getMaximumSignificantDigits();
3719 } else if (fUseExponentialNotation
) {
3720 return getMinimumIntegerDigits() + getMaximumFractionDigits();
3722 return isIntegral
? 0 : getMaximumFractionDigits();
3728 #endif /* #if !UCONFIG_NO_FORMATTING */