2 *******************************************************************************
3 * Copyright (C) 1997-2011, 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
45 #include "unicode/decimfmt.h"
46 #include "unicode/choicfmt.h"
47 #include "unicode/ucurr.h"
48 #include "unicode/ustring.h"
49 #include "unicode/dcfmtsym.h"
50 #include "unicode/ures.h"
51 #include "unicode/uchar.h"
52 #include "unicode/uniset.h"
53 #include "unicode/curramt.h"
54 #include "unicode/currpinf.h"
55 #include "unicode/plurrule.h"
72 /* For currency parsing purose,
73 * Need to remember all prefix patterns and suffix patterns of
74 * every currency format pattern,
75 * including the pattern of default currecny style
76 * and plural currency style. And the patterns are set through applyPattern.
78 struct AffixPatternsForCurrency
: public UMemory
{
79 // negative prefix pattern
80 UnicodeString negPrefixPatternForCurrency
;
81 // negative suffix pattern
82 UnicodeString negSuffixPatternForCurrency
;
83 // positive prefix pattern
84 UnicodeString posPrefixPatternForCurrency
;
85 // positive suffix pattern
86 UnicodeString posSuffixPatternForCurrency
;
89 AffixPatternsForCurrency(const UnicodeString
& negPrefix
,
90 const UnicodeString
& negSuffix
,
91 const UnicodeString
& posPrefix
,
92 const UnicodeString
& posSuffix
,
94 negPrefixPatternForCurrency
= negPrefix
;
95 negSuffixPatternForCurrency
= negSuffix
;
96 posPrefixPatternForCurrency
= posPrefix
;
97 posSuffixPatternForCurrency
= posSuffix
;
102 /* affix for currency formatting when the currency sign in the pattern
103 * equals to 3, such as the pattern contains 3 currency sign or
104 * the formatter style is currency plural format style.
106 struct AffixesForCurrency
: public UMemory
{
108 UnicodeString negPrefixForCurrency
;
110 UnicodeString negSuffixForCurrency
;
112 UnicodeString posPrefixForCurrency
;
114 UnicodeString posSuffixForCurrency
;
118 AffixesForCurrency(const UnicodeString
& negPrefix
,
119 const UnicodeString
& negSuffix
,
120 const UnicodeString
& posPrefix
,
121 const UnicodeString
& posSuffix
) {
122 negPrefixForCurrency
= negPrefix
;
123 negSuffixForCurrency
= negSuffix
;
124 posPrefixForCurrency
= posPrefix
;
125 posSuffixForCurrency
= posSuffix
;
134 static UBool U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
);
139 static UBool U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
);
143 U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
) {
144 const AffixesForCurrency
* affix_1
=
145 (AffixesForCurrency
*)val1
.pointer
;
146 const AffixesForCurrency
* affix_2
=
147 (AffixesForCurrency
*)val2
.pointer
;
148 return affix_1
->negPrefixForCurrency
== affix_2
->negPrefixForCurrency
&&
149 affix_1
->negSuffixForCurrency
== affix_2
->negSuffixForCurrency
&&
150 affix_1
->posPrefixForCurrency
== affix_2
->posPrefixForCurrency
&&
151 affix_1
->posSuffixForCurrency
== affix_2
->posSuffixForCurrency
;
156 U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
) {
157 const AffixPatternsForCurrency
* affix_1
=
158 (AffixPatternsForCurrency
*)val1
.pointer
;
159 const AffixPatternsForCurrency
* affix_2
=
160 (AffixPatternsForCurrency
*)val2
.pointer
;
161 return affix_1
->negPrefixPatternForCurrency
==
162 affix_2
->negPrefixPatternForCurrency
&&
163 affix_1
->negSuffixPatternForCurrency
==
164 affix_2
->negSuffixPatternForCurrency
&&
165 affix_1
->posPrefixPatternForCurrency
==
166 affix_2
->posPrefixPatternForCurrency
&&
167 affix_1
->posSuffixPatternForCurrency
==
168 affix_2
->posSuffixPatternForCurrency
&&
169 affix_1
->patternType
== affix_2
->patternType
;
179 static void debugout(UnicodeString s
) {
181 s
.extract((int32_t) 0, s
.length(), buf
);
184 #define debug(x) printf("%s\n", x);
190 // Set to 1 to make leading zeroes be an error when doing a strict parse.
191 // Decided in ICU mtg 2010-04-21 that an error for leading zeros is wrong for
192 // strict parsing in both ICU4C & ICU4J, so this goes off (and ICU4J will be fixed).
193 #define CHECK_FOR_LEADING_ZERO 0
195 // *****************************************************************************
196 // class DecimalFormat
197 // *****************************************************************************
199 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat
)
201 // Constants for characters used in programmatic (unlocalized) patterns.
202 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
203 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
204 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
205 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
206 #define kPatternPerMill ((UChar)0x2030)
207 #define kPatternPercent ((UChar)0x0025) /*'%'*/
208 #define kPatternDigit ((UChar)0x0023) /*'#'*/
209 #define kPatternSeparator ((UChar)0x003B) /*';'*/
210 #define kPatternExponent ((UChar)0x0045) /*'E'*/
211 #define kPatternPlus ((UChar)0x002B) /*'+'*/
212 #define kPatternMinus ((UChar)0x002D) /*'-'*/
213 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
214 #define kQuote ((UChar)0x0027) /*'\''*/
216 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
217 * is used in patterns and substitued with either the currency symbol,
218 * or if it is doubled, with the international currency symbol. If the
219 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
220 * replaced with the monetary decimal separator.
222 #define kCurrencySign ((UChar)0x00A4)
223 #define kDefaultPad ((UChar)0x0020) /* */
225 const int32_t DecimalFormat::kDoubleIntegerDigits
= 309;
226 const int32_t DecimalFormat::kDoubleFractionDigits
= 340;
228 const int32_t DecimalFormat::kMaxScientificIntegerDigits
= 8;
231 * These are the tags we expect to see in normal resource bundle files associated
234 const char DecimalFormat::fgNumberPatterns
[]="NumberPatterns"; // Deprecated - not used
235 static const char fgNumberElements
[]="NumberElements";
236 static const char fgLatn
[]="latn";
237 static const char fgPatterns
[]="patterns";
238 static const char fgDecimalFormat
[]="decimalFormat";
239 static const char fgCurrencyFormat
[]="currencyFormat";
240 static const UChar fgTripleCurrencySign
[] = {0xA4, 0xA4, 0xA4, 0};
242 inline int32_t _min(int32_t a
, int32_t b
) { return (a
<b
) ? a
: b
; }
243 inline int32_t _max(int32_t a
, int32_t b
) { return (a
<b
) ? b
: a
; }
245 //------------------------------------------------------------------------------
246 // Constructs a DecimalFormat instance in the default locale.
248 DecimalFormat::DecimalFormat(UErrorCode
& status
) {
250 UParseError parseError
;
251 construct(status
, parseError
);
254 //------------------------------------------------------------------------------
255 // Constructs a DecimalFormat instance with the specified number format
256 // pattern in the default locale.
258 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
259 UErrorCode
& status
) {
261 UParseError parseError
;
262 construct(status
, parseError
, &pattern
);
265 //------------------------------------------------------------------------------
266 // Constructs a DecimalFormat instance with the specified number format
267 // pattern and the number format symbols in the default locale. The
268 // created instance owns the symbols.
270 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
271 DecimalFormatSymbols
* symbolsToAdopt
,
272 UErrorCode
& status
) {
274 UParseError parseError
;
275 if (symbolsToAdopt
== NULL
)
276 status
= U_ILLEGAL_ARGUMENT_ERROR
;
277 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
280 DecimalFormat::DecimalFormat( const UnicodeString
& pattern
,
281 DecimalFormatSymbols
* symbolsToAdopt
,
282 UParseError
& parseErr
,
283 UErrorCode
& status
) {
285 if (symbolsToAdopt
== NULL
)
286 status
= U_ILLEGAL_ARGUMENT_ERROR
;
287 construct(status
,parseErr
, &pattern
, symbolsToAdopt
);
290 //------------------------------------------------------------------------------
291 // Constructs a DecimalFormat instance with the specified number format
292 // pattern and the number format symbols in the default locale. The
293 // created instance owns the clone of the symbols.
295 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
296 const DecimalFormatSymbols
& symbols
,
297 UErrorCode
& status
) {
299 UParseError parseError
;
300 construct(status
, parseError
, &pattern
, new DecimalFormatSymbols(symbols
));
303 //------------------------------------------------------------------------------
304 // Constructs a DecimalFormat instance with the specified number format
305 // pattern, the number format symbols, and the number format style.
306 // The created instance owns the clone of the symbols.
308 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
309 DecimalFormatSymbols
* symbolsToAdopt
,
310 NumberFormat::EStyles style
,
311 UErrorCode
& status
) {
314 UParseError parseError
;
315 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
318 //-----------------------------------------------------------------------------
319 // Common DecimalFormat initialization.
320 // Put all fields of an uninitialized object into a known state.
321 // Common code, shared by all constructors.
323 DecimalFormat::init() {
324 fPosPrefixPattern
= 0;
325 fPosSuffixPattern
= 0;
326 fNegPrefixPattern
= 0;
327 fNegSuffixPattern
= 0;
332 fDecimalSeparatorAlwaysShown
= FALSE
;
334 fUseSignificantDigits
= FALSE
;
335 fMinSignificantDigits
= 1;
336 fMaxSignificantDigits
= 6;
337 fUseExponentialNotation
= FALSE
;
338 fMinExponentDigits
= 0;
339 fExponentSignAlwaysShown
= FALSE
;
340 fRoundingIncrement
= 0;
341 fRoundingMode
= kRoundHalfEven
;
344 fPadPosition
= kPadBeforePrefix
;
345 fStyle
= NumberFormat::kNumberStyle
;
346 fCurrencySignCount
= 0;
347 fAffixPatternsForCurrency
= NULL
;
348 fAffixesForCurrency
= NULL
;
349 fPluralAffixesForCurrency
= NULL
;
350 fCurrencyPluralInfo
= NULL
;
353 //------------------------------------------------------------------------------
354 // Constructs a DecimalFormat instance with the specified number format
355 // pattern and the number format symbols in the desired locale. The
356 // created instance owns the symbols.
359 DecimalFormat::construct(UErrorCode
& status
,
360 UParseError
& parseErr
,
361 const UnicodeString
* pattern
,
362 DecimalFormatSymbols
* symbolsToAdopt
)
364 fSymbols
= symbolsToAdopt
; // Do this BEFORE aborting on status failure!!!
365 fRoundingIncrement
= NULL
;
366 fRoundingMode
= kRoundHalfEven
;
367 fPad
= kPatternPadEscape
;
368 fPadPosition
= kPadBeforePrefix
;
369 if (U_FAILURE(status
))
372 fPosPrefixPattern
= fPosSuffixPattern
= NULL
;
373 fNegPrefixPattern
= fNegSuffixPattern
= NULL
;
377 fDecimalSeparatorAlwaysShown
= FALSE
;
378 fUseExponentialNotation
= FALSE
;
379 fMinExponentDigits
= 0;
381 if (fSymbols
== NULL
)
383 fSymbols
= new DecimalFormatSymbols(Locale::getDefault(), status
);
386 status
= U_MEMORY_ALLOCATION_ERROR
;
392 // Uses the default locale's number format pattern if there isn't
397 UResourceBundle
*resource
= ures_open(NULL
, Locale::getDefault().getName(), &status
);
399 resource
= ures_getByKey(resource
, fgNumberElements
, resource
, &status
);
400 // TODO : Get the pattern based on the active numbering system for the locale. Right now assumes "latn".
401 resource
= ures_getByKey(resource
, fgLatn
, resource
, &status
);
402 resource
= ures_getByKey(resource
, fgPatterns
, resource
, &status
);
403 const UChar
*resStr
= ures_getStringByKey(resource
, fgDecimalFormat
, &len
, &status
);
404 str
.setTo(TRUE
, resStr
, len
);
406 ures_close(resource
);
409 if (U_FAILURE(status
))
414 if (pattern
->indexOf((UChar
)kCurrencySign
) >= 0) {
415 // If it looks like we are going to use a currency pattern
416 // then do the time consuming lookup.
417 setCurrencyForSymbols();
419 setCurrencyInternally(NULL
, status
);
422 const UnicodeString
* patternUsed
;
423 UnicodeString currencyPluralPatternForOther
;
425 if (fStyle
== NumberFormat::kPluralCurrencyStyle
) {
426 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
427 if (U_FAILURE(status
)) {
431 // the pattern used in format is not fixed until formatting,
432 // in which, the number is known and
433 // will be used to pick the right pattern based on plural count.
434 // Here, set the pattern as the pattern of plural count == "other".
435 // For most locale, the patterns are probably the same for all
436 // plural count. If not, the right pattern need to be re-applied
438 fCurrencyPluralInfo
->getCurrencyPluralPattern("other", currencyPluralPatternForOther
);
439 patternUsed
= ¤cyPluralPatternForOther
;
441 setCurrencyForSymbols();
444 patternUsed
= pattern
;
447 if (patternUsed
->indexOf(kCurrencySign
) != -1) {
448 // initialize for currency, not only for plural format,
449 // but also for mix parsing
450 if (fCurrencyPluralInfo
== NULL
) {
451 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
452 if (U_FAILURE(status
)) {
456 // need it for mix parsing
457 setupCurrencyAffixPatterns(status
);
458 // expanded affixes for plural names
459 if (patternUsed
->indexOf(fgTripleCurrencySign
) != -1) {
460 setupCurrencyAffixes(*patternUsed
, TRUE
, TRUE
, status
);
464 applyPatternWithoutExpandAffix(*patternUsed
,FALSE
, parseErr
, status
);
467 if (fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
468 expandAffixAdjustWidth(NULL
);
471 // If it was a currency format, apply the appropriate rounding by
472 // resetting the currency. NOTE: this copies fCurrency on top of itself.
473 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
474 setCurrencyInternally(getCurrency(), status
);
480 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode
& status
) {
481 if (U_FAILURE(status
)) {
484 UParseError parseErr
;
485 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
486 if (U_FAILURE(status
)) {
490 // Save the default currency patterns of this locale.
491 // Here, chose onlyApplyPatternWithoutExpandAffix without
492 // expanding the affix patterns into affixes.
493 UnicodeString currencyPattern
;
494 UErrorCode error
= U_ZERO_ERROR
;
496 UResourceBundle
*resource
= ures_open(NULL
, fSymbols
->getLocale().getName(), &error
);
497 resource
= ures_getByKey(resource
, fgNumberElements
, resource
, &error
);
498 // TODO : Get the pattern based on the active numbering system for the locale. Right now assumes "latn".
499 resource
= ures_getByKey(resource
, fgLatn
, resource
, &error
);
500 resource
= ures_getByKey(resource
, fgPatterns
, resource
, &error
);
502 const UChar
*patResStr
= ures_getStringByKey(resource
, fgCurrencyFormat
, &patLen
, &error
);
503 ures_close(resource
);
505 if (U_SUCCESS(error
)) {
506 applyPatternWithoutExpandAffix(UnicodeString(patResStr
, patLen
), false,
508 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
514 fAffixPatternsForCurrency
->put("default", affixPtn
, status
);
517 // save the unique currency plural patterns of this locale.
518 Hashtable
* pluralPtn
= fCurrencyPluralInfo
->fPluralCountToCurrencyUnitPattern
;
519 const UHashElement
* element
= NULL
;
521 Hashtable pluralPatternSet
;
522 while ((element
= pluralPtn
->nextElement(pos
)) != NULL
) {
523 const UHashTok valueTok
= element
->value
;
524 const UnicodeString
* value
= (UnicodeString
*)valueTok
.pointer
;
525 const UHashTok keyTok
= element
->key
;
526 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
527 if (pluralPatternSet
.geti(*value
) != 1) {
528 pluralPatternSet
.puti(*value
, 1, status
);
529 applyPatternWithoutExpandAffix(*value
, false, parseErr
, status
);
530 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
536 fAffixPatternsForCurrency
->put(*key
, affixPtn
, status
);
543 DecimalFormat::setupCurrencyAffixes(const UnicodeString
& pattern
,
544 UBool setupForCurrentPattern
,
545 UBool setupForPluralPattern
,
546 UErrorCode
& status
) {
547 if (U_FAILURE(status
)) {
550 UParseError parseErr
;
551 if (setupForCurrentPattern
) {
552 if (fAffixesForCurrency
) {
553 deleteHashForAffix(fAffixesForCurrency
);
555 fAffixesForCurrency
= initHashForAffix(status
);
556 if (U_SUCCESS(status
)) {
557 applyPatternWithoutExpandAffix(pattern
, false, parseErr
, status
);
558 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
559 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
560 if (U_SUCCESS(status
)) {
561 const char* pluralCountCh
;
562 while ((pluralCountCh
= keywords
->next(NULL
, status
)) != NULL
) {
563 if ( U_SUCCESS(status
) ) {
564 UnicodeString pluralCount
= UnicodeString(pluralCountCh
);
565 expandAffixAdjustWidth(&pluralCount
);
566 AffixesForCurrency
* affix
= new AffixesForCurrency(
567 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
568 fAffixesForCurrency
->put(pluralCount
, affix
, status
);
576 if (U_FAILURE(status
)) {
580 if (setupForPluralPattern
) {
581 if (fPluralAffixesForCurrency
) {
582 deleteHashForAffix(fPluralAffixesForCurrency
);
584 fPluralAffixesForCurrency
= initHashForAffix(status
);
585 if (U_SUCCESS(status
)) {
586 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
587 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
588 if (U_SUCCESS(status
)) {
589 const char* pluralCountCh
;
590 while ((pluralCountCh
= keywords
->next(NULL
, status
)) != NULL
) {
591 if ( U_SUCCESS(status
) ) {
592 UnicodeString pluralCount
= UnicodeString(pluralCountCh
);
594 fCurrencyPluralInfo
->getCurrencyPluralPattern(pluralCount
, ptn
);
595 applyPatternInternally(pluralCount
, ptn
, false, parseErr
, status
);
596 AffixesForCurrency
* affix
= new AffixesForCurrency(
597 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
598 fPluralAffixesForCurrency
->put(pluralCount
, affix
, status
);
608 //------------------------------------------------------------------------------
610 DecimalFormat::~DecimalFormat()
612 delete fPosPrefixPattern
;
613 delete fPosSuffixPattern
;
614 delete fNegPrefixPattern
;
615 delete fNegSuffixPattern
;
616 delete fCurrencyChoice
;
619 delete fRoundingIncrement
;
620 deleteHashForAffixPattern();
621 deleteHashForAffix(fAffixesForCurrency
);
622 deleteHashForAffix(fPluralAffixesForCurrency
);
623 delete fCurrencyPluralInfo
;
626 //------------------------------------------------------------------------------
629 DecimalFormat::DecimalFormat(const DecimalFormat
&source
) :
630 NumberFormat(source
) {
635 //------------------------------------------------------------------------------
636 // assignment operator
638 static void _copy_us_ptr(UnicodeString
** pdest
, const UnicodeString
* source
) {
639 if (source
== NULL
) {
642 } else if (*pdest
== NULL
) {
643 *pdest
= new UnicodeString(*source
);
650 DecimalFormat::operator=(const DecimalFormat
& rhs
)
653 NumberFormat::operator=(rhs
);
654 fPositivePrefix
= rhs
.fPositivePrefix
;
655 fPositiveSuffix
= rhs
.fPositiveSuffix
;
656 fNegativePrefix
= rhs
.fNegativePrefix
;
657 fNegativeSuffix
= rhs
.fNegativeSuffix
;
658 _copy_us_ptr(&fPosPrefixPattern
, rhs
.fPosPrefixPattern
);
659 _copy_us_ptr(&fPosSuffixPattern
, rhs
.fPosSuffixPattern
);
660 _copy_us_ptr(&fNegPrefixPattern
, rhs
.fNegPrefixPattern
);
661 _copy_us_ptr(&fNegSuffixPattern
, rhs
.fNegSuffixPattern
);
662 if (rhs
.fCurrencyChoice
== 0) {
663 delete fCurrencyChoice
;
666 fCurrencyChoice
= (ChoiceFormat
*) rhs
.fCurrencyChoice
->clone();
668 setRoundingIncrement(rhs
.getRoundingIncrement());
669 fRoundingMode
= rhs
.fRoundingMode
;
670 setMultiplier(rhs
.getMultiplier());
671 fGroupingSize
= rhs
.fGroupingSize
;
672 fGroupingSize2
= rhs
.fGroupingSize2
;
673 fDecimalSeparatorAlwaysShown
= rhs
.fDecimalSeparatorAlwaysShown
;
674 if(fSymbols
== NULL
) {
675 fSymbols
= new DecimalFormatSymbols(*rhs
.fSymbols
);
677 *fSymbols
= *rhs
.fSymbols
;
679 fUseExponentialNotation
= rhs
.fUseExponentialNotation
;
680 fExponentSignAlwaysShown
= rhs
.fExponentSignAlwaysShown
;
681 /*Bertrand A. D. Update 98.03.17*/
682 fCurrencySignCount
= rhs
.fCurrencySignCount
;
684 fMinExponentDigits
= rhs
.fMinExponentDigits
;
687 fFormatWidth
= rhs
.fFormatWidth
;
689 fPadPosition
= rhs
.fPadPosition
;
691 fMinSignificantDigits
= rhs
.fMinSignificantDigits
;
692 fMaxSignificantDigits
= rhs
.fMaxSignificantDigits
;
693 fUseSignificantDigits
= rhs
.fUseSignificantDigits
;
694 fFormatPattern
= rhs
.fFormatPattern
;
696 fCurrencySignCount
= rhs
.fCurrencySignCount
;
697 if (rhs
.fCurrencyPluralInfo
) {
698 delete fCurrencyPluralInfo
;
699 fCurrencyPluralInfo
= rhs
.fCurrencyPluralInfo
->clone();
701 if (rhs
.fAffixPatternsForCurrency
) {
702 UErrorCode status
= U_ZERO_ERROR
;
703 deleteHashForAffixPattern();
704 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
705 copyHashForAffixPattern(rhs
.fAffixPatternsForCurrency
,
706 fAffixPatternsForCurrency
, status
);
708 if (rhs
.fAffixesForCurrency
) {
709 UErrorCode status
= U_ZERO_ERROR
;
710 deleteHashForAffix(fAffixesForCurrency
);
711 fAffixesForCurrency
= initHashForAffixPattern(status
);
712 copyHashForAffix(rhs
.fAffixesForCurrency
, fAffixesForCurrency
, status
);
714 if (rhs
.fPluralAffixesForCurrency
) {
715 UErrorCode status
= U_ZERO_ERROR
;
716 deleteHashForAffix(fPluralAffixesForCurrency
);
717 fPluralAffixesForCurrency
= initHashForAffixPattern(status
);
718 copyHashForAffix(rhs
.fPluralAffixesForCurrency
, fPluralAffixesForCurrency
, status
);
724 //------------------------------------------------------------------------------
727 DecimalFormat::operator==(const Format
& that
) const
732 // NumberFormat::operator== guarantees this cast is safe
733 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
736 // This code makes it easy to determine why two format objects that should
739 if (!NumberFormat::operator==(that
)) {
740 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
741 debug("NumberFormat::!=");
743 if (!((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
744 fPositivePrefix
== other
->fPositivePrefix
)
745 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
746 *fPosPrefixPattern
== *other
->fPosPrefixPattern
))) {
747 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
748 debug("Pos Prefix !=");
750 if (!((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
751 fPositiveSuffix
== other
->fPositiveSuffix
)
752 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
753 *fPosSuffixPattern
== *other
->fPosSuffixPattern
))) {
754 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
755 debug("Pos Suffix !=");
757 if (!((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
758 fNegativePrefix
== other
->fNegativePrefix
)
759 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
760 *fNegPrefixPattern
== *other
->fNegPrefixPattern
))) {
761 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
762 debug("Neg Prefix ");
763 if (fNegPrefixPattern
== NULL
) {
765 debugout(fNegativePrefix
);
768 debugout(*fNegPrefixPattern
);
771 if (other
->fNegPrefixPattern
== NULL
) {
773 debugout(other
->fNegativePrefix
);
776 debugout(*other
->fNegPrefixPattern
);
779 if (!((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
780 fNegativeSuffix
== other
->fNegativeSuffix
)
781 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
782 *fNegSuffixPattern
== *other
->fNegSuffixPattern
))) {
783 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
784 debug("Neg Suffix ");
785 if (fNegSuffixPattern
== NULL
) {
787 debugout(fNegativeSuffix
);
790 debugout(*fNegSuffixPattern
);
793 if (other
->fNegSuffixPattern
== NULL
) {
795 debugout(other
->fNegativeSuffix
);
798 debugout(*other
->fNegSuffixPattern
);
801 if (!((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
802 || (fRoundingIncrement
!= NULL
&&
803 other
->fRoundingIncrement
!= NULL
&&
804 *fRoundingIncrement
== *other
->fRoundingIncrement
))) {
805 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
806 debug("Rounding Increment !=");
808 if (getMultiplier() != other
->getMultiplier()) {
809 if (first
) { printf("[ "); first
= FALSE
; }
810 printf("Multiplier %ld != %ld", getMultiplier(), other
->getMultiplier());
812 if (fGroupingSize
!= other
->fGroupingSize
) {
813 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
814 printf("Grouping Size %ld != %ld", fGroupingSize
, other
->fGroupingSize
);
816 if (fGroupingSize2
!= other
->fGroupingSize2
) {
817 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
818 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2
, other
->fGroupingSize2
);
820 if (fDecimalSeparatorAlwaysShown
!= other
->fDecimalSeparatorAlwaysShown
) {
821 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
822 printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown
, other
->fDecimalSeparatorAlwaysShown
);
824 if (fUseExponentialNotation
!= other
->fUseExponentialNotation
) {
825 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
828 if (!(!fUseExponentialNotation
||
829 fMinExponentDigits
!= other
->fMinExponentDigits
)) {
830 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
831 debug("Exp Digits !=");
833 if (*fSymbols
!= *(other
->fSymbols
)) {
834 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
837 // TODO Add debug stuff for significant digits here
838 if (fUseSignificantDigits
!= other
->fUseSignificantDigits
) {
839 debug("fUseSignificantDigits !=");
841 if (fUseSignificantDigits
&&
842 fMinSignificantDigits
!= other
->fMinSignificantDigits
) {
843 debug("fMinSignificantDigits !=");
845 if (fUseSignificantDigits
&&
846 fMaxSignificantDigits
!= other
->fMaxSignificantDigits
) {
847 debug("fMaxSignificantDigits !=");
850 if (!first
) { printf(" ]"); }
851 if (fCurrencySignCount
!= other
->fCurrencySignCount
) {
852 debug("fCurrencySignCount !=");
854 if (fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
) {
855 debug("fCurrencyPluralInfo == ");
856 if (fCurrencyPluralInfo
== NULL
) {
857 debug("fCurrencyPluralInfo == NULL");
860 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
861 *fCurrencyPluralInfo
!= *(other
->fCurrencyPluralInfo
)) {
862 debug("fCurrencyPluralInfo !=");
864 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
== NULL
||
865 fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
!= NULL
) {
866 debug("fCurrencyPluralInfo one NULL, the other not");
868 if (fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
== NULL
) {
869 debug("fCurrencyPluralInfo == ");
874 return (NumberFormat::operator==(that
) &&
875 ((fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) ?
876 (fAffixPatternsForCurrency
->equals(*other
->fAffixPatternsForCurrency
)) :
877 (((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
878 fPositivePrefix
== other
->fPositivePrefix
)
879 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
880 *fPosPrefixPattern
== *other
->fPosPrefixPattern
)) &&
881 ((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
882 fPositiveSuffix
== other
->fPositiveSuffix
)
883 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
884 *fPosSuffixPattern
== *other
->fPosSuffixPattern
)) &&
885 ((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
886 fNegativePrefix
== other
->fNegativePrefix
)
887 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
888 *fNegPrefixPattern
== *other
->fNegPrefixPattern
)) &&
889 ((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
890 fNegativeSuffix
== other
->fNegativeSuffix
)
891 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
892 *fNegSuffixPattern
== *other
->fNegSuffixPattern
)))) &&
893 ((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
894 || (fRoundingIncrement
!= NULL
&&
895 other
->fRoundingIncrement
!= NULL
&&
896 *fRoundingIncrement
== *other
->fRoundingIncrement
)) &&
897 getMultiplier() == other
->getMultiplier() &&
898 fGroupingSize
== other
->fGroupingSize
&&
899 fGroupingSize2
== other
->fGroupingSize2
&&
900 fDecimalSeparatorAlwaysShown
== other
->fDecimalSeparatorAlwaysShown
&&
901 fUseExponentialNotation
== other
->fUseExponentialNotation
&&
902 (!fUseExponentialNotation
||
903 fMinExponentDigits
== other
->fMinExponentDigits
) &&
904 *fSymbols
== *(other
->fSymbols
) &&
905 fUseSignificantDigits
== other
->fUseSignificantDigits
&&
906 (!fUseSignificantDigits
||
907 (fMinSignificantDigits
== other
->fMinSignificantDigits
&&
908 fMaxSignificantDigits
== other
->fMaxSignificantDigits
)) &&
909 fCurrencySignCount
== other
->fCurrencySignCount
&&
910 ((fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
&&
911 fCurrencyPluralInfo
== NULL
) ||
912 (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
913 *fCurrencyPluralInfo
== *(other
->fCurrencyPluralInfo
))));
916 //------------------------------------------------------------------------------
919 DecimalFormat::clone() const
921 return new DecimalFormat(*this);
924 //------------------------------------------------------------------------------
927 DecimalFormat::format(int32_t number
,
928 UnicodeString
& appendTo
,
929 FieldPosition
& fieldPosition
) const
931 return format((int64_t)number
, appendTo
, fieldPosition
);
935 DecimalFormat::format(int32_t number
,
936 UnicodeString
& appendTo
,
937 FieldPositionIterator
* posIter
,
938 UErrorCode
& status
) const
940 return format((int64_t)number
, appendTo
, posIter
, status
);
943 //------------------------------------------------------------------------------
946 DecimalFormat::format(int64_t number
,
947 UnicodeString
& appendTo
,
948 FieldPosition
& fieldPosition
) const
950 FieldPositionOnlyHandler
handler(fieldPosition
);
951 return _format(number
, appendTo
, handler
);
955 DecimalFormat::format(int64_t number
,
956 UnicodeString
& appendTo
,
957 FieldPositionIterator
* posIter
,
958 UErrorCode
& status
) const
960 FieldPositionIteratorHandler
handler(posIter
, status
);
961 return _format(number
, appendTo
, handler
);
965 DecimalFormat::_format(int64_t number
,
966 UnicodeString
& appendTo
,
967 FieldPositionHandler
& handler
) const
969 UErrorCode status
= U_ZERO_ERROR
;
972 return _format(digits
, appendTo
, handler
, status
);
975 //------------------------------------------------------------------------------
978 DecimalFormat::format( double number
,
979 UnicodeString
& appendTo
,
980 FieldPosition
& fieldPosition
) const
982 FieldPositionOnlyHandler
handler(fieldPosition
);
983 return _format(number
, appendTo
, handler
);
987 DecimalFormat::format( double number
,
988 UnicodeString
& appendTo
,
989 FieldPositionIterator
* posIter
,
990 UErrorCode
& status
) const
992 FieldPositionIteratorHandler
handler(posIter
, status
);
993 return _format(number
, appendTo
, handler
);
997 DecimalFormat::_format( double number
,
998 UnicodeString
& appendTo
,
999 FieldPositionHandler
& handler
) const
1001 // Special case for NaN, sets the begin and end index to be the
1002 // the string length of localized name of NaN.
1003 // TODO: let NaNs go through DigitList.
1004 if (uprv_isNaN(number
))
1006 int begin
= appendTo
.length();
1007 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1009 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1011 addPadding(appendTo
, handler
, 0, 0);
1015 UErrorCode status
= U_ZERO_ERROR
;
1018 _format(digits
, appendTo
, handler
, status
);
1019 // No way to return status from here.
1023 //------------------------------------------------------------------------------
1027 DecimalFormat::format(const StringPiece
&number
,
1028 UnicodeString
&toAppendTo
,
1029 FieldPositionIterator
*posIter
,
1030 UErrorCode
&status
) const
1033 dnum
.set(number
, status
);
1034 if (U_FAILURE(status
)) {
1037 FieldPositionIteratorHandler
handler(posIter
, status
);
1038 _format(dnum
, toAppendTo
, handler
, status
);
1044 DecimalFormat::format(const DigitList
&number
,
1045 UnicodeString
&appendTo
,
1046 FieldPositionIterator
*posIter
,
1047 UErrorCode
&status
) const {
1048 FieldPositionIteratorHandler
handler(posIter
, status
);
1049 _format(number
, appendTo
, handler
, status
);
1056 DecimalFormat::format(const DigitList
&number
,
1057 UnicodeString
& appendTo
,
1059 UErrorCode
&status
) const {
1060 FieldPositionOnlyHandler
handler(pos
);
1061 _format(number
, appendTo
, handler
, status
);
1068 DecimalFormat::_format(const DigitList
&number
,
1069 UnicodeString
& appendTo
,
1070 FieldPositionHandler
& handler
,
1071 UErrorCode
&status
) const
1073 // Special case for NaN, sets the begin and end index to be the
1074 // the string length of localized name of NaN.
1077 int begin
= appendTo
.length();
1078 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1080 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1082 addPadding(appendTo
, handler
, 0, 0);
1086 // Do this BEFORE checking to see if value is infinite or negative! Sets the
1087 // begin and end index to be length of the string composed of
1088 // localized name of Infinite and the positive/negative localized
1091 DigitList
adjustedNum(number
); // Copy, so we do not alter the original.
1092 adjustedNum
.setRoundingMode(fRoundingMode
);
1093 if (fMultiplier
!= NULL
) {
1094 adjustedNum
.mult(*fMultiplier
, status
);
1098 * Note: sign is important for zero as well as non-zero numbers.
1099 * Proper detection of -0.0 is needed to deal with the
1100 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
1102 UBool isNegative
= !adjustedNum
.isPositive();
1104 // Apply rounding after multiplier
1105 if (fRoundingIncrement
!= NULL
) {
1106 adjustedNum
.div(*fRoundingIncrement
, status
);
1107 adjustedNum
.toIntegralValue();
1108 adjustedNum
.mult(*fRoundingIncrement
, status
);
1112 // Special case for INFINITE,
1113 if (adjustedNum
.isInfinite()) {
1114 int32_t prefixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, TRUE
);
1116 int begin
= appendTo
.length();
1117 appendTo
+= getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1119 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1121 int32_t suffixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, FALSE
);
1123 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1127 if (fUseExponentialNotation
|| areSignificantDigitsUsed()) {
1128 int32_t sigDigits
= precision();
1129 if (sigDigits
> 0) {
1130 adjustedNum
.round(sigDigits
);
1133 // Fixed point format. Round to a set number of fraction digits.
1134 int32_t numFractionDigits
= precision();
1135 adjustedNum
.roundFixedPoint(numFractionDigits
);
1138 return subformat(appendTo
, handler
, adjustedNum
, FALSE
);
1143 DecimalFormat::format( const Formattable
& obj
,
1144 UnicodeString
& appendTo
,
1145 FieldPosition
& fieldPosition
,
1146 UErrorCode
& status
) const
1148 return NumberFormat::format(obj
, appendTo
, fieldPosition
, status
);
1152 * Return true if a grouping separator belongs at the given
1153 * position, based on whether grouping is in use and the values of
1154 * the primary and secondary grouping interval.
1155 * @param pos the number of integer digits to the right of
1156 * the current position. Zero indicates the position after the
1157 * rightmost integer digit.
1158 * @return true if a grouping character belongs at the current
1161 UBool
DecimalFormat::isGroupingPosition(int32_t pos
) const {
1162 UBool result
= FALSE
;
1163 if (isGroupingUsed() && (pos
> 0) && (fGroupingSize
> 0)) {
1164 if ((fGroupingSize2
> 0) && (pos
> fGroupingSize
)) {
1165 result
= ((pos
- fGroupingSize
) % fGroupingSize2
) == 0;
1167 result
= pos
% fGroupingSize
== 0;
1173 //------------------------------------------------------------------------------
1176 * Complete the formatting of a finite number. On entry, the DigitList must
1177 * be filled in with the correct digits.
1180 DecimalFormat::subformat(UnicodeString
& appendTo
,
1181 FieldPositionHandler
& handler
,
1183 UBool isInteger
) const
1186 // DigitList returns digits as '0' thru '9', so we will need to
1187 // always need to subtract the character 0 to get the numeric value to use for indexing.
1189 UChar32 localizedDigits
[10];
1190 localizedDigits
[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1191 localizedDigits
[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol
).char32At(0);
1192 localizedDigits
[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol
).char32At(0);
1193 localizedDigits
[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol
).char32At(0);
1194 localizedDigits
[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol
).char32At(0);
1195 localizedDigits
[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol
).char32At(0);
1196 localizedDigits
[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol
).char32At(0);
1197 localizedDigits
[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol
).char32At(0);
1198 localizedDigits
[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol
).char32At(0);
1199 localizedDigits
[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol
).char32At(0);
1201 const UnicodeString
*grouping
;
1202 if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1203 grouping
= &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
1205 grouping
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1207 const UnicodeString
*decimal
;
1208 if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1209 decimal
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1211 decimal
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1213 UBool useSigDig
= areSignificantDigitsUsed();
1214 int32_t maxIntDig
= getMaximumIntegerDigits();
1215 int32_t minIntDig
= getMinimumIntegerDigits();
1217 // Appends the prefix.
1218 double doubleValue
= digits
.getDouble();
1219 int32_t prefixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), TRUE
);
1221 if (fUseExponentialNotation
)
1223 int currentLength
= appendTo
.length();
1224 int intBegin
= currentLength
;
1228 int32_t minFracDig
= 0;
1230 maxIntDig
= minIntDig
= 1;
1231 minFracDig
= getMinimumSignificantDigits() - 1;
1233 minFracDig
= getMinimumFractionDigits();
1234 if (maxIntDig
> kMaxScientificIntegerDigits
) {
1236 if (maxIntDig
< minIntDig
) {
1237 maxIntDig
= minIntDig
;
1240 if (maxIntDig
> minIntDig
) {
1245 // Minimum integer digits are handled in exponential format by
1246 // adjusting the exponent. For example, 0.01234 with 3 minimum
1247 // integer digits is "123.4E-4".
1249 // Maximum integer digits are interpreted as indicating the
1250 // repeating range. This is useful for engineering notation, in
1251 // which the exponent is restricted to a multiple of 3. For
1252 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1253 // If maximum integer digits are defined and are larger than
1254 // minimum integer digits, then minimum integer digits are
1256 digits
.reduce(); // Removes trailing zero digits.
1257 int32_t exponent
= digits
.getDecimalAt();
1258 if (maxIntDig
> 1 && maxIntDig
!= minIntDig
) {
1259 // A exponent increment is defined; adjust to it.
1260 exponent
= (exponent
> 0) ? (exponent
- 1) / maxIntDig
1261 : (exponent
/ maxIntDig
) - 1;
1262 exponent
*= maxIntDig
;
1264 // No exponent increment is defined; use minimum integer digits.
1265 // If none is specified, as in "#E0", generate 1 integer digit.
1266 exponent
-= (minIntDig
> 0 || minFracDig
> 0)
1270 // We now output a minimum number of digits, and more if there
1271 // are more digits, up to the maximum number of digits. We
1272 // place the decimal point after the "integer" digits, which
1273 // are the first (decimalAt - exponent) digits.
1274 int32_t minimumDigits
= minIntDig
+ minFracDig
;
1275 // The number of integer digits is handled specially if the number
1276 // is zero, since then there may be no digits.
1277 int32_t integerDigits
= digits
.isZero() ? minIntDig
:
1278 digits
.getDecimalAt() - exponent
;
1279 int32_t totalDigits
= digits
.getCount();
1280 if (minimumDigits
> totalDigits
)
1281 totalDigits
= minimumDigits
;
1282 if (integerDigits
> totalDigits
)
1283 totalDigits
= integerDigits
;
1285 // totalDigits records total number of digits needs to be processed
1287 for (i
=0; i
<totalDigits
; ++i
)
1289 if (i
== integerDigits
)
1291 intEnd
= appendTo
.length();
1292 handler
.addAttribute(kIntegerField
, intBegin
, intEnd
);
1294 appendTo
+= *decimal
;
1296 fracBegin
= appendTo
.length();
1297 handler
.addAttribute(kDecimalSeparatorField
, fracBegin
- 1, fracBegin
);
1299 // Restores the digit character or pads the buffer with zeros.
1300 UChar32 c
= (UChar32
)((i
< digits
.getCount()) ?
1301 localizedDigits
[digits
.getDigitValue(i
)] :
1302 localizedDigits
[0]);
1306 currentLength
= appendTo
.length();
1309 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1311 if (fracBegin
> 0) {
1312 handler
.addAttribute(kFractionField
, fracBegin
, currentLength
);
1315 // The exponent is output using the pattern-specified minimum
1316 // exponent digits. There is no maximum limit to the exponent
1317 // digits, since truncating the exponent would appendTo in an
1318 // unacceptable inaccuracy.
1319 appendTo
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1321 handler
.addAttribute(kExponentSymbolField
, currentLength
, appendTo
.length());
1322 currentLength
= appendTo
.length();
1324 // For zero values, we force the exponent to zero. We
1325 // must do this here, and not earlier, because the value
1326 // is used to determine integer digit count above.
1327 if (digits
.isZero())
1331 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1332 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1333 } else if (fExponentSignAlwaysShown
) {
1334 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1335 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1338 currentLength
= appendTo
.length();
1340 DigitList expDigits
;
1341 expDigits
.set(exponent
);
1343 int expDig
= fMinExponentDigits
;
1344 if (fUseExponentialNotation
&& expDig
< 1) {
1347 for (i
=expDigits
.getDecimalAt(); i
<expDig
; ++i
)
1348 appendTo
+= (localizedDigits
[0]);
1350 for (i
=0; i
<expDigits
.getDecimalAt(); ++i
)
1352 UChar32 c
= (UChar32
)((i
< expDigits
.getCount()) ?
1353 localizedDigits
[expDigits
.getDigitValue(i
)] :
1354 localizedDigits
[0]);
1358 handler
.addAttribute(kExponentField
, currentLength
, appendTo
.length());
1360 else // Not using exponential notation
1362 int currentLength
= appendTo
.length();
1363 int intBegin
= currentLength
;
1365 int32_t sigCount
= 0;
1366 int32_t minSigDig
= getMinimumSignificantDigits();
1367 int32_t maxSigDig
= getMaximumSignificantDigits();
1370 maxSigDig
= INT32_MAX
;
1373 // Output the integer portion. Here 'count' is the total
1374 // number of integer digits we will display, including both
1375 // leading zeros required to satisfy getMinimumIntegerDigits,
1376 // and actual digits present in the number.
1377 int32_t count
= useSigDig
?
1378 _max(1, digits
.getDecimalAt()) : minIntDig
;
1379 if (digits
.getDecimalAt() > 0 && count
< digits
.getDecimalAt()) {
1380 count
= digits
.getDecimalAt();
1383 // Handle the case where getMaximumIntegerDigits() is smaller
1384 // than the real number of integer digits. If this is so, we
1385 // output the least significant max integer digits. For example,
1386 // the value 1997 printed with 2 max integer digits is just "97".
1388 int32_t digitIndex
= 0; // Index into digitList.fDigits[]
1389 if (count
> maxIntDig
&& maxIntDig
>= 0) {
1391 digitIndex
= digits
.getDecimalAt() - count
;
1394 int32_t sizeBeforeIntegerPart
= appendTo
.length();
1397 for (i
=count
-1; i
>=0; --i
)
1399 if (i
< digits
.getDecimalAt() && digitIndex
< digits
.getCount() &&
1400 sigCount
< maxSigDig
) {
1401 // Output a real digit
1402 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
1407 // Output a zero (leading or trailing)
1408 appendTo
+= localizedDigits
[0];
1414 // Output grouping separator if necessary.
1415 if (isGroupingPosition(i
)) {
1416 currentLength
= appendTo
.length();
1417 appendTo
.append(*grouping
);
1418 handler
.addAttribute(kGroupingSeparatorField
, currentLength
, appendTo
.length());
1422 // TODO(dlf): this looks like it was a bug, we marked the int field as ending
1423 // before the zero was generated.
1424 // Record field information for caller.
1425 // if (fieldPosition.getField() == NumberFormat::kIntegerField)
1426 // fieldPosition.setEndIndex(appendTo.length());
1428 // Determine whether or not there are any printable fractional
1429 // digits. If we've used up the digits we know there aren't.
1430 UBool fractionPresent
= (!isInteger
&& digitIndex
< digits
.getCount()) ||
1431 (useSigDig
? (sigCount
< minSigDig
) : (getMinimumFractionDigits() > 0));
1433 // If there is no fraction present, and we haven't printed any
1434 // integer digits, then print a zero. Otherwise we won't print
1435 // _any_ digits, and we won't be able to parse this string.
1436 if (!fractionPresent
&& appendTo
.length() == sizeBeforeIntegerPart
)
1437 appendTo
+= localizedDigits
[0];
1439 currentLength
= appendTo
.length();
1440 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1442 // Output the decimal separator if we always do so.
1443 if (fDecimalSeparatorAlwaysShown
|| fractionPresent
) {
1444 appendTo
+= *decimal
;
1445 handler
.addAttribute(kDecimalSeparatorField
, currentLength
, appendTo
.length());
1446 currentLength
= appendTo
.length();
1449 int fracBegin
= currentLength
;
1451 count
= useSigDig
? INT32_MAX
: getMaximumFractionDigits();
1452 if (useSigDig
&& (sigCount
== maxSigDig
||
1453 (sigCount
>= minSigDig
&& digitIndex
== digits
.getCount()))) {
1457 for (i
=0; i
< count
; ++i
) {
1458 // Here is where we escape from the loop. We escape
1459 // if we've output the maximum fraction digits
1460 // (specified in the for expression above). We also
1461 // stop when we've output the minimum digits and
1462 // either: we have an integer, so there is no
1463 // fractional stuff to display, or we're out of
1464 // significant digits.
1465 if (!useSigDig
&& i
>= getMinimumFractionDigits() &&
1466 (isInteger
|| digitIndex
>= digits
.getCount())) {
1470 // Output leading fractional zeros. These are zeros
1471 // that come after the decimal but before any
1472 // significant digits. These are only output if
1473 // abs(number being formatted) < 1.0.
1474 if (-1-i
> (digits
.getDecimalAt()-1)) {
1475 appendTo
+= localizedDigits
[0];
1479 // Output a digit, if we have any precision left, or a
1480 // zero if we don't. We don't want to output noise digits.
1481 if (!isInteger
&& digitIndex
< digits
.getCount()) {
1482 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
1484 appendTo
+= localizedDigits
[0];
1487 // If we reach the maximum number of significant
1488 // digits, or if we output all the real digits and
1489 // reach the minimum, then we are done.
1492 (sigCount
== maxSigDig
||
1493 (digitIndex
== digits
.getCount() && sigCount
>= minSigDig
))) {
1498 handler
.addAttribute(kFractionField
, fracBegin
, appendTo
.length());
1501 int32_t suffixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), FALSE
);
1503 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1508 * Inserts the character fPad as needed to expand result to fFormatWidth.
1509 * @param result the string to be padded
1511 void DecimalFormat::addPadding(UnicodeString
& appendTo
,
1512 FieldPositionHandler
& handler
,
1514 int32_t suffixLen
) const
1516 if (fFormatWidth
> 0) {
1517 int32_t len
= fFormatWidth
- appendTo
.length();
1519 UnicodeString padding
;
1520 for (int32_t i
=0; i
<len
; ++i
) {
1523 switch (fPadPosition
) {
1524 case kPadAfterPrefix
:
1525 appendTo
.insert(prefixLen
, padding
);
1527 case kPadBeforePrefix
:
1528 appendTo
.insert(0, padding
);
1530 case kPadBeforeSuffix
:
1531 appendTo
.insert(appendTo
.length() - suffixLen
, padding
);
1533 case kPadAfterSuffix
:
1534 appendTo
+= padding
;
1537 if (fPadPosition
== kPadBeforePrefix
|| fPadPosition
== kPadAfterPrefix
) {
1538 handler
.shiftLast(len
);
1544 //------------------------------------------------------------------------------
1547 DecimalFormat::parse(const UnicodeString
& text
,
1548 Formattable
& result
,
1549 UErrorCode
& status
) const
1551 NumberFormat::parse(text
, result
, status
);
1555 DecimalFormat::parse(const UnicodeString
& text
,
1556 Formattable
& result
,
1557 ParsePosition
& parsePosition
) const {
1558 parse(text
, result
, parsePosition
, FALSE
);
1561 Formattable
& DecimalFormat::parseCurrency(const UnicodeString
& text
,
1562 Formattable
& result
,
1563 ParsePosition
& pos
) const {
1564 parse(text
, result
, pos
, TRUE
);
1569 * Parses the given text as either a number or a currency amount.
1570 * @param text the string to parse
1571 * @param result output parameter for the result
1572 * @param parsePosition input-output position; on input, the
1573 * position within text to match; must have 0 <= pos.getIndex() <
1574 * text.length(); on output, the position after the last matched
1575 * character. If the parse fails, the position in unchanged upon
1577 * @param parseCurrency if true, a currency amount is parsed;
1578 * otherwise a Number is parsed
1580 void DecimalFormat::parse(const UnicodeString
& text
,
1581 Formattable
& result
,
1582 ParsePosition
& parsePosition
,
1583 UBool parseCurrency
) const {
1585 int32_t i
= backup
= parsePosition
.getIndex();
1587 // clear any old contents in the result. In particular, clears any DigitList
1588 // that it may be holding.
1591 // Handle NaN as a special case:
1593 // Skip padding characters, if around prefix
1594 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforePrefix
||
1595 fPadPosition
== kPadAfterPrefix
)) {
1596 i
= skipPadding(text
, i
);
1599 if (! isParseStrict()) {
1600 // skip any leading whitespace
1601 i
= backup
= skipUWhiteSpace(text
, i
);
1604 // If the text is composed of the representation of NaN, returns NaN.length
1605 const UnicodeString
*nan
= &getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1606 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
1607 ? 0 : nan
->length());
1610 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforeSuffix
||
1611 fPadPosition
== kPadAfterSuffix
)) {
1612 i
= skipPadding(text
, i
);
1614 parsePosition
.setIndex(i
);
1615 result
.setDouble(uprv_getNaN());
1619 // NaN parse failed; start over
1621 parsePosition
.setIndex(i
);
1623 // status is used to record whether a number is infinite.
1624 UBool status
[fgStatusLength
];
1626 UChar
* currency
= parseCurrency
? curbuf
: NULL
;
1627 DigitList
*digits
= new DigitList
;
1628 if (digits
== NULL
) {
1629 return; // no way to report error from here.
1632 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
1633 if (!parseForCurrency(text
, parsePosition
, *digits
,
1634 status
, currency
)) {
1640 fNegPrefixPattern
, fNegSuffixPattern
,
1641 fPosPrefixPattern
, fPosSuffixPattern
,
1642 FALSE
, UCURR_SYMBOL_NAME
,
1643 parsePosition
, *digits
, status
, currency
)) {
1644 parsePosition
.setIndex(backup
);
1651 if (status
[fgStatusInfinite
]) {
1652 double inf
= uprv_getInfinity();
1653 result
.setDouble(digits
->isPositive() ? inf
: -inf
);
1654 delete digits
; // TODO: set the dl to infinity, and let it fall into the code below.
1659 if (fMultiplier
!= NULL
) {
1660 UErrorCode ec
= U_ZERO_ERROR
;
1661 digits
->div(*fMultiplier
, ec
);
1664 // Negative zero special case:
1665 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1666 // if not parsing integerOnly, leave as -0, which a double can represent.
1667 if (digits
->isZero() && !digits
->isPositive() && isParseIntegerOnly()) {
1668 digits
->setPositive(TRUE
);
1670 result
.adoptDigitList(digits
);
1673 if (parseCurrency
) {
1674 UErrorCode ec
= U_ZERO_ERROR
;
1675 Formattable
n(result
);
1676 result
.adoptObject(new CurrencyAmount(n
, curbuf
, ec
));
1677 U_ASSERT(U_SUCCESS(ec
)); // should always succeed
1684 DecimalFormat::parseForCurrency(const UnicodeString
& text
,
1685 ParsePosition
& parsePosition
,
1688 UChar
* currency
) const {
1689 int origPos
= parsePosition
.getIndex();
1690 int maxPosIndex
= origPos
;
1691 int maxErrorPos
= -1;
1692 // First, parse against current pattern.
1693 // Since current pattern could be set by applyPattern(),
1694 // it could be an arbitrary pattern, and it may not be the one
1695 // defined in current locale.
1696 UBool tmpStatus
[fgStatusLength
];
1697 ParsePosition
tmpPos(origPos
);
1698 DigitList tmpDigitList
;
1700 if (fStyle
== NumberFormat::kPluralCurrencyStyle
) {
1701 found
= subparse(text
,
1702 fNegPrefixPattern
, fNegSuffixPattern
,
1703 fPosPrefixPattern
, fPosSuffixPattern
,
1704 TRUE
, UCURR_LONG_NAME
,
1705 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1707 found
= subparse(text
,
1708 fNegPrefixPattern
, fNegSuffixPattern
,
1709 fPosPrefixPattern
, fPosSuffixPattern
,
1710 TRUE
, UCURR_SYMBOL_NAME
,
1711 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1714 if (tmpPos
.getIndex() > maxPosIndex
) {
1715 maxPosIndex
= tmpPos
.getIndex();
1716 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1717 status
[i
] = tmpStatus
[i
];
1719 digits
= tmpDigitList
;
1722 maxErrorPos
= tmpPos
.getErrorIndex();
1724 // Then, parse against affix patterns.
1725 // Those are currency patterns and currency plural patterns.
1727 const UHashElement
* element
= NULL
;
1728 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
1729 const UHashTok keyTok
= element
->key
;
1730 const UHashTok valueTok
= element
->value
;
1731 const AffixPatternsForCurrency
* affixPtn
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
1732 UBool tmpStatus
[fgStatusLength
];
1733 ParsePosition
tmpPos(origPos
);
1734 DigitList tmpDigitList
;
1735 UBool result
= subparse(text
,
1736 &affixPtn
->negPrefixPatternForCurrency
,
1737 &affixPtn
->negSuffixPatternForCurrency
,
1738 &affixPtn
->posPrefixPatternForCurrency
,
1739 &affixPtn
->posSuffixPatternForCurrency
,
1740 TRUE
, affixPtn
->patternType
,
1741 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1744 if (tmpPos
.getIndex() > maxPosIndex
) {
1745 maxPosIndex
= tmpPos
.getIndex();
1746 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1747 status
[i
] = tmpStatus
[i
];
1749 digits
= tmpDigitList
;
1752 maxErrorPos
= (tmpPos
.getErrorIndex() > maxErrorPos
) ?
1753 tmpPos
.getErrorIndex() : maxErrorPos
;
1756 // Finally, parse against simple affix to find the match.
1757 // For example, in TestMonster suite,
1758 // if the to-be-parsed text is "-\u00A40,00".
1759 // complexAffixCompare will not find match,
1760 // since there is no ISO code matches "\u00A4",
1761 // and the parse stops at "\u00A4".
1762 // We will just use simple affix comparison (look for exact match)
1764 UBool tmpStatus_2
[fgStatusLength
];
1765 ParsePosition
tmpPos_2(origPos
);
1766 DigitList tmpDigitList_2
;
1767 // set currencySignCount to 0 so that compareAffix function will
1768 // fall to compareSimpleAffix path, not compareComplexAffix path.
1769 // ?? TODO: is it right? need "false"?
1770 UBool result
= subparse(text
,
1771 &fNegativePrefix
, &fNegativeSuffix
,
1772 &fPositivePrefix
, &fPositiveSuffix
,
1773 FALSE
, UCURR_SYMBOL_NAME
,
1774 tmpPos_2
, tmpDigitList_2
, tmpStatus_2
,
1777 if (tmpPos_2
.getIndex() > maxPosIndex
) {
1778 maxPosIndex
= tmpPos_2
.getIndex();
1779 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1780 status
[i
] = tmpStatus_2
[i
];
1782 digits
= tmpDigitList_2
;
1786 maxErrorPos
= (tmpPos_2
.getErrorIndex() > maxErrorPos
) ?
1787 tmpPos_2
.getErrorIndex() : maxErrorPos
;
1791 //parsePosition.setIndex(origPos);
1792 parsePosition
.setErrorIndex(maxErrorPos
);
1794 parsePosition
.setIndex(maxPosIndex
);
1795 parsePosition
.setErrorIndex(-1);
1802 * Parse the given text into a number. The text is parsed beginning at
1803 * parsePosition, until an unparseable character is seen.
1804 * @param text the string to parse.
1805 * @param negPrefix negative prefix.
1806 * @param negSuffix negative suffix.
1807 * @param posPrefix positive prefix.
1808 * @param posSuffix positive suffix.
1809 * @param currencyParsing whether it is currency parsing or not.
1810 * @param type the currency type to parse against, LONG_NAME only or not.
1811 * @param parsePosition The position at which to being parsing. Upon
1812 * return, the first unparsed character.
1813 * @param digits the DigitList to set to the parsed value.
1814 * @param status output param containing boolean status flags indicating
1815 * whether the value was infinite and whether it was positive.
1816 * @param currency return value for parsed currency, for generic
1817 * currency parsing mode, or NULL for normal parsing. In generic
1818 * currency parsing mode, any currency is parsed, not just the
1819 * currency that this formatter is set to.
1821 UBool
DecimalFormat::subparse(const UnicodeString
& text
,
1822 const UnicodeString
* negPrefix
,
1823 const UnicodeString
* negSuffix
,
1824 const UnicodeString
* posPrefix
,
1825 const UnicodeString
* posSuffix
,
1826 UBool currencyParsing
,
1828 ParsePosition
& parsePosition
,
1829 DigitList
& digits
, UBool
* status
,
1830 UChar
* currency
) const
1832 // The parsing process builds up the number as char string, in the neutral format that
1833 // will be acceptable to the decNumber library, then at the end passes that string
1834 // off for conversion to a decNumber.
1835 UErrorCode err
= U_ZERO_ERROR
;
1836 CharString parsedNum
;
1839 int32_t position
= parsePosition
.getIndex();
1840 int32_t oldStart
= position
;
1841 UBool strictParse
= isParseStrict();
1843 // Match padding before prefix
1844 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforePrefix
) {
1845 position
= skipPadding(text
, position
);
1848 // Match positive and negative prefixes; prefer longest match.
1849 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, posPrefix
, currencyParsing
, type
, currency
);
1850 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, negPrefix
, currencyParsing
, type
, currency
);
1851 if (posMatch
>= 0 && negMatch
>= 0) {
1852 if (posMatch
> negMatch
) {
1854 } else if (negMatch
> posMatch
) {
1858 if (posMatch
>= 0) {
1859 position
+= posMatch
;
1860 parsedNum
.append('+', err
);
1861 } else if (negMatch
>= 0) {
1862 position
+= negMatch
;
1863 parsedNum
.append('-', err
);
1864 } else if (strictParse
){
1865 parsePosition
.setErrorIndex(position
);
1869 // Match padding before prefix
1870 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterPrefix
) {
1871 position
= skipPadding(text
, position
);
1874 if (! strictParse
) {
1875 position
= skipUWhiteSpace(text
, position
);
1878 // process digits or Inf, find decimal position
1879 const UnicodeString
*inf
= &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1880 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
1881 ? 0 : inf
->length());
1882 position
+= infLen
; // infLen is non-zero when it does equal to infinity
1883 status
[fgStatusInfinite
] = infLen
!= 0;
1887 parsedNum
.append("Infinity", err
);
1889 // We now have a string of digits, possibly with grouping symbols,
1890 // and decimal points. We want to process these into a DigitList.
1891 // We don't want to put a bunch of leading zeros into the DigitList
1892 // though, so we keep track of the location of the decimal point,
1893 // put only significant digits into the DigitList, and adjust the
1894 // exponent as needed.
1896 UChar32 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1898 UBool strictFail
= FALSE
; // did we exit with a strict parse failure?
1899 int32_t lastGroup
= -1; // where did we last see a grouping separator?
1900 int32_t digitStart
= position
;
1901 int32_t gs2
= fGroupingSize2
== 0 ? fGroupingSize
: fGroupingSize2
;
1903 #if CHECK_FOR_LEADING_ZERO
1904 // Strict parsing leading zeroes. If a leading zero would
1905 // be forced by the pattern, then don't fail strict parsing.
1906 UBool strictLeadingZero
= FALSE
;
1907 int32_t leadingZeroPos
= 0;
1908 int32_t leadingZeroCount
= 0;
1911 const UnicodeString
*decimalString
;
1912 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
1913 decimalString
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1915 decimalString
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1917 UChar32 decimalChar
= decimalString
->char32At(0);
1919 const UnicodeString
*groupingString
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1920 UChar32 groupingChar
= groupingString
->char32At(0);
1921 UBool sawDecimal
= FALSE
;
1922 UBool sawDigit
= FALSE
;
1923 int32_t backup
= -1;
1925 int32_t textLength
= text
.length(); // One less pointer to follow
1926 int32_t decimalStringLength
= decimalString
->length();
1927 int32_t decimalCharLength
= U16_LENGTH(decimalChar
);
1928 int32_t groupingStringLength
= groupingString
->length();
1929 int32_t groupingCharLength
= U16_LENGTH(groupingChar
);
1931 // equivalent grouping and decimal support
1932 // TODO markdavis Cache these if it makes a difference in performance.
1933 UnicodeSet decimalFallback
;
1934 UnicodeSet
*decimalSet
= NULL
;
1935 UnicodeSet
*groupingSet
= NULL
;
1937 if (decimalCharLength
== decimalStringLength
) {
1938 decimalSet
= (UnicodeSet
*) DecimalFormatStaticSets::getSimilarDecimals(decimalChar
, strictParse
, &decimalFallback
)->cloneAsThawed();
1941 if (groupingCharLength
== groupingStringLength
) {
1943 groupingSet
= (UnicodeSet
*) DecimalFormatStaticSets::gStaticSets
->fStrictDefaultGroupingSeparators
->cloneAsThawed();
1945 groupingSet
= (UnicodeSet
*) DecimalFormatStaticSets::gStaticSets
->fDefaultGroupingSeparators
->cloneAsThawed();
1948 groupingSet
->add(groupingChar
);
1950 if (decimalSet
!= NULL
) {
1951 groupingSet
->removeAll(*decimalSet
);
1955 // we are guaranteed that
1956 // decimalSet contains the decimal, and
1957 // groupingSet contains the groupingSeparator
1958 // (unless decimal and grouping are the same, which should never happen. But in that case, groupingSet will just be empty.)
1960 // We have to track digitCount ourselves, because digits.fCount will
1961 // pin when the maximum allowable digits is reached.
1962 int32_t digitCount
= 0;
1963 int32_t integerDigitCount
= 0;
1965 for (; position
< textLength
; )
1967 UChar32 ch
= text
.char32At(position
);
1969 /* We recognize all digit ranges, not only the Latin digit range
1970 * '0'..'9'. We do so by using the Character.digit() method,
1971 * which converts a valid Unicode digit to the range 0..9.
1973 * The character 'ch' may be a digit. If so, place its value
1974 * from 0 to 9 in 'digit'. First try using the locale digit,
1975 * which may or MAY NOT be a standard Unicode digit range. If
1976 * this fails, try using the standard Unicode digit ranges by
1977 * calling Character.digit(). If this also fails, digit will
1978 * have a value outside the range 0..9.
1982 if (digit
< 0 || digit
> 9)
1984 digit
= u_charDigitValue(ch
);
1987 // As a last resort, look through the localized digits if the zero digit
1988 // is not a "standard" Unicode digit.
1989 if ( (digit
< 0 || digit
> 9) && u_charDigitValue(zero
) != 0) {
1991 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is:
1992 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits.
1993 if ( zero
!=0x3007 || ch
!=0x96F6 ) {
1994 for (digit
= 1 ; digit
< 10 ; digit
++ ) {
1995 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)(DecimalFormatSymbols::kOneDigitSymbol
+digit
-1)).char32At(0) == ch
) {
2002 if (digit
>= 0 && digit
<= 9)
2004 if (strictParse
&& backup
!= -1) {
2005 // comma followed by digit, so group before comma is a
2006 // secondary group. If there was a group separator
2007 // before that, the group must == the secondary group
2008 // length, else it can be <= the the secondary group
2010 if ((lastGroup
!= -1 && backup
- lastGroup
- 1 != gs2
) ||
2011 (lastGroup
== -1 && position
- digitStart
- 1 > gs2
)) {
2019 // Cancel out backup setting (see grouping handler below)
2023 // Note: this will append leading zeros
2024 parsedNum
.append((char)(digit
+ '0'), err
);
2026 // count any digit that's not a leading zero
2027 if (digit
> 0 || digitCount
> 0 || sawDecimal
) {
2030 // count any integer digit that's not a leading zero
2032 integerDigitCount
+= 1;
2034 #if CHECK_FOR_LEADING_ZERO
2035 } else if (strictParse
&& ! fUseExponentialNotation
) {
2036 // TODO: Not sure we need to check fUseExponentialNotation
2037 if (!strictLeadingZero
) {
2038 leadingZeroPos
= position
+ U16_LENGTH(ch
);
2039 strictLeadingZero
= TRUE
;
2042 leadingZeroCount
+= 1;
2046 position
+= U16_LENGTH(ch
);
2048 else if (groupingStringLength
> 0 && matchSymbol(text
, position
, groupingStringLength
, *groupingString
, groupingSet
, ch
) && isGroupingUsed())
2055 if ( (!sawDigit
&& groupingSet
!=NULL
&& u_isWhitespace(ch
)) || backup
!= -1 ) {
2056 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for
2057 // backward compatibility) as long as it is not one of the breaking whitespace characters
2058 // that is only treated as a group separator because of the equivalence set. If we get
2059 // here it is because the leading sep was such a breaking space, or there were multiple
2060 // group separators in a row. Note that the DecimalFormat documentation says
2061 // "During parsing, grouping separators are ignored" and that was for strict parsing,
2062 // so we may need to further revisit this strictParse restriction to ensure compatibility.
2063 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F.
2064 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP).
2070 // Ignore grouping characters, if we are using them, but require
2071 // that they be followed by a digit. Otherwise we backup and
2074 position
+= groupingStringLength
;
2076 if (groupingSet
!= NULL
) {
2077 // Once we see a grouping character, we only accept that grouping character from then on.
2078 groupingSet
->set(ch
, ch
);
2081 else if (matchSymbol(text
, position
, decimalStringLength
, *decimalString
, decimalSet
, ch
))
2085 (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1)) {
2091 // If we're only parsing integers, or if we ALREADY saw the
2092 // decimal, then don't parse this one.
2093 if (isParseIntegerOnly() || sawDecimal
) {
2097 parsedNum
.append('.', err
);
2098 position
+= decimalStringLength
;
2101 if (decimalSet
!= NULL
) {
2102 // Once we see a decimal character, we only accept that decimal character from then on.
2103 decimalSet
->set(ch
, ch
);
2108 const UnicodeString
*tmp
;
2109 tmp
= &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
2110 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
2112 // Parse sign, if present
2113 int32_t pos
= position
+ tmp
->length();
2114 char exponentSign
= '+';
2116 if (pos
< textLength
)
2118 tmp
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2119 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2121 pos
+= tmp
->length();
2124 tmp
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2125 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2128 pos
+= tmp
->length();
2133 UBool sawExponentDigit
= FALSE
;
2134 while (pos
< textLength
) {
2135 ch
= text
[(int32_t)pos
];
2138 if (digit
< 0 || digit
> 9) {
2139 digit
= u_charDigitValue(ch
);
2141 if (0 <= digit
&& digit
<= 9) {
2142 if (!sawExponentDigit
) {
2143 parsedNum
.append('E', err
);
2144 parsedNum
.append(exponentSign
, err
);
2145 sawExponentDigit
= TRUE
;
2148 parsedNum
.append((char)(digit
+ '0'), err
);
2154 if (sawExponentDigit
) {
2155 position
= pos
; // Advance past the exponent
2158 break; // Whether we fail or succeed, we exit this loop
2174 #if CHECK_FOR_LEADING_ZERO
2175 // check for strict parse errors
2176 if (strictParse
&& strictLeadingZero
) {
2177 int32_t minIntegerDigits
= getMinimumIntegerDigits();
2179 if (minIntegerDigits
== 0 && integerDigitCount
== 0) {
2180 minIntegerDigits
= 1;
2183 if ((leadingZeroCount
+ integerDigitCount
) > minIntegerDigits
) {
2184 parsePosition
.setIndex(oldStart
);
2185 parsePosition
.setErrorIndex(leadingZeroPos
);
2191 if (strictParse
&& !sawDecimal
) {
2192 if (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1) {
2198 // only set with strictParse and a leading zero error
2199 // leading zeros are an error with strict parsing except
2200 // immediately before nondigit (except group separator
2201 // followed by digit), or end of text.
2203 parsePosition
.setIndex(oldStart
);
2204 parsePosition
.setErrorIndex(position
);
2208 // If there was no decimal point we have an integer
2210 // If none of the text string was recognized. For example, parse
2211 // "x" with pattern "#0.00" (return index and error index both 0)
2212 // parse "$" with pattern "$#0.00". (return index 0 and error index
2214 if (!sawDigit
&& digitCount
== 0) {
2215 parsePosition
.setIndex(oldStart
);
2216 parsePosition
.setErrorIndex(oldStart
);
2221 // Match padding before suffix
2222 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforeSuffix
) {
2223 position
= skipPadding(text
, position
);
2226 int32_t posSuffixMatch
= -1, negSuffixMatch
= -1;
2228 // Match positive and negative suffixes; prefer longest match.
2229 if (posMatch
>= 0 || (!strictParse
&& negMatch
< 0)) {
2230 posSuffixMatch
= compareAffix(text
, position
, FALSE
, FALSE
, posSuffix
, currencyParsing
, type
, currency
);
2232 if (negMatch
>= 0) {
2233 negSuffixMatch
= compareAffix(text
, position
, TRUE
, FALSE
, negSuffix
, currencyParsing
, type
, currency
);
2235 if (posSuffixMatch
>= 0 && negSuffixMatch
>= 0) {
2236 if (posSuffixMatch
> negSuffixMatch
) {
2237 negSuffixMatch
= -1;
2238 } else if (negSuffixMatch
> posSuffixMatch
) {
2239 posSuffixMatch
= -1;
2243 // Fail if neither or both
2244 if (strictParse
&& ((posSuffixMatch
>= 0) == (negSuffixMatch
>= 0))) {
2245 parsePosition
.setErrorIndex(position
);
2249 position
+= (posSuffixMatch
>= 0 ? posSuffixMatch
: (negSuffixMatch
>= 0 ? negSuffixMatch
: 0));
2251 // Match padding before suffix
2252 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterSuffix
) {
2253 position
= skipPadding(text
, position
);
2256 parsePosition
.setIndex(position
);
2258 parsedNum
.data()[0] = (posSuffixMatch
>= 0 || (!strictParse
&& negMatch
< 0 && negSuffixMatch
< 0)) ? '+' : '-';
2260 if(parsePosition
.getIndex() == oldStart
)
2262 parsePosition
.setErrorIndex(position
);
2265 digits
.set(parsedNum
.toStringPiece(), err
);
2267 if (U_FAILURE(err
)) {
2268 parsePosition
.setErrorIndex(position
);
2275 * Starting at position, advance past a run of pad characters, if any.
2276 * Return the index of the first character after position that is not a pad
2277 * character. Result is >= position.
2279 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
2280 int32_t padLen
= U16_LENGTH(fPad
);
2281 while (position
< text
.length() &&
2282 text
.char32At(position
) == fPad
) {
2289 * Return the length matched by the given affix, or -1 if none.
2290 * Runs of white space in the affix, match runs of white space in
2291 * the input. Pattern white space and input white space are
2292 * determined differently; see code.
2293 * @param text input text
2294 * @param pos offset into input at which to begin matching
2297 * @param affixPat affix pattern used for currency affix comparison.
2298 * @param currencyParsing whether it is currency parsing or not
2299 * @param type the currency type to parse against, LONG_NAME only or not.
2300 * @param currency return value for parsed currency, for generic
2301 * currency parsing mode, or null for normal parsing. In generic
2302 * currency parsing mode, any currency is parsed, not just the
2303 * currency that this formatter is set to.
2304 * @return length of input that matches, or -1 if match failure
2306 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
2310 const UnicodeString
* affixPat
,
2311 UBool currencyParsing
,
2313 UChar
* currency
) const
2315 const UnicodeString
*patternToCompare
;
2316 if (fCurrencyChoice
!= NULL
|| currency
!= NULL
||
2317 (fCurrencySignCount
> fgCurrencySignCountZero
&& currencyParsing
)) {
2319 if (affixPat
!= NULL
) {
2320 return compareComplexAffix(*affixPat
, text
, pos
, type
, currency
);
2326 patternToCompare
= &fNegativePrefix
;
2329 patternToCompare
= &fNegativeSuffix
;
2334 patternToCompare
= &fPositivePrefix
;
2337 patternToCompare
= &fPositiveSuffix
;
2340 return compareSimpleAffix(*patternToCompare
, text
, pos
, isParseStrict());
2344 * Return the length matched by the given affix, or -1 if none.
2345 * Runs of white space in the affix, match runs of white space in
2346 * the input. Pattern white space and input white space are
2347 * determined differently; see code.
2348 * @param affix pattern string, taken as a literal
2349 * @param input input text
2350 * @param pos offset into input at which to begin matching
2351 * @return length of input that matches, or -1 if match failure
2353 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
2354 const UnicodeString
& input
,
2357 UErrorCode status
= U_ZERO_ERROR
;
2358 int32_t start
= pos
;
2359 UChar32 affixChar
= affix
.char32At(0);
2360 int32_t affixLength
= affix
.length();
2361 int32_t inputLength
= input
.length();
2362 int32_t affixCharLength
= U16_LENGTH(affixChar
);
2363 UnicodeSet
*affixSet
;
2365 DecimalFormatStaticSets::initSets(&status
);
2368 affixSet
= DecimalFormatStaticSets::gStaticSets
->fStrictDashEquivalents
;
2370 // If the affix is exactly one character long and that character
2371 // is in the dash set and the very next input character is also
2372 // in the dash set, return a match.
2373 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2374 if (affixSet
->contains(input
.char32At(pos
))) {
2379 for (int32_t i
= 0; i
< affixLength
; ) {
2380 UChar32 c
= affix
.char32At(i
);
2381 int32_t len
= U16_LENGTH(c
);
2382 if (uprv_isRuleWhiteSpace(c
)) {
2383 // We may have a pattern like: \u200F \u0020
2384 // and input text like: \u200F \u0020
2385 // Note that U+200F and U+0020 are RuleWhiteSpace but only
2386 // U+0020 is UWhiteSpace. So we have to first do a direct
2387 // match of the run of RULE whitespace in the pattern,
2388 // then match any extra characters.
2389 UBool literalMatch
= FALSE
;
2390 while (pos
< inputLength
&&
2391 input
.char32At(pos
) == c
) {
2392 literalMatch
= TRUE
;
2395 if (i
== affixLength
) {
2398 c
= affix
.char32At(i
);
2399 len
= U16_LENGTH(c
);
2400 if (!uprv_isRuleWhiteSpace(c
)) {
2405 // Advance over run in pattern
2406 i
= skipRuleWhiteSpace(affix
, i
);
2408 // Advance over run in input text
2409 // Must see at least one white space char in input,
2410 // unless we've already matched some characters literally.
2412 pos
= skipUWhiteSpace(input
, pos
);
2413 if (pos
== s
&& !literalMatch
) {
2417 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2418 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2419 // is also in the affix.
2420 i
= skipUWhiteSpace(affix
, i
);
2422 if (pos
< inputLength
&&
2423 input
.char32At(pos
) == c
) {
2432 UBool match
= FALSE
;
2434 affixSet
= DecimalFormatStaticSets::gStaticSets
->fDashEquivalents
;
2436 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2437 pos
= skipUWhiteSpace(input
, pos
);
2439 if (affixSet
->contains(input
.char32At(pos
))) {
2440 return pos
- start
+ 1;
2444 for (int32_t i
= 0; i
< affixLength
; )
2446 //i = skipRuleWhiteSpace(affix, i);
2447 i
= skipUWhiteSpace(affix
, i
);
2448 pos
= skipUWhiteSpace(input
, pos
);
2450 if (i
>= affixLength
|| pos
>= inputLength
) {
2454 UChar32 c
= affix
.char32At(i
);
2455 int32_t len
= U16_LENGTH(c
);
2457 if (input
.char32At(pos
) != c
) {
2466 if (affixLength
> 0 && ! match
) {
2475 * Skip over a run of zero or more isRuleWhiteSpace() characters at
2478 int32_t DecimalFormat::skipRuleWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2479 while (pos
< text
.length()) {
2480 UChar32 c
= text
.char32At(pos
);
2481 if (!uprv_isRuleWhiteSpace(c
)) {
2484 pos
+= U16_LENGTH(c
);
2490 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2493 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2494 while (pos
< text
.length()) {
2495 UChar32 c
= text
.char32At(pos
);
2496 if (!u_isUWhiteSpace(c
)) {
2499 pos
+= U16_LENGTH(c
);
2505 * Return the length matched by the given affix, or -1 if none.
2506 * @param affixPat pattern string
2507 * @param input input text
2508 * @param pos offset into input at which to begin matching
2509 * @param type the currency type to parse against, LONG_NAME only or not.
2510 * @param currency return value for parsed currency, for generic
2511 * currency parsing mode, or null for normal parsing. In generic
2512 * currency parsing mode, any currency is parsed, not just the
2513 * currency that this formatter is set to.
2514 * @return length of input that matches, or -1 if match failure
2516 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
2517 const UnicodeString
& text
,
2520 UChar
* currency
) const
2522 int32_t start
= pos
;
2523 U_ASSERT(currency
!= NULL
||
2524 (fCurrencyChoice
!= NULL
&& *getCurrency() != 0) ||
2525 fCurrencySignCount
> fgCurrencySignCountZero
);
2528 i
<affixPat
.length() && pos
>= 0; ) {
2529 UChar32 c
= affixPat
.char32At(i
);
2533 U_ASSERT(i
<= affixPat
.length());
2534 c
= affixPat
.char32At(i
);
2537 const UnicodeString
* affix
= NULL
;
2540 case kCurrencySign
: {
2541 // since the currency names in choice format is saved
2542 // the same way as other currency names,
2543 // do not need to do currency choice parsing here.
2544 // the general currency parsing parse against all names,
2545 // including names in choice format.
2546 UBool intl
= i
<affixPat
.length() &&
2547 affixPat
.char32At(i
) == kCurrencySign
;
2551 UBool plural
= i
<affixPat
.length() &&
2552 affixPat
.char32At(i
) == kCurrencySign
;
2557 // Parse generic currency -- anything for which we
2558 // have a display name, or any 3-letter ISO code.
2559 // Try to parse display name for our locale; first
2560 // determine our locale.
2561 const char* loc
= fCurrencyPluralInfo
->getLocale().getName();
2562 ParsePosition
ppos(pos
);
2564 UErrorCode ec
= U_ZERO_ERROR
;
2565 // Delegate parse of display name => ISO code to Currency
2566 uprv_parseCurrency(loc
, text
, ppos
, type
, curr
, ec
);
2568 // If parse succeeds, populate currency[0]
2569 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
2571 u_strcpy(currency
, curr
);
2572 } else if (isParseStrict()) {
2573 // The formatter is currency-style but the client has not requested
2574 // the value of the parsed currency. In this case, if that value does
2575 // not match the formatter's current value, then the parse fails.
2576 UChar effectiveCurr
[4];
2577 getEffectiveCurrency(effectiveCurr
, ec
);
2578 if ( U_FAILURE(ec
) || u_strncmp(curr
,effectiveCurr
,3) != 0 ) {
2583 pos
= ppos
.getIndex();
2584 } else if (isParseStrict()){
2589 case kPatternPercent
:
2590 affix
= &getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
2592 case kPatternPerMill
:
2593 affix
= &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
2596 affix
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2599 affix
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2602 // fall through to affix!=0 test, which will fail
2606 if (affix
!= NULL
) {
2607 pos
= match(text
, pos
, *affix
);
2612 pos
= match(text
, pos
, c
);
2613 if (uprv_isRuleWhiteSpace(c
)) {
2614 i
= skipRuleWhiteSpace(affixPat
, i
);
2621 * Match a single character at text[pos] and return the index of the
2622 * next character upon success. Return -1 on failure. If
2623 * isRuleWhiteSpace(ch) then match a run of white space in text.
2625 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
2626 if (uprv_isRuleWhiteSpace(ch
)) {
2627 // Advance over run of white space in input text
2628 // Must see at least one white space char in input
2630 pos
= skipRuleWhiteSpace(text
, pos
);
2636 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
2637 (pos
+ U16_LENGTH(ch
)) : -1;
2641 * Match a string at text[pos] and return the index of the next
2642 * character upon success. Return -1 on failure. Match a run of
2643 * white space in str with a run of white space in text.
2645 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
2646 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
2647 UChar32 ch
= str
.char32At(i
);
2648 i
+= U16_LENGTH(ch
);
2649 if (uprv_isRuleWhiteSpace(ch
)) {
2650 i
= skipRuleWhiteSpace(str
, i
);
2652 pos
= match(text
, pos
, ch
);
2657 UBool
DecimalFormat::matchSymbol(const UnicodeString
&text
, int32_t position
, int32_t length
, const UnicodeString
&symbol
,
2658 UnicodeSet
*sset
, UChar32 schar
)
2661 return sset
->contains(schar
);
2664 return text
.compare(position
, length
, symbol
) == 0;
2668 //------------------------------------------------------------------------------
2669 // Gets the pointer to the localized decimal format symbols
2671 const DecimalFormatSymbols
*
2672 DecimalFormat::getDecimalFormatSymbols() const
2677 //------------------------------------------------------------------------------
2678 // De-owning the current localized symbols and adopt the new symbols.
2681 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
2683 if (symbolsToAdopt
== NULL
) {
2684 return; // do not allow caller to set fSymbols to NULL
2687 UBool sameSymbols
= FALSE
;
2688 if (fSymbols
!= NULL
) {
2689 sameSymbols
= (UBool
)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) ==
2690 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) &&
2691 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) ==
2692 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
2696 fSymbols
= symbolsToAdopt
;
2698 // If the currency symbols are the same, there is no need to recalculate.
2699 setCurrencyForSymbols();
2701 expandAffixes(NULL
);
2703 //------------------------------------------------------------------------------
2704 // Setting the symbols is equlivalent to adopting a newly created localized
2708 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
2710 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
2713 const CurrencyPluralInfo
*
2714 DecimalFormat::getCurrencyPluralInfo(void) const
2716 return fCurrencyPluralInfo
;
2720 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo
* toAdopt
)
2722 if (toAdopt
!= NULL
) {
2723 delete fCurrencyPluralInfo
;
2724 fCurrencyPluralInfo
= toAdopt
;
2725 // re-set currency affix patterns and currency affixes.
2726 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
2727 UErrorCode status
= U_ZERO_ERROR
;
2728 if (fAffixPatternsForCurrency
) {
2729 deleteHashForAffixPattern();
2731 setupCurrencyAffixPatterns(status
);
2732 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
2733 // only setup the affixes of the plural pattern.
2734 setupCurrencyAffixes(fFormatPattern
, FALSE
, TRUE
, status
);
2741 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo
& info
)
2743 adoptCurrencyPluralInfo(info
.clone());
2748 * Update the currency object to match the symbols. This method
2749 * is used only when the caller has passed in a symbols object
2750 * that may not be the default object for its locale.
2753 DecimalFormat::setCurrencyForSymbols() {
2755 Update the affix strings accroding to symbols in order to keep
2756 the affix strings up to date.
2760 // With the introduction of the Currency object, the currency
2761 // symbols in the DFS object are ignored. For backward
2762 // compatibility, we check any explicitly set DFS object. If it
2763 // is a default symbols object for its locale, we change the
2764 // currency object to one for that locale. If it is custom,
2765 // we set the currency to null.
2766 UErrorCode ec
= U_ZERO_ERROR
;
2767 const UChar
* c
= NULL
;
2768 const char* loc
= fSymbols
->getLocale().getName();
2769 UChar intlCurrencySymbol
[4];
2770 ucurr_forLocale(loc
, intlCurrencySymbol
, 4, &ec
);
2771 UnicodeString currencySymbol
;
2773 uprv_getStaticCurrencyName(intlCurrencySymbol
, loc
, currencySymbol
, ec
);
2775 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) == currencySymbol
2776 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) == intlCurrencySymbol
)
2778 // Trap an error in mapping locale to currency. If we can't
2779 // map, then don't fail and set the currency to "".
2780 c
= intlCurrencySymbol
;
2782 ec
= U_ZERO_ERROR
; // reset local error code!
2783 setCurrencyInternally(c
, ec
);
2787 //------------------------------------------------------------------------------
2788 // Gets the positive prefix of the number pattern.
2791 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
2793 result
= fPositivePrefix
;
2797 //------------------------------------------------------------------------------
2798 // Sets the positive prefix of the number pattern.
2801 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
2803 fPositivePrefix
= newValue
;
2804 delete fPosPrefixPattern
;
2805 fPosPrefixPattern
= 0;
2808 //------------------------------------------------------------------------------
2809 // Gets the negative prefix of the number pattern.
2812 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
2814 result
= fNegativePrefix
;
2818 //------------------------------------------------------------------------------
2819 // Gets the negative prefix of the number pattern.
2822 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
2824 fNegativePrefix
= newValue
;
2825 delete fNegPrefixPattern
;
2826 fNegPrefixPattern
= 0;
2829 //------------------------------------------------------------------------------
2830 // Gets the positive suffix of the number pattern.
2833 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
2835 result
= fPositiveSuffix
;
2839 //------------------------------------------------------------------------------
2840 // Sets the positive suffix of the number pattern.
2843 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
2845 fPositiveSuffix
= newValue
;
2846 delete fPosSuffixPattern
;
2847 fPosSuffixPattern
= 0;
2850 //------------------------------------------------------------------------------
2851 // Gets the negative suffix of the number pattern.
2854 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
2856 result
= fNegativeSuffix
;
2860 //------------------------------------------------------------------------------
2861 // Sets the negative suffix of the number pattern.
2864 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
2866 fNegativeSuffix
= newValue
;
2867 delete fNegSuffixPattern
;
2868 fNegSuffixPattern
= 0;
2871 //------------------------------------------------------------------------------
2872 // Gets the multiplier of the number pattern.
2873 // Multipliers are stored as decimal numbers (DigitLists) because that
2874 // is the most convenient for muliplying or dividing the numbers to be formatted.
2875 // A NULL multiplier implies one, and the scaling operations are skipped.
2878 DecimalFormat::getMultiplier() const
2880 if (fMultiplier
== NULL
) {
2883 return fMultiplier
->getLong();
2887 //------------------------------------------------------------------------------
2888 // Sets the multiplier of the number pattern.
2890 DecimalFormat::setMultiplier(int32_t newValue
)
2892 // if (newValue == 0) {
2893 // throw new IllegalArgumentException("Bad multiplier: " + newValue);
2895 if (newValue
== 0) {
2896 newValue
= 1; // one being the benign default value for a multiplier.
2898 if (newValue
== 1) {
2902 if (fMultiplier
== NULL
) {
2903 fMultiplier
= new DigitList
;
2905 if (fMultiplier
!= NULL
) {
2906 fMultiplier
->set(newValue
);
2912 * Get the rounding increment.
2913 * @return A positive rounding increment, or 0.0 if rounding
2915 * @see #setRoundingIncrement
2916 * @see #getRoundingMode
2917 * @see #setRoundingMode
2919 double DecimalFormat::getRoundingIncrement() const {
2920 if (fRoundingIncrement
== NULL
) {
2923 return fRoundingIncrement
->getDouble();
2928 * Set the rounding increment. This method also controls whether
2929 * rounding is enabled.
2930 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2931 * Negative increments are equivalent to 0.0.
2932 * @see #getRoundingIncrement
2933 * @see #getRoundingMode
2934 * @see #setRoundingMode
2936 void DecimalFormat::setRoundingIncrement(double newValue
) {
2937 if (newValue
> 0.0) {
2938 if (fRoundingIncrement
== NULL
) {
2939 fRoundingIncrement
= new DigitList();
2941 if (fRoundingIncrement
!= NULL
) {
2942 fRoundingIncrement
->set(newValue
);
2946 // These statements are executed if newValue is less than 0.0
2947 // or fRoundingIncrement could not be created.
2948 delete fRoundingIncrement
;
2949 fRoundingIncrement
= NULL
;
2953 * Get the rounding mode.
2954 * @return A rounding mode
2955 * @see #setRoundingIncrement
2956 * @see #getRoundingIncrement
2957 * @see #setRoundingMode
2959 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
2960 return fRoundingMode
;
2964 * Set the rounding mode. This has no effect unless the rounding
2965 * increment is greater than zero.
2966 * @param roundingMode A rounding mode
2967 * @see #setRoundingIncrement
2968 * @see #getRoundingIncrement
2969 * @see #getRoundingMode
2971 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
2972 fRoundingMode
= roundingMode
;
2976 * Get the width to which the output of <code>format()</code> is padded.
2977 * @return the format width, or zero if no padding is in effect
2978 * @see #setFormatWidth
2979 * @see #getPadCharacter
2980 * @see #setPadCharacter
2981 * @see #getPadPosition
2982 * @see #setPadPosition
2984 int32_t DecimalFormat::getFormatWidth() const {
2985 return fFormatWidth
;
2989 * Set the width to which the output of <code>format()</code> is padded.
2990 * This method also controls whether padding is enabled.
2991 * @param width the width to which to pad the result of
2992 * <code>format()</code>, or zero to disable padding. A negative
2993 * width is equivalent to 0.
2994 * @see #getFormatWidth
2995 * @see #getPadCharacter
2996 * @see #setPadCharacter
2997 * @see #getPadPosition
2998 * @see #setPadPosition
3000 void DecimalFormat::setFormatWidth(int32_t width
) {
3001 fFormatWidth
= (width
> 0) ? width
: 0;
3004 UnicodeString
DecimalFormat::getPadCharacterString() const {
3008 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
3009 if (padChar
.length() > 0) {
3010 fPad
= padChar
.char32At(0);
3018 * Get the position at which padding will take place. This is the location
3019 * at which padding will be inserted if the result of <code>format()</code>
3020 * is shorter than the format width.
3021 * @return the pad position, one of <code>kPadBeforePrefix</code>,
3022 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3023 * <code>kPadAfterSuffix</code>.
3024 * @see #setFormatWidth
3025 * @see #getFormatWidth
3026 * @see #setPadCharacter
3027 * @see #getPadCharacter
3028 * @see #setPadPosition
3029 * @see #kPadBeforePrefix
3030 * @see #kPadAfterPrefix
3031 * @see #kPadBeforeSuffix
3032 * @see #kPadAfterSuffix
3034 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
3035 return fPadPosition
;
3039 * <strong><font face=helvetica color=red>NEW</font></strong>
3040 * Set the position at which padding will take place. This is the location
3041 * at which padding will be inserted if the result of <code>format()</code>
3042 * is shorter than the format width. This has no effect unless padding is
3044 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
3045 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3046 * <code>kPadAfterSuffix</code>.
3047 * @see #setFormatWidth
3048 * @see #getFormatWidth
3049 * @see #setPadCharacter
3050 * @see #getPadCharacter
3051 * @see #getPadPosition
3052 * @see #kPadBeforePrefix
3053 * @see #kPadAfterPrefix
3054 * @see #kPadBeforeSuffix
3055 * @see #kPadAfterSuffix
3057 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
3058 fPadPosition
= padPos
;
3062 * Return whether or not scientific notation is used.
3063 * @return TRUE if this object formats and parses scientific notation
3064 * @see #setScientificNotation
3065 * @see #getMinimumExponentDigits
3066 * @see #setMinimumExponentDigits
3067 * @see #isExponentSignAlwaysShown
3068 * @see #setExponentSignAlwaysShown
3070 UBool
DecimalFormat::isScientificNotation() {
3071 return fUseExponentialNotation
;
3075 * Set whether or not scientific notation is used.
3076 * @param useScientific TRUE if this object formats and parses scientific
3078 * @see #isScientificNotation
3079 * @see #getMinimumExponentDigits
3080 * @see #setMinimumExponentDigits
3081 * @see #isExponentSignAlwaysShown
3082 * @see #setExponentSignAlwaysShown
3084 void DecimalFormat::setScientificNotation(UBool useScientific
) {
3085 fUseExponentialNotation
= useScientific
;
3089 * Return the minimum exponent digits that will be shown.
3090 * @return the minimum exponent digits that will be shown
3091 * @see #setScientificNotation
3092 * @see #isScientificNotation
3093 * @see #setMinimumExponentDigits
3094 * @see #isExponentSignAlwaysShown
3095 * @see #setExponentSignAlwaysShown
3097 int8_t DecimalFormat::getMinimumExponentDigits() const {
3098 return fMinExponentDigits
;
3102 * Set the minimum exponent digits that will be shown. This has no
3103 * effect unless scientific notation is in use.
3104 * @param minExpDig a value >= 1 indicating the fewest exponent digits
3105 * that will be shown. Values less than 1 will be treated as 1.
3106 * @see #setScientificNotation
3107 * @see #isScientificNotation
3108 * @see #getMinimumExponentDigits
3109 * @see #isExponentSignAlwaysShown
3110 * @see #setExponentSignAlwaysShown
3112 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
3113 fMinExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
3117 * Return whether the exponent sign is always shown.
3118 * @return TRUE if the exponent is always prefixed with either the
3119 * localized minus sign or the localized plus sign, false if only negative
3120 * exponents are prefixed with the localized minus sign.
3121 * @see #setScientificNotation
3122 * @see #isScientificNotation
3123 * @see #setMinimumExponentDigits
3124 * @see #getMinimumExponentDigits
3125 * @see #setExponentSignAlwaysShown
3127 UBool
DecimalFormat::isExponentSignAlwaysShown() {
3128 return fExponentSignAlwaysShown
;
3132 * Set whether the exponent sign is always shown. This has no effect
3133 * unless scientific notation is in use.
3134 * @param expSignAlways TRUE if the exponent is always prefixed with either
3135 * the localized minus sign or the localized plus sign, false if only
3136 * negative exponents are prefixed with the localized minus sign.
3137 * @see #setScientificNotation
3138 * @see #isScientificNotation
3139 * @see #setMinimumExponentDigits
3140 * @see #getMinimumExponentDigits
3141 * @see #isExponentSignAlwaysShown
3143 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
3144 fExponentSignAlwaysShown
= expSignAlways
;
3147 //------------------------------------------------------------------------------
3148 // Gets the grouping size of the number pattern. For example, thousand or 10
3149 // thousand groupings.
3152 DecimalFormat::getGroupingSize() const
3154 return fGroupingSize
;
3157 //------------------------------------------------------------------------------
3158 // Gets the grouping size of the number pattern.
3161 DecimalFormat::setGroupingSize(int32_t newValue
)
3163 fGroupingSize
= newValue
;
3166 //------------------------------------------------------------------------------
3169 DecimalFormat::getSecondaryGroupingSize() const
3171 return fGroupingSize2
;
3174 //------------------------------------------------------------------------------
3177 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
3179 fGroupingSize2
= newValue
;
3182 //------------------------------------------------------------------------------
3183 // Checks if to show the decimal separator.
3186 DecimalFormat::isDecimalSeparatorAlwaysShown() const
3188 return fDecimalSeparatorAlwaysShown
;
3191 //------------------------------------------------------------------------------
3192 // Sets to always show the decimal separator.
3195 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
3197 fDecimalSeparatorAlwaysShown
= newValue
;
3200 //------------------------------------------------------------------------------
3201 // Emits the pattern of this DecimalFormat instance.
3204 DecimalFormat::toPattern(UnicodeString
& result
) const
3206 return toPattern(result
, FALSE
);
3209 //------------------------------------------------------------------------------
3210 // Emits the localized pattern this DecimalFormat instance.
3213 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
3215 return toPattern(result
, TRUE
);
3218 //------------------------------------------------------------------------------
3220 * Expand the affix pattern strings into the expanded affix strings. If any
3221 * affix pattern string is null, do not expand it. This method should be
3222 * called any time the symbols or the affix patterns change in order to keep
3223 * the expanded affix strings up to date.
3224 * This method also will be called before formatting if format currency
3225 * plural names, since the plural name is not a static one, it is
3226 * based on the currency plural count, the affix will be known only
3227 * after the currency plural count is know.
3228 * In which case, the parameter
3229 * 'pluralCount' will be a non-null currency plural count.
3230 * In all other cases, the 'pluralCount' is null, which means it is not needed.
3232 void DecimalFormat::expandAffixes(const UnicodeString
* pluralCount
) {
3233 FieldPositionHandler none
;
3234 if (fPosPrefixPattern
!= 0) {
3235 expandAffix(*fPosPrefixPattern
, fPositivePrefix
, 0, none
, FALSE
, pluralCount
);
3237 if (fPosSuffixPattern
!= 0) {
3238 expandAffix(*fPosSuffixPattern
, fPositiveSuffix
, 0, none
, FALSE
, pluralCount
);
3240 if (fNegPrefixPattern
!= 0) {
3241 expandAffix(*fNegPrefixPattern
, fNegativePrefix
, 0, none
, FALSE
, pluralCount
);
3243 if (fNegSuffixPattern
!= 0) {
3244 expandAffix(*fNegSuffixPattern
, fNegativeSuffix
, 0, none
, FALSE
, pluralCount
);
3249 .append(*fPosPrefixPattern
).append("|").append(*fPosSuffixPattern
)
3250 .append(";") .append(*fNegPrefixPattern
).append("|").append(*fNegSuffixPattern
)
3252 .append(fPositivePrefix
).append("|").append(fPositiveSuffix
)
3253 .append(";") .append(fNegativePrefix
).append("|").append(fNegativeSuffix
)
3260 * Expand an affix pattern into an affix string. All characters in the
3261 * pattern are literal unless prefixed by kQuote. The following characters
3262 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
3263 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
3264 * kCurrencySign + kCurrencySign), it is interpreted as an international
3265 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
3266 * currency plural long names, such as "US Dollars".
3267 * Any other character after a kQuote represents itself.
3268 * kQuote must be followed by another character; kQuote may not occur by
3269 * itself at the end of the pattern.
3271 * This method is used in two distinct ways. First, it is used to expand
3272 * the stored affix patterns into actual affixes. For this usage, doFormat
3273 * must be false. Second, it is used to expand the stored affix patterns
3274 * given a specific number (doFormat == true), for those rare cases in
3275 * which a currency format references a ChoiceFormat (e.g., en_IN display
3276 * name for INR). The number itself is taken from digitList.
3278 * When used in the first way, this method has a side effect: It sets
3279 * currencyChoice to a ChoiceFormat object, if the currency's display name
3280 * in this locale is a ChoiceFormat pattern (very rare). It only does this
3281 * if currencyChoice is null to start with.
3283 * @param pattern the non-null, fPossibly empty pattern
3284 * @param affix string to receive the expanded equivalent of pattern.
3285 * Previous contents are deleted.
3286 * @param doFormat if false, then the pattern will be expanded, and if a
3287 * currency symbol is encountered that expands to a ChoiceFormat, the
3288 * currencyChoice member variable will be initialized if it is null. If
3289 * doFormat is true, then it is assumed that the currencyChoice has been
3290 * created, and it will be used to format the value in digitList.
3291 * @param pluralCount the plural count. It is only used for currency
3292 * plural format. In which case, it is the plural
3293 * count of the currency amount. For example,
3294 * in en_US, it is the singular "one", or the plural
3295 * "other". For all other cases, it is null, and
3296 * is not being used.
3298 void DecimalFormat::expandAffix(const UnicodeString
& pattern
,
3299 UnicodeString
& affix
,
3301 FieldPositionHandler
& handler
,
3303 const UnicodeString
* pluralCount
) const {
3305 for (int i
=0; i
<pattern
.length(); ) {
3306 UChar32 c
= pattern
.char32At(i
);
3309 c
= pattern
.char32At(i
);
3311 int beginIdx
= affix
.length();
3313 case kCurrencySign
: {
3314 // As of ICU 2.2 we use the currency object, and
3315 // ignore the currency symbols in the DFS, unless
3316 // we have a null currency object. This occurs if
3317 // resurrecting a pre-2.2 object or if the user
3318 // sets a custom DFS.
3319 UBool intl
= i
<pattern
.length() &&
3320 pattern
.char32At(i
) == kCurrencySign
;
3321 UBool plural
= FALSE
;
3324 plural
= i
<pattern
.length() &&
3325 pattern
.char32At(i
) == kCurrencySign
;
3331 const UChar
* currencyUChars
= getCurrency();
3332 if (currencyUChars
[0] != 0) {
3333 UErrorCode ec
= U_ZERO_ERROR
;
3334 if (plural
&& pluralCount
!= NULL
) {
3335 // plural name is only needed when pluralCount != null,
3336 // which means when formatting currency plural names.
3337 // For other cases, pluralCount == null,
3338 // and plural names are not needed.
3340 // TODO: num of char in plural count
3341 char pluralCountChar
[10];
3342 if (pluralCount
->length() >= 10) {
3345 pluralCount
->extract(0, pluralCount
->length(), pluralCountChar
);
3346 UBool isChoiceFormat
;
3347 const UChar
* s
= ucurr_getPluralName(currencyUChars
,
3348 fSymbols
!= NULL
? fSymbols
->getLocale().getName() :
3349 Locale::getDefault().getName(), &isChoiceFormat
,
3350 pluralCountChar
, &len
, &ec
);
3351 affix
+= UnicodeString(s
, len
);
3352 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3354 affix
+= currencyUChars
;
3355 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3358 UBool isChoiceFormat
;
3359 // If fSymbols is NULL, use default locale
3360 const UChar
* s
= ucurr_getName(currencyUChars
,
3361 fSymbols
!= NULL
? fSymbols
->getLocale().getName() : Locale::getDefault().getName(),
3362 UCURR_SYMBOL_NAME
, &isChoiceFormat
, &len
, &ec
);
3363 if (isChoiceFormat
) {
3364 // Two modes here: If doFormat is false, we set up
3365 // currencyChoice. If doFormat is true, we use the
3366 // previously created currencyChoice to format the
3367 // value in digitList.
3369 // If the currency is handled by a ChoiceFormat,
3370 // then we're not going to use the expanded
3371 // patterns. Instantiate the ChoiceFormat and
3373 if (fCurrencyChoice
== NULL
) {
3374 // TODO Replace double-check with proper thread-safe code
3375 ChoiceFormat
* fmt
= new ChoiceFormat(s
, ec
);
3376 if (U_SUCCESS(ec
)) {
3378 if (fCurrencyChoice
== NULL
) {
3380 ((DecimalFormat
*)this)->fCurrencyChoice
= fmt
;
3387 // We could almost return null or "" here, since the
3388 // expanded affixes are almost not used at all
3389 // in this situation. However, one method --
3390 // toPattern() -- still does use the expanded
3391 // affixes, in order to set up a padding
3392 // pattern. We use the CURRENCY_SIGN as a
3394 affix
.append(kCurrencySign
);
3396 if (fCurrencyChoice
!= NULL
) {
3397 FieldPosition
pos(0); // ignored
3401 fCurrencyChoice
->format(number
, affix
, pos
);
3403 // We only arrive here if the currency choice
3404 // format in the locale data is INVALID.
3405 affix
+= currencyUChars
;
3406 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3411 affix
+= UnicodeString(s
, len
);
3412 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3416 affix
+= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3418 affix
+= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
3420 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3424 case kPatternPercent
:
3425 affix
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3426 handler
.addAttribute(kPercentField
, beginIdx
, affix
.length());
3428 case kPatternPerMill
:
3429 affix
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3430 handler
.addAttribute(kPermillField
, beginIdx
, affix
.length());
3433 affix
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3434 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
3437 affix
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3438 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
3452 * Append an affix to the given StringBuffer.
3453 * @param buf buffer to append to
3457 int32_t DecimalFormat::appendAffix(UnicodeString
& buf
, double number
,
3458 FieldPositionHandler
& handler
,
3459 UBool isNegative
, UBool isPrefix
) const {
3460 // plural format precedes choice format
3461 if (fCurrencyChoice
!= 0 &&
3462 fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
3463 const UnicodeString
* affixPat
;
3465 affixPat
= isNegative
? fNegPrefixPattern
: fPosPrefixPattern
;
3467 affixPat
= isNegative
? fNegSuffixPattern
: fPosSuffixPattern
;
3470 UnicodeString affixBuf
;
3471 expandAffix(*affixPat
, affixBuf
, number
, handler
, TRUE
, NULL
);
3472 buf
.append(affixBuf
);
3473 return affixBuf
.length();
3475 // else someone called a function that reset the pattern.
3478 const UnicodeString
* affix
;
3479 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
3480 UnicodeString pluralCount
= fCurrencyPluralInfo
->getPluralRules()->select(number
);
3481 AffixesForCurrency
* oneSet
;
3482 if (fStyle
== NumberFormat::kPluralCurrencyStyle
) {
3483 oneSet
= (AffixesForCurrency
*)fPluralAffixesForCurrency
->get(pluralCount
);
3485 oneSet
= (AffixesForCurrency
*)fAffixesForCurrency
->get(pluralCount
);
3488 affix
= isNegative
? &oneSet
->negPrefixForCurrency
:
3489 &oneSet
->posPrefixForCurrency
;
3491 affix
= isNegative
? &oneSet
->negSuffixForCurrency
:
3492 &oneSet
->posSuffixForCurrency
;
3496 affix
= isNegative
? &fNegativePrefix
: &fPositivePrefix
;
3498 affix
= isNegative
? &fNegativeSuffix
: &fPositiveSuffix
;
3502 int32_t begin
= (int) buf
.length();
3506 if (handler
.isRecording()) {
3507 int32_t offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
));
3509 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
3510 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3513 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
3515 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3516 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3519 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
3521 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3522 handler
.addAttribute(kSignField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3525 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
3527 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3528 handler
.addAttribute(kPercentField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3531 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
3533 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3534 handler
.addAttribute(kPermillField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3537 return affix
->length();
3541 * Appends an affix pattern to the given StringBuffer, quoting special
3542 * characters as needed. Uses the internal affix pattern, if that exists,
3543 * or the literal affix, if the internal affix pattern is null. The
3544 * appended string will generate the same affix pattern (or literal affix)
3545 * when passed to toPattern().
3547 * @param appendTo the affix string is appended to this
3548 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
3549 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
3550 * Ignored unless affixPattern is null. If affixPattern is null, then
3551 * expAffix is appended as a literal affix.
3552 * @param localized true if the appended pattern should contain localized
3553 * pattern characters; otherwise, non-localized pattern chars are appended
3555 void DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
3556 const UnicodeString
* affixPattern
,
3557 const UnicodeString
& expAffix
,
3558 UBool localized
) const {
3559 if (affixPattern
== 0) {
3560 appendAffixPattern(appendTo
, expAffix
, localized
);
3563 for (int pos
=0; pos
<affixPattern
->length(); pos
=i
) {
3564 i
= affixPattern
->indexOf(kQuote
, pos
);
3567 affixPattern
->extractBetween(pos
, affixPattern
->length(), s
);
3568 appendAffixPattern(appendTo
, s
, localized
);
3573 affixPattern
->extractBetween(pos
, i
, s
);
3574 appendAffixPattern(appendTo
, s
, localized
);
3576 UChar32 c
= affixPattern
->char32At(++i
);
3579 appendTo
.append(c
).append(c
);
3580 // Fall through and append another kQuote below
3581 } else if (c
== kCurrencySign
&&
3582 i
<affixPattern
->length() &&
3583 affixPattern
->char32At(i
) == kCurrencySign
) {
3585 appendTo
.append(c
).append(c
);
3586 } else if (localized
) {
3588 case kPatternPercent
:
3589 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3591 case kPatternPerMill
:
3592 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3595 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3598 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3611 * Append an affix to the given StringBuffer, using quotes if
3612 * there are special characters. Single quotes themselves must be
3613 * escaped in either case.
3616 DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
3617 const UnicodeString
& affix
,
3618 UBool localized
) const {
3621 needQuote
= affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
)) >= 0
3622 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
)) >= 0
3623 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
)) >= 0
3624 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
)) >= 0
3625 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
)) >= 0
3626 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
)) >= 0
3627 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
)) >= 0
3628 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
)) >= 0
3629 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) >= 0
3630 || affix
.indexOf(kCurrencySign
) >= 0;
3633 needQuote
= affix
.indexOf(kPatternZeroDigit
) >= 0
3634 || affix
.indexOf(kPatternGroupingSeparator
) >= 0
3635 || affix
.indexOf(kPatternDecimalSeparator
) >= 0
3636 || affix
.indexOf(kPatternPercent
) >= 0
3637 || affix
.indexOf(kPatternPerMill
) >= 0
3638 || affix
.indexOf(kPatternDigit
) >= 0
3639 || affix
.indexOf(kPatternSeparator
) >= 0
3640 || affix
.indexOf(kPatternExponent
) >= 0
3641 || affix
.indexOf(kPatternPlus
) >= 0
3642 || affix
.indexOf(kPatternMinus
) >= 0
3643 || affix
.indexOf(kCurrencySign
) >= 0;
3646 appendTo
+= (UChar
)0x0027 /*'\''*/;
3647 if (affix
.indexOf((UChar
)0x0027 /*'\''*/) < 0)
3650 for (int32_t j
= 0; j
< affix
.length(); ) {
3651 UChar32 c
= affix
.char32At(j
);
3654 if (c
== 0x0027 /*'\''*/)
3659 appendTo
+= (UChar
)0x0027 /*'\''*/;
3662 //------------------------------------------------------------------------------
3665 DecimalFormat::toPattern(UnicodeString
& result
, UBool localized
) const
3667 if (fStyle
== NumberFormat::kPluralCurrencyStyle
) {
3668 // the prefix or suffix pattern might not be defined yet,
3669 // so they can not be synthesized,
3670 // instead, get them directly.
3671 // but it might not be the actual pattern used in formatting.
3672 // the actual pattern used in formatting depends on the
3673 // formatted number's plural count.
3674 result
= fFormatPattern
;
3678 UChar32 zero
, sigDigit
= kPatternSignificantDigit
;
3679 UnicodeString digit
, group
;
3681 int32_t roundingDecimalPos
= 0; // Pos of decimal in roundingDigits
3682 UnicodeString roundingDigits
;
3683 int32_t padPos
= (fFormatWidth
> 0) ? fPadPosition
: -1;
3684 UnicodeString padSpec
;
3685 UBool useSigDig
= areSignificantDigitsUsed();
3688 digit
.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
3689 group
.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
3690 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
3692 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
3696 digit
.append((UChar
)kPatternDigit
);
3697 group
.append((UChar
)kPatternGroupingSeparator
);
3698 zero
= (UChar32
)kPatternZeroDigit
;
3700 if (fFormatWidth
> 0) {
3702 padSpec
.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
3705 padSpec
.append((UChar
)kPatternPadEscape
);
3707 padSpec
.append(fPad
);
3709 if (fRoundingIncrement
!= NULL
) {
3710 for(i
=0; i
<fRoundingIncrement
->getCount(); ++i
) {
3711 roundingDigits
.append(zero
+(fRoundingIncrement
->getDigitValue(i
))); // Convert to Unicode digit
3713 roundingDecimalPos
= fRoundingIncrement
->getDecimalAt();
3715 for (int32_t part
=0; part
<2; ++part
) {
3716 if (padPos
== kPadBeforePrefix
) {
3717 result
.append(padSpec
);
3719 appendAffixPattern(result
,
3720 (part
==0 ? fPosPrefixPattern
: fNegPrefixPattern
),
3721 (part
==0 ? fPositivePrefix
: fNegativePrefix
),
3723 if (padPos
== kPadAfterPrefix
&& ! padSpec
.isEmpty()) {
3724 result
.append(padSpec
);
3726 int32_t sub0Start
= result
.length();
3727 int32_t g
= isGroupingUsed() ? _max(0, fGroupingSize
) : 0;
3728 if (g
> 0 && fGroupingSize2
> 0 && fGroupingSize2
!= fGroupingSize
) {
3729 g
+= fGroupingSize2
;
3731 int32_t maxDig
= 0, minDig
= 0, maxSigDig
= 0;
3733 minDig
= getMinimumSignificantDigits();
3734 maxDig
= maxSigDig
= getMaximumSignificantDigits();
3736 minDig
= getMinimumIntegerDigits();
3737 maxDig
= getMaximumIntegerDigits();
3739 if (fUseExponentialNotation
) {
3740 if (maxDig
> kMaxScientificIntegerDigits
) {
3743 } else if (useSigDig
) {
3744 maxDig
= _max(maxDig
, g
+1);
3746 maxDig
= _max(_max(g
, getMinimumIntegerDigits()),
3747 roundingDecimalPos
) + 1;
3749 for (i
= maxDig
; i
> 0; --i
) {
3750 if (!fUseExponentialNotation
&& i
<maxDig
&&
3751 isGroupingPosition(i
)) {
3752 result
.append(group
);
3755 // #@,@### (maxSigDig == 5, minSigDig == 2)
3756 // 65 4321 (1-based pos, count from the right)
3757 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
3758 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
3759 if (maxSigDig
>= i
&& i
> (maxSigDig
- minDig
)) {
3760 result
.append(sigDigit
);
3762 result
.append(digit
);
3765 if (! roundingDigits
.isEmpty()) {
3766 int32_t pos
= roundingDecimalPos
- i
;
3767 if (pos
>= 0 && pos
< roundingDigits
.length()) {
3768 result
.append((UChar
) (roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
3773 result
.append(zero
);
3775 result
.append(digit
);
3780 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown
) {
3782 result
+= getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
3785 result
.append((UChar
)kPatternDecimalSeparator
);
3788 int32_t pos
= roundingDecimalPos
;
3789 for (i
= 0; i
< getMaximumFractionDigits(); ++i
) {
3790 if (! roundingDigits
.isEmpty() && pos
< roundingDigits
.length()) {
3792 result
.append(zero
);
3795 result
.append((UChar
)(roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
3800 if (i
<getMinimumFractionDigits()) {
3801 result
.append(zero
);
3804 result
.append(digit
);
3808 if (fUseExponentialNotation
) {
3810 result
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
3813 result
.append((UChar
)kPatternExponent
);
3815 if (fExponentSignAlwaysShown
) {
3817 result
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3820 result
.append((UChar
)kPatternPlus
);
3823 for (i
=0; i
<fMinExponentDigits
; ++i
) {
3824 result
.append(zero
);
3827 if (! padSpec
.isEmpty() && !fUseExponentialNotation
) {
3828 int32_t add
= fFormatWidth
- result
.length() + sub0Start
3830 ? fPositivePrefix
.length() + fPositiveSuffix
.length()
3831 : fNegativePrefix
.length() + fNegativeSuffix
.length());
3833 result
.insert(sub0Start
, digit
);
3836 // Only add a grouping separator if we have at least
3837 // 2 additional characters to be added, so we don't
3838 // end up with ",###".
3839 if (add
>1 && isGroupingPosition(maxDig
)) {
3840 result
.insert(sub0Start
, group
);
3845 if (fPadPosition
== kPadBeforeSuffix
&& ! padSpec
.isEmpty()) {
3846 result
.append(padSpec
);
3849 appendAffixPattern(result
, fPosSuffixPattern
, fPositiveSuffix
, localized
);
3850 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
3851 result
.append(padSpec
);
3853 UBool isDefault
= FALSE
;
3854 if ((fNegSuffixPattern
== fPosSuffixPattern
&& // both null
3855 fNegativeSuffix
== fPositiveSuffix
)
3856 || (fNegSuffixPattern
!= 0 && fPosSuffixPattern
!= 0 &&
3857 *fNegSuffixPattern
== *fPosSuffixPattern
))
3859 if (fNegPrefixPattern
!= NULL
&& fPosPrefixPattern
!= NULL
)
3861 int32_t length
= fPosPrefixPattern
->length();
3862 isDefault
= fNegPrefixPattern
->length() == (length
+2) &&
3863 (*fNegPrefixPattern
)[(int32_t)0] == kQuote
&&
3864 (*fNegPrefixPattern
)[(int32_t)1] == kPatternMinus
&&
3865 fNegPrefixPattern
->compare(2, length
, *fPosPrefixPattern
, 0, length
) == 0;
3868 fNegPrefixPattern
== NULL
&& fPosPrefixPattern
== NULL
)
3870 int32_t length
= fPositivePrefix
.length();
3871 isDefault
= fNegativePrefix
.length() == (length
+1) &&
3872 fNegativePrefix
.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) == 0 &&
3873 fNegativePrefix
.compare(1, length
, fPositivePrefix
, 0, length
) == 0;
3877 break; // Don't output default negative subpattern
3880 result
+= getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
);
3883 result
.append((UChar
)kPatternSeparator
);
3887 appendAffixPattern(result
, fNegSuffixPattern
, fNegativeSuffix
, localized
);
3888 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
3889 result
.append(padSpec
);
3897 //------------------------------------------------------------------------------
3900 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
3902 UParseError parseError
;
3903 applyPattern(pattern
, FALSE
, parseError
, status
);
3906 //------------------------------------------------------------------------------
3909 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
3910 UParseError
& parseError
,
3913 applyPattern(pattern
, FALSE
, parseError
, status
);
3915 //------------------------------------------------------------------------------
3918 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
3920 UParseError parseError
;
3921 applyPattern(pattern
, TRUE
,parseError
,status
);
3924 //------------------------------------------------------------------------------
3927 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
3928 UParseError
& parseError
,
3931 applyPattern(pattern
, TRUE
,parseError
,status
);
3934 //------------------------------------------------------------------------------
3937 DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString
& pattern
,
3939 UParseError
& parseError
,
3942 if (U_FAILURE(status
))
3946 // Clear error struct
3947 parseError
.offset
= -1;
3948 parseError
.preContext
[0] = parseError
.postContext
[0] = (UChar
)0;
3950 // Set the significant pattern symbols
3951 UChar32 zeroDigit
= kPatternZeroDigit
; // '0'
3952 UChar32 sigDigit
= kPatternSignificantDigit
; // '@'
3953 UnicodeString
groupingSeparator ((UChar
)kPatternGroupingSeparator
);
3954 UnicodeString
decimalSeparator ((UChar
)kPatternDecimalSeparator
);
3955 UnicodeString
percent ((UChar
)kPatternPercent
);
3956 UnicodeString
perMill ((UChar
)kPatternPerMill
);
3957 UnicodeString
digit ((UChar
)kPatternDigit
); // '#'
3958 UnicodeString
separator ((UChar
)kPatternSeparator
);
3959 UnicodeString
exponent ((UChar
)kPatternExponent
);
3960 UnicodeString
plus ((UChar
)kPatternPlus
);
3961 UnicodeString
minus ((UChar
)kPatternMinus
);
3962 UnicodeString
padEscape ((UChar
)kPatternPadEscape
);
3963 // Substitute with the localized symbols if necessary
3965 zeroDigit
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
3966 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
3967 groupingSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
3968 decimalSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
));
3969 percent
. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
3970 perMill
. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
3971 digit
. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
3972 separator
. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
));
3973 exponent
. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
));
3974 plus
. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
));
3975 minus
. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
3976 padEscape
. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
3978 UChar nineDigit
= (UChar
)(zeroDigit
+ 9);
3979 int32_t digitLen
= digit
.length();
3980 int32_t groupSepLen
= groupingSeparator
.length();
3981 int32_t decimalSepLen
= decimalSeparator
.length();
3984 int32_t patLen
= pattern
.length();
3985 // Part 0 is the positive pattern. Part 1, if present, is the negative
3987 for (int32_t part
=0; part
<2 && pos
<patLen
; ++part
) {
3988 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
3989 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
3990 // between the prefix and suffix, and consists of pattern
3991 // characters. In the prefix and suffix, percent, perMill, and
3992 // currency symbols are recognized and translated.
3993 int32_t subpart
= 1, sub0Start
= 0, sub0Limit
= 0, sub2Limit
= 0;
3995 // It's important that we don't change any fields of this object
3996 // prematurely. We set the following variables for the multiplier,
3997 // grouping, etc., and then only change the actual object fields if
3998 // everything parses correctly. This also lets us register
3999 // the data from part 0 and ignore the part 1, except for the
4000 // prefix and suffix.
4001 UnicodeString prefix
;
4002 UnicodeString suffix
;
4003 int32_t decimalPos
= -1;
4004 int32_t multiplier
= 1;
4005 int32_t digitLeftCount
= 0, zeroDigitCount
= 0, digitRightCount
= 0, sigDigitCount
= 0;
4006 int8_t groupingCount
= -1;
4007 int8_t groupingCount2
= -1;
4008 int32_t padPos
= -1;
4009 UChar32 padChar
= 0;
4010 int32_t roundingPos
= -1;
4011 DigitList roundingInc
;
4012 int8_t expDigits
= -1;
4013 UBool expSignAlways
= FALSE
;
4015 // The affix is either the prefix or the suffix.
4016 UnicodeString
* affix
= &prefix
;
4018 int32_t start
= pos
;
4019 UBool isPartDone
= FALSE
;
4022 for (; !isPartDone
&& pos
< patLen
; ) {
4023 // Todo: account for surrogate pairs
4024 ch
= pattern
.char32At(pos
);
4026 case 0: // Pattern proper subpart (between prefix & suffix)
4027 // Process the digits, decimal, and grouping characters. We
4028 // record five pieces of information. We expect the digits
4029 // to occur in the pattern ####00.00####, and we record the
4030 // number of left digits, zero (central) digits, and right
4031 // digits. The position of the last grouping character is
4032 // recorded (should be somewhere within the first two blocks
4033 // of characters), as is the position of the decimal point,
4034 // if any (should be in the zero digits). If there is no
4035 // decimal point, then there should be no right digits.
4036 if (pattern
.compare(pos
, digitLen
, digit
) == 0) {
4037 if (zeroDigitCount
> 0 || sigDigitCount
> 0) {
4042 if (groupingCount
>= 0 && decimalPos
< 0) {
4046 } else if ((ch
>= zeroDigit
&& ch
<= nineDigit
) ||
4048 if (digitRightCount
> 0) {
4050 debug("Unexpected '0'")
4051 status
= U_UNEXPECTED_TOKEN
;
4052 syntaxError(pattern
,pos
,parseError
);
4055 if (ch
== sigDigit
) {
4059 if (ch
!= zeroDigit
&& roundingPos
< 0) {
4060 roundingPos
= digitLeftCount
+ zeroDigitCount
;
4062 if (roundingPos
>= 0) {
4063 roundingInc
.append((char)(ch
- zeroDigit
+ '0'));
4066 if (groupingCount
>= 0 && decimalPos
< 0) {
4069 pos
+= U16_LENGTH(ch
);
4070 } else if (pattern
.compare(pos
, groupSepLen
, groupingSeparator
) == 0) {
4071 if (decimalPos
>= 0) {
4072 // Grouping separator after decimal
4073 debug("Grouping separator after decimal")
4074 status
= U_UNEXPECTED_TOKEN
;
4075 syntaxError(pattern
,pos
,parseError
);
4078 groupingCount2
= groupingCount
;
4081 } else if (pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) == 0) {
4082 if (decimalPos
>= 0) {
4083 // Multiple decimal separators
4084 debug("Multiple decimal separators")
4085 status
= U_MULTIPLE_DECIMAL_SEPARATORS
;
4086 syntaxError(pattern
,pos
,parseError
);
4089 // Intentionally incorporate the digitRightCount,
4090 // even though it is illegal for this to be > 0
4091 // at this point. We check pattern syntax below.
4092 decimalPos
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
4093 pos
+= decimalSepLen
;
4095 if (pattern
.compare(pos
, exponent
.length(), exponent
) == 0) {
4096 if (expDigits
>= 0) {
4097 // Multiple exponential symbols
4098 debug("Multiple exponential symbols")
4099 status
= U_MULTIPLE_EXPONENTIAL_SYMBOLS
;
4100 syntaxError(pattern
,pos
,parseError
);
4103 if (groupingCount
>= 0) {
4104 // Grouping separator in exponential pattern
4105 debug("Grouping separator in exponential pattern")
4106 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
4107 syntaxError(pattern
,pos
,parseError
);
4110 pos
+= exponent
.length();
4111 // Check for positive prefix
4113 && pattern
.compare(pos
, plus
.length(), plus
) == 0) {
4114 expSignAlways
= TRUE
;
4115 pos
+= plus
.length();
4117 // Use lookahead to parse out the exponential part of the
4118 // pattern, then jump into suffix subpart.
4120 while (pos
< patLen
&&
4121 pattern
.char32At(pos
) == zeroDigit
) {
4123 pos
+= U16_LENGTH(zeroDigit
);
4126 // 1. Require at least one mantissa pattern digit
4127 // 2. Disallow "#+ @" in mantissa
4128 // 3. Require at least one exponent pattern digit
4129 if (((digitLeftCount
+ zeroDigitCount
) < 1 &&
4130 (sigDigitCount
+ digitRightCount
) < 1) ||
4131 (sigDigitCount
> 0 && digitLeftCount
> 0) ||
4133 // Malformed exponential pattern
4134 debug("Malformed exponential pattern")
4135 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
4136 syntaxError(pattern
,pos
,parseError
);
4140 // Transition to suffix subpart
4141 subpart
= 2; // suffix subpart
4147 case 1: // Prefix subpart
4148 case 2: // Suffix subpart
4149 // Process the prefix / suffix characters
4150 // Process unquoted characters seen in prefix or suffix
4153 // Several syntax characters implicitly begins the
4154 // next subpart if we are in the prefix; otherwise
4155 // they are illegal if unquoted.
4156 if (!pattern
.compare(pos
, digitLen
, digit
) ||
4157 !pattern
.compare(pos
, groupSepLen
, groupingSeparator
) ||
4158 !pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) ||
4159 (ch
>= zeroDigit
&& ch
<= nineDigit
) ||
4161 if (subpart
== 1) { // prefix subpart
4162 subpart
= 0; // pattern proper subpart
4163 sub0Start
= pos
; // Reprocess this character
4166 status
= U_UNQUOTED_SPECIAL
;
4167 syntaxError(pattern
,pos
,parseError
);
4170 } else if (ch
== kCurrencySign
) {
4171 affix
->append(kQuote
); // Encode currency
4172 // Use lookahead to determine if the currency sign is
4174 U_ASSERT(U16_LENGTH(kCurrencySign
) == 1);
4175 if ((pos
+1) < pattern
.length() && pattern
[pos
+1] == kCurrencySign
) {
4176 affix
->append(kCurrencySign
);
4177 ++pos
; // Skip over the doubled character
4178 if ((pos
+1) < pattern
.length() &&
4179 pattern
[pos
+1] == kCurrencySign
) {
4180 affix
->append(kCurrencySign
);
4181 ++pos
; // Skip over the doubled character
4182 fCurrencySignCount
= fgCurrencySignCountInPluralFormat
;
4184 fCurrencySignCount
= fgCurrencySignCountInISOFormat
;
4187 fCurrencySignCount
= fgCurrencySignCountInSymbolFormat
;
4189 // Fall through to append(ch)
4190 } else if (ch
== kQuote
) {
4191 // A quote outside quotes indicates either the opening
4192 // quote or two quotes, which is a quote literal. That is,
4193 // we have the first quote in 'do' or o''clock.
4194 U_ASSERT(U16_LENGTH(kQuote
) == 1);
4196 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
4197 affix
->append(kQuote
); // Encode quote
4198 // Fall through to append(ch)
4200 subpart
+= 2; // open quote
4203 } else if (pattern
.compare(pos
, separator
.length(), separator
) == 0) {
4204 // Don't allow separators in the prefix, and don't allow
4205 // separators in the second pattern (part == 1).
4206 if (subpart
== 1 || part
== 1) {
4207 // Unexpected separator
4208 debug("Unexpected separator")
4209 status
= U_UNEXPECTED_TOKEN
;
4210 syntaxError(pattern
,pos
,parseError
);
4214 isPartDone
= TRUE
; // Go to next part
4215 pos
+= separator
.length();
4217 } else if (pattern
.compare(pos
, percent
.length(), percent
) == 0) {
4218 // Next handle characters which are appended directly.
4219 if (multiplier
!= 1) {
4220 // Too many percent/perMill characters
4221 debug("Too many percent characters")
4222 status
= U_MULTIPLE_PERCENT_SYMBOLS
;
4223 syntaxError(pattern
,pos
,parseError
);
4226 affix
->append(kQuote
); // Encode percent/perMill
4227 affix
->append(kPatternPercent
); // Use unlocalized pattern char
4229 pos
+= percent
.length();
4231 } else if (pattern
.compare(pos
, perMill
.length(), perMill
) == 0) {
4232 // Next handle characters which are appended directly.
4233 if (multiplier
!= 1) {
4234 // Too many percent/perMill characters
4235 debug("Too many perMill characters")
4236 status
= U_MULTIPLE_PERMILL_SYMBOLS
;
4237 syntaxError(pattern
,pos
,parseError
);
4240 affix
->append(kQuote
); // Encode percent/perMill
4241 affix
->append(kPatternPerMill
); // Use unlocalized pattern char
4243 pos
+= perMill
.length();
4245 } else if (pattern
.compare(pos
, padEscape
.length(), padEscape
) == 0) {
4246 if (padPos
>= 0 || // Multiple pad specifiers
4247 (pos
+1) == pattern
.length()) { // Nothing after padEscape
4248 debug("Multiple pad specifiers")
4249 status
= U_MULTIPLE_PAD_SPECIFIERS
;
4250 syntaxError(pattern
,pos
,parseError
);
4254 pos
+= padEscape
.length();
4255 padChar
= pattern
.char32At(pos
);
4256 pos
+= U16_LENGTH(padChar
);
4258 } else if (pattern
.compare(pos
, minus
.length(), minus
) == 0) {
4259 affix
->append(kQuote
); // Encode minus
4260 affix
->append(kPatternMinus
);
4261 pos
+= minus
.length();
4263 } else if (pattern
.compare(pos
, plus
.length(), plus
) == 0) {
4264 affix
->append(kQuote
); // Encode plus
4265 affix
->append(kPatternPlus
);
4266 pos
+= plus
.length();
4269 // Unquoted, non-special characters fall through to here, as
4270 // well as other code which needs to append something to the
4273 pos
+= U16_LENGTH(ch
);
4275 case 3: // Prefix subpart, in quote
4276 case 4: // Suffix subpart, in quote
4277 // A quote within quotes indicates either the closing
4278 // quote or two quotes, which is a quote literal. That is,
4279 // we have the second quote in 'do' or 'don''t'.
4282 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
4283 affix
->append(kQuote
); // Encode quote
4284 // Fall through to append(ch)
4286 subpart
-= 2; // close quote
4291 pos
+= U16_LENGTH(ch
);
4296 if (sub0Limit
== 0) {
4297 sub0Limit
= pattern
.length();
4300 if (sub2Limit
== 0) {
4301 sub2Limit
= pattern
.length();
4304 /* Handle patterns with no '0' pattern character. These patterns
4305 * are legal, but must be recodified to make sense. "##.###" ->
4306 * "#0.###". ".###" -> ".0##".
4308 * We allow patterns of the form "####" to produce a zeroDigitCount
4309 * of zero (got that?); although this seems like it might make it
4310 * possible for format() to produce empty strings, format() checks
4311 * for this condition and outputs a zero digit in this situation.
4312 * Having a zeroDigitCount of zero yields a minimum integer digits
4313 * of zero, which allows proper round-trip patterns. We don't want
4314 * "#" to become "#0" when toPattern() is called (even though that's
4315 * what it really is, semantically).
4317 if (zeroDigitCount
== 0 && sigDigitCount
== 0 &&
4318 digitLeftCount
> 0 && decimalPos
>= 0) {
4319 // Handle "###.###" and "###." and ".###"
4322 ++n
; // Handle ".###"
4323 digitRightCount
= digitLeftCount
- n
;
4324 digitLeftCount
= n
- 1;
4328 // Do syntax checking on the digits, decimal points, and quotes.
4329 if ((decimalPos
< 0 && digitRightCount
> 0 && sigDigitCount
== 0) ||
4331 (sigDigitCount
> 0 ||
4332 decimalPos
< digitLeftCount
||
4333 decimalPos
> (digitLeftCount
+ zeroDigitCount
))) ||
4334 groupingCount
== 0 || groupingCount2
== 0 ||
4335 (sigDigitCount
> 0 && zeroDigitCount
> 0) ||
4337 { // subpart > 2 == unmatched quote
4338 debug("Syntax error")
4339 status
= U_PATTERN_SYNTAX_ERROR
;
4340 syntaxError(pattern
,pos
,parseError
);
4344 // Make sure pad is at legal position before or after affix.
4346 if (padPos
== start
) {
4347 padPos
= kPadBeforePrefix
;
4348 } else if (padPos
+2 == sub0Start
) {
4349 padPos
= kPadAfterPrefix
;
4350 } else if (padPos
== sub0Limit
) {
4351 padPos
= kPadBeforeSuffix
;
4352 } else if (padPos
+2 == sub2Limit
) {
4353 padPos
= kPadAfterSuffix
;
4355 // Illegal pad position
4356 debug("Illegal pad position")
4357 status
= U_ILLEGAL_PAD_POSITION
;
4358 syntaxError(pattern
,pos
,parseError
);
4364 delete fPosPrefixPattern
;
4365 delete fPosSuffixPattern
;
4366 delete fNegPrefixPattern
;
4367 delete fNegSuffixPattern
;
4368 fPosPrefixPattern
= new UnicodeString(prefix
);
4370 if (fPosPrefixPattern
== 0) {
4371 status
= U_MEMORY_ALLOCATION_ERROR
;
4374 fPosSuffixPattern
= new UnicodeString(suffix
);
4376 if (fPosSuffixPattern
== 0) {
4377 status
= U_MEMORY_ALLOCATION_ERROR
;
4378 delete fPosPrefixPattern
;
4381 fNegPrefixPattern
= 0;
4382 fNegSuffixPattern
= 0;
4384 fUseExponentialNotation
= (expDigits
>= 0);
4385 if (fUseExponentialNotation
) {
4386 fMinExponentDigits
= expDigits
;
4388 fExponentSignAlwaysShown
= expSignAlways
;
4389 int32_t digitTotalCount
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
4390 // The effectiveDecimalPos is the position the decimal is at or
4391 // would be at if there is no decimal. Note that if
4392 // decimalPos<0, then digitTotalCount == digitLeftCount +
4394 int32_t effectiveDecimalPos
= decimalPos
>= 0 ? decimalPos
: digitTotalCount
;
4395 UBool isSigDig
= (sigDigitCount
> 0);
4396 setSignificantDigitsUsed(isSigDig
);
4398 setMinimumSignificantDigits(sigDigitCount
);
4399 setMaximumSignificantDigits(sigDigitCount
+ digitRightCount
);
4401 int32_t minInt
= effectiveDecimalPos
- digitLeftCount
;
4402 setMinimumIntegerDigits(minInt
);
4403 setMaximumIntegerDigits(fUseExponentialNotation
4404 ? digitLeftCount
+ getMinimumIntegerDigits()
4405 : kDoubleIntegerDigits
);
4406 setMaximumFractionDigits(decimalPos
>= 0
4407 ? (digitTotalCount
- decimalPos
) : 0);
4408 setMinimumFractionDigits(decimalPos
>= 0
4409 ? (digitLeftCount
+ zeroDigitCount
- decimalPos
) : 0);
4411 setGroupingUsed(groupingCount
> 0);
4412 fGroupingSize
= (groupingCount
> 0) ? groupingCount
: 0;
4413 fGroupingSize2
= (groupingCount2
> 0 && groupingCount2
!= groupingCount
)
4414 ? groupingCount2
: 0;
4415 setMultiplier(multiplier
);
4416 setDecimalSeparatorAlwaysShown(decimalPos
== 0
4417 || decimalPos
== digitTotalCount
);
4419 fPadPosition
= (EPadPosition
) padPos
;
4420 // To compute the format width, first set up sub0Limit -
4421 // sub0Start. Add in prefix/suffix length later.
4423 // fFormatWidth = prefix.length() + suffix.length() +
4424 // sub0Limit - sub0Start;
4425 fFormatWidth
= sub0Limit
- sub0Start
;
4430 if (roundingPos
>= 0) {
4431 roundingInc
.setDecimalAt(effectiveDecimalPos
- roundingPos
);
4432 if (fRoundingIncrement
!= NULL
) {
4433 *fRoundingIncrement
= roundingInc
;
4435 fRoundingIncrement
= new DigitList(roundingInc
);
4437 if (fRoundingIncrement
== NULL
) {
4438 status
= U_MEMORY_ALLOCATION_ERROR
;
4439 delete fPosPrefixPattern
;
4440 delete fPosSuffixPattern
;
4444 fRoundingIncrement
->getDouble(); // forces caching of double in the DigitList,
4445 // makes getting it thread safe.
4446 fRoundingMode
= kRoundHalfEven
;
4448 setRoundingIncrement(0.0);
4451 fNegPrefixPattern
= new UnicodeString(prefix
);
4453 if (fNegPrefixPattern
== 0) {
4454 status
= U_MEMORY_ALLOCATION_ERROR
;
4457 fNegSuffixPattern
= new UnicodeString(suffix
);
4459 if (fNegSuffixPattern
== 0) {
4460 delete fNegPrefixPattern
;
4461 status
= U_MEMORY_ALLOCATION_ERROR
;
4467 if (pattern
.length() == 0) {
4468 delete fNegPrefixPattern
;
4469 delete fNegSuffixPattern
;
4470 fNegPrefixPattern
= NULL
;
4471 fNegSuffixPattern
= NULL
;
4472 if (fPosPrefixPattern
!= NULL
) {
4473 fPosPrefixPattern
->remove();
4475 fPosPrefixPattern
= new UnicodeString();
4477 if (fPosPrefixPattern
== 0) {
4478 status
= U_MEMORY_ALLOCATION_ERROR
;
4482 if (fPosSuffixPattern
!= NULL
) {
4483 fPosSuffixPattern
->remove();
4485 fPosSuffixPattern
= new UnicodeString();
4487 if (fPosSuffixPattern
== 0) {
4488 delete fPosPrefixPattern
;
4489 status
= U_MEMORY_ALLOCATION_ERROR
;
4494 setMinimumIntegerDigits(0);
4495 setMaximumIntegerDigits(kDoubleIntegerDigits
);
4496 setMinimumFractionDigits(0);
4497 setMaximumFractionDigits(kDoubleFractionDigits
);
4499 fUseExponentialNotation
= FALSE
;
4500 fCurrencySignCount
= 0;
4501 setGroupingUsed(FALSE
);
4505 setDecimalSeparatorAlwaysShown(FALSE
);
4507 setRoundingIncrement(0.0);
4510 // If there was no negative pattern, or if the negative pattern is
4511 // identical to the positive pattern, then prepend the minus sign to the
4512 // positive pattern to form the negative pattern.
4513 if (fNegPrefixPattern
== NULL
||
4514 (*fNegPrefixPattern
== *fPosPrefixPattern
4515 && *fNegSuffixPattern
== *fPosSuffixPattern
)) {
4516 _copy_us_ptr(&fNegSuffixPattern
, fPosSuffixPattern
);
4517 if (fNegPrefixPattern
== NULL
) {
4518 fNegPrefixPattern
= new UnicodeString();
4520 if (fNegPrefixPattern
== 0) {
4521 status
= U_MEMORY_ALLOCATION_ERROR
;
4525 fNegPrefixPattern
->remove();
4527 fNegPrefixPattern
->append(kQuote
).append(kPatternMinus
)
4528 .append(*fPosPrefixPattern
);
4532 s
.append("\"").append(pattern
).append("\"->");
4537 fFormatPattern
= pattern
;
4542 DecimalFormat::expandAffixAdjustWidth(const UnicodeString
* pluralCount
) {
4543 expandAffixes(pluralCount
);
4544 if (fFormatWidth
> 0) {
4545 // Finish computing format width (see above)
4546 // TODO: how to handle fFormatWidth,
4547 // need to save in f(Plural)AffixesForCurrecy?
4548 fFormatWidth
+= fPositivePrefix
.length() + fPositiveSuffix
.length();
4554 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
4556 UParseError
& parseError
,
4559 // do the following re-set first. since they change private data by
4560 // apply pattern again.
4561 if (pattern
.indexOf(kCurrencySign
) != -1) {
4562 if (fCurrencyPluralInfo
== NULL
) {
4563 // initialize currencyPluralInfo if needed
4564 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
4566 if (fAffixPatternsForCurrency
== NULL
) {
4567 setupCurrencyAffixPatterns(status
);
4569 if (pattern
.indexOf(fgTripleCurrencySign
) != -1) {
4570 // only setup the affixes of the current pattern.
4571 setupCurrencyAffixes(pattern
, TRUE
, FALSE
, status
);
4574 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
4575 expandAffixAdjustWidth(NULL
);
4580 DecimalFormat::applyPatternInternally(const UnicodeString
& pluralCount
,
4581 const UnicodeString
& pattern
,
4583 UParseError
& parseError
,
4584 UErrorCode
& status
) {
4585 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
4586 expandAffixAdjustWidth(&pluralCount
);
4591 * Sets the maximum number of digits allowed in the integer portion of a
4592 * number. This override limits the integer digit count to 309.
4593 * @see NumberFormat#setMaximumIntegerDigits
4595 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
4596 NumberFormat::setMaximumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
4600 * Sets the minimum number of digits allowed in the integer portion of a
4601 * number. This override limits the integer digit count to 309.
4602 * @see NumberFormat#setMinimumIntegerDigits
4604 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
4605 NumberFormat::setMinimumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
4609 * Sets the maximum number of digits allowed in the fraction portion of a
4610 * number. This override limits the fraction digit count to 340.
4611 * @see NumberFormat#setMaximumFractionDigits
4613 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
4614 NumberFormat::setMaximumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
4618 * Sets the minimum number of digits allowed in the fraction portion of a
4619 * number. This override limits the fraction digit count to 340.
4620 * @see NumberFormat#setMinimumFractionDigits
4622 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
4623 NumberFormat::setMinimumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
4626 int32_t DecimalFormat::getMinimumSignificantDigits() const {
4627 return fMinSignificantDigits
;
4630 int32_t DecimalFormat::getMaximumSignificantDigits() const {
4631 return fMaxSignificantDigits
;
4634 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
4638 // pin max sig dig to >= min
4639 int32_t max
= _max(fMaxSignificantDigits
, min
);
4640 fMinSignificantDigits
= min
;
4641 fMaxSignificantDigits
= max
;
4644 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
4648 // pin min sig dig to 1..max
4649 U_ASSERT(fMinSignificantDigits
>= 1);
4650 int32_t min
= _min(fMinSignificantDigits
, max
);
4651 fMinSignificantDigits
= min
;
4652 fMaxSignificantDigits
= max
;
4655 UBool
DecimalFormat::areSignificantDigitsUsed() const {
4656 return fUseSignificantDigits
;
4659 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
4660 fUseSignificantDigits
= useSignificantDigits
;
4663 void DecimalFormat::setCurrencyInternally(const UChar
* theCurrency
,
4665 // If we are a currency format, then modify our affixes to
4666 // encode the currency symbol for the given currency in our
4667 // locale, and adjust the decimal digits and rounding for the
4670 // Note: The code is ordered so that this object is *not changed*
4671 // until we are sure we are going to succeed.
4673 // NULL or empty currency is *legal* and indicates no currency.
4674 UBool isCurr
= (theCurrency
&& *theCurrency
);
4676 double rounding
= 0.0;
4678 if (fCurrencySignCount
> fgCurrencySignCountZero
&& isCurr
) {
4679 rounding
= ucurr_getRoundingIncrement(theCurrency
, &ec
);
4680 frac
= ucurr_getDefaultFractionDigits(theCurrency
, &ec
);
4683 NumberFormat::setCurrency(theCurrency
, ec
);
4684 if (U_FAILURE(ec
)) return;
4686 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
4687 // NULL or empty currency is *legal* and indicates no currency.
4689 setRoundingIncrement(rounding
);
4690 setMinimumFractionDigits(frac
);
4691 setMaximumFractionDigits(frac
);
4693 expandAffixes(NULL
);
4697 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
4698 // set the currency before compute affixes to get the right currency names
4699 NumberFormat::setCurrency(theCurrency
, ec
);
4700 if (fFormatPattern
.indexOf(fgTripleCurrencySign
) != -1) {
4701 UnicodeString savedPtn
= fFormatPattern
;
4702 setupCurrencyAffixes(fFormatPattern
, TRUE
, TRUE
, ec
);
4703 UParseError parseErr
;
4704 applyPattern(savedPtn
, FALSE
, parseErr
, ec
);
4706 // set the currency after apply pattern to get the correct rounding/fraction
4707 setCurrencyInternally(theCurrency
, ec
);
4710 // Deprecated variant with no UErrorCode parameter
4711 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
4712 UErrorCode ec
= U_ZERO_ERROR
;
4713 setCurrency(theCurrency
, ec
);
4716 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
4717 if (fSymbols
== NULL
) {
4718 ec
= U_MEMORY_ALLOCATION_ERROR
;
4722 const UChar
* c
= getCurrency();
4724 const UnicodeString
&intl
=
4725 fSymbols
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
4726 c
= intl
.getBuffer(); // ok for intl to go out of scope
4728 u_strncpy(result
, c
, 3);
4733 * Return the number of fraction digits to display, or the total
4734 * number of digits for significant digit formats and exponential
4738 DecimalFormat::precision() const {
4739 if (areSignificantDigitsUsed()) {
4740 return getMaximumSignificantDigits();
4741 } else if (fUseExponentialNotation
) {
4742 return getMinimumIntegerDigits() + getMaximumFractionDigits();
4744 return getMaximumFractionDigits();
4749 // TODO: template algorithm
4751 DecimalFormat::initHashForAffix(UErrorCode
& status
) {
4752 if ( U_FAILURE(status
) ) {
4756 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
4757 status
= U_MEMORY_ALLOCATION_ERROR
;
4760 if ( U_FAILURE(status
) ) {
4764 hTable
->setValueComparator(decimfmtAffixValueComparator
);
4769 DecimalFormat::initHashForAffixPattern(UErrorCode
& status
) {
4770 if ( U_FAILURE(status
) ) {
4774 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
4775 status
= U_MEMORY_ALLOCATION_ERROR
;
4778 if ( U_FAILURE(status
) ) {
4782 hTable
->setValueComparator(decimfmtAffixPatternValueComparator
);
4787 DecimalFormat::deleteHashForAffix(Hashtable
*& table
)
4789 if ( table
== NULL
) {
4793 const UHashElement
* element
= NULL
;
4794 while ( (element
= table
->nextElement(pos
)) != NULL
) {
4795 const UHashTok keyTok
= element
->key
;
4796 const UHashTok valueTok
= element
->value
;
4797 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
4807 DecimalFormat::deleteHashForAffixPattern()
4809 if ( fAffixPatternsForCurrency
== NULL
) {
4813 const UHashElement
* element
= NULL
;
4814 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
4815 const UHashTok keyTok
= element
->key
;
4816 const UHashTok valueTok
= element
->value
;
4817 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
4820 delete fAffixPatternsForCurrency
;
4821 fAffixPatternsForCurrency
= NULL
;
4826 DecimalFormat::copyHashForAffixPattern(const Hashtable
* source
,
4828 UErrorCode
& status
) {
4829 if ( U_FAILURE(status
) ) {
4833 const UHashElement
* element
= NULL
;
4835 while ( (element
= source
->nextElement(pos
)) != NULL
) {
4836 const UHashTok keyTok
= element
->key
;
4837 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
4838 const UHashTok valueTok
= element
->value
;
4839 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
4840 AffixPatternsForCurrency
* copy
= new AffixPatternsForCurrency(
4841 value
->negPrefixPatternForCurrency
,
4842 value
->negSuffixPatternForCurrency
,
4843 value
->posPrefixPatternForCurrency
,
4844 value
->posSuffixPatternForCurrency
,
4845 value
->patternType
);
4846 target
->put(UnicodeString(*key
), copy
, status
);
4847 if ( U_FAILURE(status
) ) {
4857 DecimalFormat::copyHashForAffix(const Hashtable
* source
,
4859 UErrorCode
& status
) {
4860 if ( U_FAILURE(status
) ) {
4864 const UHashElement
* element
= NULL
;
4866 while ( (element
= source
->nextElement(pos
)) != NULL
) {
4867 const UHashTok keyTok
= element
->key
;
4868 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
4870 const UHashTok valueTok
= element
->value
;
4871 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
4872 AffixesForCurrency
* copy
= new AffixesForCurrency(
4873 value
->negPrefixForCurrency
,
4874 value
->negSuffixForCurrency
,
4875 value
->posPrefixForCurrency
,
4876 value
->posSuffixForCurrency
);
4877 target
->put(UnicodeString(*key
), copy
, status
);
4878 if ( U_FAILURE(status
) ) {
4887 #endif /* #if !UCONFIG_NO_FORMATTING */