2 *******************************************************************************
3 * Copyright (C) 1997-2012, 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"
56 #include "unicode/utf16.h"
57 #include "unicode/numsys.h"
58 #include "unicode/localpointer.h"
63 #include "patternprops.h"
76 /* For currency parsing purose,
77 * Need to remember all prefix patterns and suffix patterns of
78 * every currency format pattern,
79 * including the pattern of default currecny style
80 * and plural currency style. And the patterns are set through applyPattern.
82 struct AffixPatternsForCurrency
: public UMemory
{
83 // negative prefix pattern
84 UnicodeString negPrefixPatternForCurrency
;
85 // negative suffix pattern
86 UnicodeString negSuffixPatternForCurrency
;
87 // positive prefix pattern
88 UnicodeString posPrefixPatternForCurrency
;
89 // positive suffix pattern
90 UnicodeString posSuffixPatternForCurrency
;
93 AffixPatternsForCurrency(const UnicodeString
& negPrefix
,
94 const UnicodeString
& negSuffix
,
95 const UnicodeString
& posPrefix
,
96 const UnicodeString
& posSuffix
,
98 negPrefixPatternForCurrency
= negPrefix
;
99 negSuffixPatternForCurrency
= negSuffix
;
100 posPrefixPatternForCurrency
= posPrefix
;
101 posSuffixPatternForCurrency
= posSuffix
;
106 /* affix for currency formatting when the currency sign in the pattern
107 * equals to 3, such as the pattern contains 3 currency sign or
108 * the formatter style is currency plural format style.
110 struct AffixesForCurrency
: public UMemory
{
112 UnicodeString negPrefixForCurrency
;
114 UnicodeString negSuffixForCurrency
;
116 UnicodeString posPrefixForCurrency
;
118 UnicodeString posSuffixForCurrency
;
122 AffixesForCurrency(const UnicodeString
& negPrefix
,
123 const UnicodeString
& negSuffix
,
124 const UnicodeString
& posPrefix
,
125 const UnicodeString
& posSuffix
) {
126 negPrefixForCurrency
= negPrefix
;
127 negSuffixForCurrency
= negSuffix
;
128 posPrefixForCurrency
= posPrefix
;
129 posSuffixForCurrency
= posSuffix
;
138 static UBool U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
);
143 static UBool U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
);
147 U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
) {
148 const AffixesForCurrency
* affix_1
=
149 (AffixesForCurrency
*)val1
.pointer
;
150 const AffixesForCurrency
* affix_2
=
151 (AffixesForCurrency
*)val2
.pointer
;
152 return affix_1
->negPrefixForCurrency
== affix_2
->negPrefixForCurrency
&&
153 affix_1
->negSuffixForCurrency
== affix_2
->negSuffixForCurrency
&&
154 affix_1
->posPrefixForCurrency
== affix_2
->posPrefixForCurrency
&&
155 affix_1
->posSuffixForCurrency
== affix_2
->posSuffixForCurrency
;
160 U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
) {
161 const AffixPatternsForCurrency
* affix_1
=
162 (AffixPatternsForCurrency
*)val1
.pointer
;
163 const AffixPatternsForCurrency
* affix_2
=
164 (AffixPatternsForCurrency
*)val2
.pointer
;
165 return affix_1
->negPrefixPatternForCurrency
==
166 affix_2
->negPrefixPatternForCurrency
&&
167 affix_1
->negSuffixPatternForCurrency
==
168 affix_2
->negSuffixPatternForCurrency
&&
169 affix_1
->posPrefixPatternForCurrency
==
170 affix_2
->posPrefixPatternForCurrency
&&
171 affix_1
->posSuffixPatternForCurrency
==
172 affix_2
->posSuffixPatternForCurrency
&&
173 affix_1
->patternType
== affix_2
->patternType
;
183 static void debugout(UnicodeString s
) {
185 s
.extract((int32_t) 0, s
.length(), buf
);
188 #define debug(x) printf("%s\n", x);
196 // *****************************************************************************
197 // class DecimalFormat
198 // *****************************************************************************
200 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat
)
202 // Constants for characters used in programmatic (unlocalized) patterns.
203 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
204 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
205 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
206 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
207 #define kPatternPerMill ((UChar)0x2030)
208 #define kPatternPercent ((UChar)0x0025) /*'%'*/
209 #define kPatternDigit ((UChar)0x0023) /*'#'*/
210 #define kPatternSeparator ((UChar)0x003B) /*';'*/
211 #define kPatternExponent ((UChar)0x0045) /*'E'*/
212 #define kPatternPlus ((UChar)0x002B) /*'+'*/
213 #define kPatternMinus ((UChar)0x002D) /*'-'*/
214 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
215 #define kQuote ((UChar)0x0027) /*'\''*/
217 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
218 * is used in patterns and substitued with either the currency symbol,
219 * or if it is doubled, with the international currency symbol. If the
220 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
221 * replaced with the monetary decimal separator.
223 #define kCurrencySign ((UChar)0x00A4)
224 #define kDefaultPad ((UChar)0x0020) /* */
226 const int32_t DecimalFormat::kDoubleIntegerDigits
= 309;
227 const int32_t DecimalFormat::kDoubleFractionDigits
= 340;
229 const int32_t DecimalFormat::kMaxScientificIntegerDigits
= 8;
232 * These are the tags we expect to see in normal resource bundle files associated
235 const char DecimalFormat::fgNumberPatterns
[]="NumberPatterns"; // Deprecated - not used
236 static const char fgNumberElements
[]="NumberElements";
237 static const char fgLatn
[]="latn";
238 static const char fgPatterns
[]="patterns";
239 static const char fgDecimalFormat
[]="decimalFormat";
240 static const char fgCurrencyFormat
[]="currencyFormat";
241 static const UChar fgTripleCurrencySign
[] = {0xA4, 0xA4, 0xA4, 0};
243 inline int32_t _min(int32_t a
, int32_t b
) { return (a
<b
) ? a
: b
; }
244 inline int32_t _max(int32_t a
, int32_t b
) { return (a
<b
) ? b
: a
; }
246 //------------------------------------------------------------------------------
247 // Constructs a DecimalFormat instance in the default locale.
249 DecimalFormat::DecimalFormat(UErrorCode
& status
) {
251 UParseError parseError
;
252 construct(status
, parseError
);
255 //------------------------------------------------------------------------------
256 // Constructs a DecimalFormat instance with the specified number format
257 // pattern in the default locale.
259 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
260 UErrorCode
& status
) {
262 UParseError parseError
;
263 construct(status
, parseError
, &pattern
);
266 //------------------------------------------------------------------------------
267 // Constructs a DecimalFormat instance with the specified number format
268 // pattern and the number format symbols in the default locale. The
269 // created instance owns the symbols.
271 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
272 DecimalFormatSymbols
* symbolsToAdopt
,
273 UErrorCode
& status
) {
275 UParseError parseError
;
276 if (symbolsToAdopt
== NULL
)
277 status
= U_ILLEGAL_ARGUMENT_ERROR
;
278 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
281 DecimalFormat::DecimalFormat( const UnicodeString
& pattern
,
282 DecimalFormatSymbols
* symbolsToAdopt
,
283 UParseError
& parseErr
,
284 UErrorCode
& status
) {
286 if (symbolsToAdopt
== NULL
)
287 status
= U_ILLEGAL_ARGUMENT_ERROR
;
288 construct(status
,parseErr
, &pattern
, symbolsToAdopt
);
291 //------------------------------------------------------------------------------
292 // Constructs a DecimalFormat instance with the specified number format
293 // pattern and the number format symbols in the default locale. The
294 // created instance owns the clone of the symbols.
296 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
297 const DecimalFormatSymbols
& symbols
,
298 UErrorCode
& status
) {
300 UParseError parseError
;
301 construct(status
, parseError
, &pattern
, new DecimalFormatSymbols(symbols
));
304 //------------------------------------------------------------------------------
305 // Constructs a DecimalFormat instance with the specified number format
306 // pattern, the number format symbols, and the number format style.
307 // The created instance owns the clone of the symbols.
309 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
310 DecimalFormatSymbols
* symbolsToAdopt
,
311 UNumberFormatStyle style
,
312 UErrorCode
& status
) {
315 UParseError parseError
;
316 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
319 //-----------------------------------------------------------------------------
320 // Common DecimalFormat initialization.
321 // Put all fields of an uninitialized object into a known state.
322 // Common code, shared by all constructors.
324 DecimalFormat::init() {
325 fPosPrefixPattern
= 0;
326 fPosSuffixPattern
= 0;
327 fNegPrefixPattern
= 0;
328 fNegSuffixPattern
= 0;
333 fDecimalSeparatorAlwaysShown
= FALSE
;
335 fUseSignificantDigits
= FALSE
;
336 fMinSignificantDigits
= 1;
337 fMaxSignificantDigits
= 6;
338 fUseExponentialNotation
= FALSE
;
339 fMinExponentDigits
= 0;
340 fExponentSignAlwaysShown
= FALSE
;
341 fRoundingIncrement
= 0;
342 fRoundingMode
= kRoundHalfEven
;
345 fPadPosition
= kPadBeforePrefix
;
346 fStyle
= UNUM_DECIMAL
;
347 fCurrencySignCount
= 0;
348 fAffixPatternsForCurrency
= NULL
;
349 fAffixesForCurrency
= NULL
;
350 fPluralAffixesForCurrency
= NULL
;
351 fCurrencyPluralInfo
= NULL
;
354 //------------------------------------------------------------------------------
355 // Constructs a DecimalFormat instance with the specified number format
356 // pattern and the number format symbols in the desired locale. The
357 // created instance owns the symbols.
360 DecimalFormat::construct(UErrorCode
& status
,
361 UParseError
& parseErr
,
362 const UnicodeString
* pattern
,
363 DecimalFormatSymbols
* symbolsToAdopt
)
365 fSymbols
= symbolsToAdopt
; // Do this BEFORE aborting on status failure!!!
366 fRoundingIncrement
= NULL
;
367 fRoundingMode
= kRoundHalfEven
;
368 fPad
= kPatternPadEscape
;
369 fPadPosition
= kPadBeforePrefix
;
370 if (U_FAILURE(status
))
373 fPosPrefixPattern
= fPosSuffixPattern
= NULL
;
374 fNegPrefixPattern
= fNegSuffixPattern
= NULL
;
378 fDecimalSeparatorAlwaysShown
= FALSE
;
379 fUseExponentialNotation
= FALSE
;
380 fMinExponentDigits
= 0;
382 if (fSymbols
== NULL
)
384 fSymbols
= new DecimalFormatSymbols(Locale::getDefault(), status
);
387 status
= U_MEMORY_ALLOCATION_ERROR
;
391 UErrorCode nsStatus
= U_ZERO_ERROR
;
392 NumberingSystem
*ns
= NumberingSystem::createInstance(nsStatus
);
393 if (U_FAILURE(nsStatus
)) {
399 // Uses the default locale's number format pattern if there isn't
404 UResourceBundle
*top
= ures_open(NULL
, Locale::getDefault().getName(), &status
);
406 UResourceBundle
*resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, NULL
, &status
);
407 resource
= ures_getByKeyWithFallback(resource
, ns
->getName(), resource
, &status
);
408 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
409 const UChar
*resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
410 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(fgLatn
,ns
->getName())) {
411 status
= U_ZERO_ERROR
;
412 resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, resource
, &status
);
413 resource
= ures_getByKeyWithFallback(resource
, fgLatn
, resource
, &status
);
414 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
415 resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
417 str
.setTo(TRUE
, resStr
, len
);
419 ures_close(resource
);
425 if (U_FAILURE(status
))
430 if (pattern
->indexOf((UChar
)kCurrencySign
) >= 0) {
431 // If it looks like we are going to use a currency pattern
432 // then do the time consuming lookup.
433 setCurrencyForSymbols();
435 setCurrencyInternally(NULL
, status
);
438 const UnicodeString
* patternUsed
;
439 UnicodeString currencyPluralPatternForOther
;
441 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
442 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
443 if (U_FAILURE(status
)) {
447 // the pattern used in format is not fixed until formatting,
448 // in which, the number is known and
449 // will be used to pick the right pattern based on plural count.
450 // Here, set the pattern as the pattern of plural count == "other".
451 // For most locale, the patterns are probably the same for all
452 // plural count. If not, the right pattern need to be re-applied
454 fCurrencyPluralInfo
->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther
);
455 patternUsed
= ¤cyPluralPatternForOther
;
457 setCurrencyForSymbols();
460 patternUsed
= pattern
;
463 if (patternUsed
->indexOf(kCurrencySign
) != -1) {
464 // initialize for currency, not only for plural format,
465 // but also for mix parsing
466 if (fCurrencyPluralInfo
== NULL
) {
467 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
468 if (U_FAILURE(status
)) {
472 // need it for mix parsing
473 setupCurrencyAffixPatterns(status
);
474 // expanded affixes for plural names
475 if (patternUsed
->indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
476 setupCurrencyAffixes(*patternUsed
, TRUE
, TRUE
, status
);
480 applyPatternWithoutExpandAffix(*patternUsed
,FALSE
, parseErr
, status
);
483 if (fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
484 expandAffixAdjustWidth(NULL
);
487 // If it was a currency format, apply the appropriate rounding by
488 // resetting the currency. NOTE: this copies fCurrency on top of itself.
489 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
490 setCurrencyInternally(getCurrency(), status
);
496 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode
& status
) {
497 if (U_FAILURE(status
)) {
500 UParseError parseErr
;
501 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
502 if (U_FAILURE(status
)) {
506 NumberingSystem
*ns
= NumberingSystem::createInstance(fSymbols
->getLocale(),status
);
507 if (U_FAILURE(status
)) {
511 // Save the default currency patterns of this locale.
512 // Here, chose onlyApplyPatternWithoutExpandAffix without
513 // expanding the affix patterns into affixes.
514 UnicodeString currencyPattern
;
515 UErrorCode error
= U_ZERO_ERROR
;
517 UResourceBundle
*resource
= ures_open(NULL
, fSymbols
->getLocale().getName(), &error
);
518 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, fgNumberElements
, NULL
, &error
);
519 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &error
);
520 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
522 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
523 if ( error
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(ns
->getName(),fgLatn
)) {
524 error
= U_ZERO_ERROR
;
525 resource
= ures_getByKeyWithFallback(numElements
, fgLatn
, resource
, &error
);
526 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
527 patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
529 ures_close(numElements
);
530 ures_close(resource
);
533 if (U_SUCCESS(error
)) {
534 applyPatternWithoutExpandAffix(UnicodeString(patResStr
, patLen
), false,
536 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
542 fAffixPatternsForCurrency
->put(UNICODE_STRING("default", 7), affixPtn
, status
);
545 // save the unique currency plural patterns of this locale.
546 Hashtable
* pluralPtn
= fCurrencyPluralInfo
->fPluralCountToCurrencyUnitPattern
;
547 const UHashElement
* element
= NULL
;
549 Hashtable pluralPatternSet
;
550 while ((element
= pluralPtn
->nextElement(pos
)) != NULL
) {
551 const UHashTok valueTok
= element
->value
;
552 const UnicodeString
* value
= (UnicodeString
*)valueTok
.pointer
;
553 const UHashTok keyTok
= element
->key
;
554 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
555 if (pluralPatternSet
.geti(*value
) != 1) {
556 pluralPatternSet
.puti(*value
, 1, status
);
557 applyPatternWithoutExpandAffix(*value
, false, parseErr
, status
);
558 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
564 fAffixPatternsForCurrency
->put(*key
, affixPtn
, status
);
571 DecimalFormat::setupCurrencyAffixes(const UnicodeString
& pattern
,
572 UBool setupForCurrentPattern
,
573 UBool setupForPluralPattern
,
574 UErrorCode
& status
) {
575 if (U_FAILURE(status
)) {
578 UParseError parseErr
;
579 if (setupForCurrentPattern
) {
580 if (fAffixesForCurrency
) {
581 deleteHashForAffix(fAffixesForCurrency
);
583 fAffixesForCurrency
= initHashForAffix(status
);
584 if (U_SUCCESS(status
)) {
585 applyPatternWithoutExpandAffix(pattern
, false, parseErr
, status
);
586 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
587 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
588 if (U_SUCCESS(status
)) {
589 const UnicodeString
* pluralCount
;
590 while ((pluralCount
= keywords
->snext(status
)) != NULL
) {
591 if ( U_SUCCESS(status
) ) {
592 expandAffixAdjustWidth(pluralCount
);
593 AffixesForCurrency
* affix
= new AffixesForCurrency(
594 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
595 fAffixesForCurrency
->put(*pluralCount
, affix
, status
);
603 if (U_FAILURE(status
)) {
607 if (setupForPluralPattern
) {
608 if (fPluralAffixesForCurrency
) {
609 deleteHashForAffix(fPluralAffixesForCurrency
);
611 fPluralAffixesForCurrency
= initHashForAffix(status
);
612 if (U_SUCCESS(status
)) {
613 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
614 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
615 if (U_SUCCESS(status
)) {
616 const UnicodeString
* pluralCount
;
617 while ((pluralCount
= keywords
->snext(status
)) != NULL
) {
618 if ( U_SUCCESS(status
) ) {
620 fCurrencyPluralInfo
->getCurrencyPluralPattern(*pluralCount
, ptn
);
621 applyPatternInternally(*pluralCount
, ptn
, false, parseErr
, status
);
622 AffixesForCurrency
* affix
= new AffixesForCurrency(
623 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
624 fPluralAffixesForCurrency
->put(*pluralCount
, affix
, status
);
634 //------------------------------------------------------------------------------
636 DecimalFormat::~DecimalFormat()
638 delete fPosPrefixPattern
;
639 delete fPosSuffixPattern
;
640 delete fNegPrefixPattern
;
641 delete fNegSuffixPattern
;
642 delete fCurrencyChoice
;
645 delete fRoundingIncrement
;
646 deleteHashForAffixPattern();
647 deleteHashForAffix(fAffixesForCurrency
);
648 deleteHashForAffix(fPluralAffixesForCurrency
);
649 delete fCurrencyPluralInfo
;
652 //------------------------------------------------------------------------------
655 DecimalFormat::DecimalFormat(const DecimalFormat
&source
) :
656 NumberFormat(source
) {
661 //------------------------------------------------------------------------------
662 // assignment operator
664 static void _copy_us_ptr(UnicodeString
** pdest
, const UnicodeString
* source
) {
665 if (source
== NULL
) {
668 } else if (*pdest
== NULL
) {
669 *pdest
= new UnicodeString(*source
);
676 DecimalFormat::operator=(const DecimalFormat
& rhs
)
679 NumberFormat::operator=(rhs
);
680 fPositivePrefix
= rhs
.fPositivePrefix
;
681 fPositiveSuffix
= rhs
.fPositiveSuffix
;
682 fNegativePrefix
= rhs
.fNegativePrefix
;
683 fNegativeSuffix
= rhs
.fNegativeSuffix
;
684 _copy_us_ptr(&fPosPrefixPattern
, rhs
.fPosPrefixPattern
);
685 _copy_us_ptr(&fPosSuffixPattern
, rhs
.fPosSuffixPattern
);
686 _copy_us_ptr(&fNegPrefixPattern
, rhs
.fNegPrefixPattern
);
687 _copy_us_ptr(&fNegSuffixPattern
, rhs
.fNegSuffixPattern
);
688 if (rhs
.fCurrencyChoice
== 0) {
689 delete fCurrencyChoice
;
692 fCurrencyChoice
= (ChoiceFormat
*) rhs
.fCurrencyChoice
->clone();
694 setRoundingIncrement(rhs
.getRoundingIncrement());
695 fRoundingMode
= rhs
.fRoundingMode
;
696 setMultiplier(rhs
.getMultiplier());
697 fGroupingSize
= rhs
.fGroupingSize
;
698 fGroupingSize2
= rhs
.fGroupingSize2
;
699 fDecimalSeparatorAlwaysShown
= rhs
.fDecimalSeparatorAlwaysShown
;
700 if(fSymbols
== NULL
) {
701 fSymbols
= new DecimalFormatSymbols(*rhs
.fSymbols
);
703 *fSymbols
= *rhs
.fSymbols
;
705 fUseExponentialNotation
= rhs
.fUseExponentialNotation
;
706 fExponentSignAlwaysShown
= rhs
.fExponentSignAlwaysShown
;
707 /*Bertrand A. D. Update 98.03.17*/
708 fCurrencySignCount
= rhs
.fCurrencySignCount
;
710 fMinExponentDigits
= rhs
.fMinExponentDigits
;
713 fFormatWidth
= rhs
.fFormatWidth
;
715 fPadPosition
= rhs
.fPadPosition
;
717 fMinSignificantDigits
= rhs
.fMinSignificantDigits
;
718 fMaxSignificantDigits
= rhs
.fMaxSignificantDigits
;
719 fUseSignificantDigits
= rhs
.fUseSignificantDigits
;
720 fFormatPattern
= rhs
.fFormatPattern
;
722 fCurrencySignCount
= rhs
.fCurrencySignCount
;
723 if (rhs
.fCurrencyPluralInfo
) {
724 delete fCurrencyPluralInfo
;
725 fCurrencyPluralInfo
= rhs
.fCurrencyPluralInfo
->clone();
727 if (rhs
.fAffixPatternsForCurrency
) {
728 UErrorCode status
= U_ZERO_ERROR
;
729 deleteHashForAffixPattern();
730 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
731 copyHashForAffixPattern(rhs
.fAffixPatternsForCurrency
,
732 fAffixPatternsForCurrency
, status
);
734 if (rhs
.fAffixesForCurrency
) {
735 UErrorCode status
= U_ZERO_ERROR
;
736 deleteHashForAffix(fAffixesForCurrency
);
737 fAffixesForCurrency
= initHashForAffixPattern(status
);
738 copyHashForAffix(rhs
.fAffixesForCurrency
, fAffixesForCurrency
, status
);
740 if (rhs
.fPluralAffixesForCurrency
) {
741 UErrorCode status
= U_ZERO_ERROR
;
742 deleteHashForAffix(fPluralAffixesForCurrency
);
743 fPluralAffixesForCurrency
= initHashForAffixPattern(status
);
744 copyHashForAffix(rhs
.fPluralAffixesForCurrency
, fPluralAffixesForCurrency
, status
);
750 //------------------------------------------------------------------------------
753 DecimalFormat::operator==(const Format
& that
) const
758 // NumberFormat::operator== guarantees this cast is safe
759 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
762 // This code makes it easy to determine why two format objects that should
765 if (!NumberFormat::operator==(that
)) {
766 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
767 debug("NumberFormat::!=");
769 if (!((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
770 fPositivePrefix
== other
->fPositivePrefix
)
771 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
772 *fPosPrefixPattern
== *other
->fPosPrefixPattern
))) {
773 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
774 debug("Pos Prefix !=");
776 if (!((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
777 fPositiveSuffix
== other
->fPositiveSuffix
)
778 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
779 *fPosSuffixPattern
== *other
->fPosSuffixPattern
))) {
780 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
781 debug("Pos Suffix !=");
783 if (!((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
784 fNegativePrefix
== other
->fNegativePrefix
)
785 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
786 *fNegPrefixPattern
== *other
->fNegPrefixPattern
))) {
787 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
788 debug("Neg Prefix ");
789 if (fNegPrefixPattern
== NULL
) {
791 debugout(fNegativePrefix
);
794 debugout(*fNegPrefixPattern
);
797 if (other
->fNegPrefixPattern
== NULL
) {
799 debugout(other
->fNegativePrefix
);
802 debugout(*other
->fNegPrefixPattern
);
805 if (!((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
806 fNegativeSuffix
== other
->fNegativeSuffix
)
807 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
808 *fNegSuffixPattern
== *other
->fNegSuffixPattern
))) {
809 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
810 debug("Neg Suffix ");
811 if (fNegSuffixPattern
== NULL
) {
813 debugout(fNegativeSuffix
);
816 debugout(*fNegSuffixPattern
);
819 if (other
->fNegSuffixPattern
== NULL
) {
821 debugout(other
->fNegativeSuffix
);
824 debugout(*other
->fNegSuffixPattern
);
827 if (!((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
828 || (fRoundingIncrement
!= NULL
&&
829 other
->fRoundingIncrement
!= NULL
&&
830 *fRoundingIncrement
== *other
->fRoundingIncrement
))) {
831 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
832 debug("Rounding Increment !=");
834 if (getMultiplier() != other
->getMultiplier()) {
835 if (first
) { printf("[ "); first
= FALSE
; }
836 printf("Multiplier %ld != %ld", getMultiplier(), other
->getMultiplier());
838 if (fGroupingSize
!= other
->fGroupingSize
) {
839 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
840 printf("Grouping Size %ld != %ld", fGroupingSize
, other
->fGroupingSize
);
842 if (fGroupingSize2
!= other
->fGroupingSize2
) {
843 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
844 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2
, other
->fGroupingSize2
);
846 if (fDecimalSeparatorAlwaysShown
!= other
->fDecimalSeparatorAlwaysShown
) {
847 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
848 printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown
, other
->fDecimalSeparatorAlwaysShown
);
850 if (fUseExponentialNotation
!= other
->fUseExponentialNotation
) {
851 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
854 if (!(!fUseExponentialNotation
||
855 fMinExponentDigits
!= other
->fMinExponentDigits
)) {
856 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
857 debug("Exp Digits !=");
859 if (*fSymbols
!= *(other
->fSymbols
)) {
860 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
863 // TODO Add debug stuff for significant digits here
864 if (fUseSignificantDigits
!= other
->fUseSignificantDigits
) {
865 debug("fUseSignificantDigits !=");
867 if (fUseSignificantDigits
&&
868 fMinSignificantDigits
!= other
->fMinSignificantDigits
) {
869 debug("fMinSignificantDigits !=");
871 if (fUseSignificantDigits
&&
872 fMaxSignificantDigits
!= other
->fMaxSignificantDigits
) {
873 debug("fMaxSignificantDigits !=");
876 if (!first
) { printf(" ]"); }
877 if (fCurrencySignCount
!= other
->fCurrencySignCount
) {
878 debug("fCurrencySignCount !=");
880 if (fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
) {
881 debug("fCurrencyPluralInfo == ");
882 if (fCurrencyPluralInfo
== NULL
) {
883 debug("fCurrencyPluralInfo == NULL");
886 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
887 *fCurrencyPluralInfo
!= *(other
->fCurrencyPluralInfo
)) {
888 debug("fCurrencyPluralInfo !=");
890 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
== NULL
||
891 fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
!= NULL
) {
892 debug("fCurrencyPluralInfo one NULL, the other not");
894 if (fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
== NULL
) {
895 debug("fCurrencyPluralInfo == ");
900 return (NumberFormat::operator==(that
) &&
901 ((fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) ?
902 (fAffixPatternsForCurrency
->equals(*other
->fAffixPatternsForCurrency
)) :
903 (((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
904 fPositivePrefix
== other
->fPositivePrefix
)
905 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
906 *fPosPrefixPattern
== *other
->fPosPrefixPattern
)) &&
907 ((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
908 fPositiveSuffix
== other
->fPositiveSuffix
)
909 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
910 *fPosSuffixPattern
== *other
->fPosSuffixPattern
)) &&
911 ((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
912 fNegativePrefix
== other
->fNegativePrefix
)
913 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
914 *fNegPrefixPattern
== *other
->fNegPrefixPattern
)) &&
915 ((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
916 fNegativeSuffix
== other
->fNegativeSuffix
)
917 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
918 *fNegSuffixPattern
== *other
->fNegSuffixPattern
)))) &&
919 ((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
920 || (fRoundingIncrement
!= NULL
&&
921 other
->fRoundingIncrement
!= NULL
&&
922 *fRoundingIncrement
== *other
->fRoundingIncrement
)) &&
923 getMultiplier() == other
->getMultiplier() &&
924 fGroupingSize
== other
->fGroupingSize
&&
925 fGroupingSize2
== other
->fGroupingSize2
&&
926 fDecimalSeparatorAlwaysShown
== other
->fDecimalSeparatorAlwaysShown
&&
927 fUseExponentialNotation
== other
->fUseExponentialNotation
&&
928 (!fUseExponentialNotation
||
929 fMinExponentDigits
== other
->fMinExponentDigits
) &&
930 *fSymbols
== *(other
->fSymbols
) &&
931 fUseSignificantDigits
== other
->fUseSignificantDigits
&&
932 (!fUseSignificantDigits
||
933 (fMinSignificantDigits
== other
->fMinSignificantDigits
&&
934 fMaxSignificantDigits
== other
->fMaxSignificantDigits
)) &&
935 fCurrencySignCount
== other
->fCurrencySignCount
&&
936 ((fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
&&
937 fCurrencyPluralInfo
== NULL
) ||
938 (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
939 *fCurrencyPluralInfo
== *(other
->fCurrencyPluralInfo
))));
942 //------------------------------------------------------------------------------
945 DecimalFormat::clone() const
947 return new DecimalFormat(*this);
950 //------------------------------------------------------------------------------
953 DecimalFormat::format(int32_t number
,
954 UnicodeString
& appendTo
,
955 FieldPosition
& fieldPosition
) const
957 return format((int64_t)number
, appendTo
, fieldPosition
);
961 DecimalFormat::format(int32_t number
,
962 UnicodeString
& appendTo
,
963 FieldPositionIterator
* posIter
,
964 UErrorCode
& status
) const
966 return format((int64_t)number
, appendTo
, posIter
, status
);
969 //------------------------------------------------------------------------------
972 DecimalFormat::format(int64_t number
,
973 UnicodeString
& appendTo
,
974 FieldPosition
& fieldPosition
) const
976 FieldPositionOnlyHandler
handler(fieldPosition
);
977 return _format(number
, appendTo
, handler
);
981 DecimalFormat::format(int64_t number
,
982 UnicodeString
& appendTo
,
983 FieldPositionIterator
* posIter
,
984 UErrorCode
& status
) const
986 FieldPositionIteratorHandler
handler(posIter
, status
);
987 return _format(number
, appendTo
, handler
);
991 DecimalFormat::_format(int64_t number
,
992 UnicodeString
& appendTo
,
993 FieldPositionHandler
& handler
) const
995 UErrorCode status
= U_ZERO_ERROR
;
998 return _format(digits
, appendTo
, handler
, status
);
1001 //------------------------------------------------------------------------------
1004 DecimalFormat::format( double number
,
1005 UnicodeString
& appendTo
,
1006 FieldPosition
& fieldPosition
) const
1008 FieldPositionOnlyHandler
handler(fieldPosition
);
1009 return _format(number
, appendTo
, handler
);
1013 DecimalFormat::format( double number
,
1014 UnicodeString
& appendTo
,
1015 FieldPositionIterator
* posIter
,
1016 UErrorCode
& status
) const
1018 FieldPositionIteratorHandler
handler(posIter
, status
);
1019 return _format(number
, appendTo
, handler
);
1023 DecimalFormat::_format( double number
,
1024 UnicodeString
& appendTo
,
1025 FieldPositionHandler
& handler
) const
1027 // Special case for NaN, sets the begin and end index to be the
1028 // the string length of localized name of NaN.
1029 // TODO: let NaNs go through DigitList.
1030 if (uprv_isNaN(number
))
1032 int begin
= appendTo
.length();
1033 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1035 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1037 addPadding(appendTo
, handler
, 0, 0);
1041 UErrorCode status
= U_ZERO_ERROR
;
1044 _format(digits
, appendTo
, handler
, status
);
1045 // No way to return status from here.
1049 //------------------------------------------------------------------------------
1053 DecimalFormat::format(const StringPiece
&number
,
1054 UnicodeString
&toAppendTo
,
1055 FieldPositionIterator
*posIter
,
1056 UErrorCode
&status
) const
1059 dnum
.set(number
, status
);
1060 if (U_FAILURE(status
)) {
1063 FieldPositionIteratorHandler
handler(posIter
, status
);
1064 _format(dnum
, toAppendTo
, handler
, status
);
1070 DecimalFormat::format(const DigitList
&number
,
1071 UnicodeString
&appendTo
,
1072 FieldPositionIterator
*posIter
,
1073 UErrorCode
&status
) const {
1074 FieldPositionIteratorHandler
handler(posIter
, status
);
1075 _format(number
, appendTo
, handler
, status
);
1082 DecimalFormat::format(const DigitList
&number
,
1083 UnicodeString
& appendTo
,
1085 UErrorCode
&status
) const {
1086 FieldPositionOnlyHandler
handler(pos
);
1087 _format(number
, appendTo
, handler
, status
);
1094 DecimalFormat::_format(const DigitList
&number
,
1095 UnicodeString
& appendTo
,
1096 FieldPositionHandler
& handler
,
1097 UErrorCode
&status
) const
1099 // Special case for NaN, sets the begin and end index to be the
1100 // the string length of localized name of NaN.
1103 int begin
= appendTo
.length();
1104 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1106 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1108 addPadding(appendTo
, handler
, 0, 0);
1112 // Do this BEFORE checking to see if value is infinite or negative! Sets the
1113 // begin and end index to be length of the string composed of
1114 // localized name of Infinite and the positive/negative localized
1117 DigitList
adjustedNum(number
); // Copy, so we do not alter the original.
1118 adjustedNum
.setRoundingMode(fRoundingMode
);
1119 if (fMultiplier
!= NULL
) {
1120 adjustedNum
.mult(*fMultiplier
, status
);
1124 * Note: sign is important for zero as well as non-zero numbers.
1125 * Proper detection of -0.0 is needed to deal with the
1126 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
1128 UBool isNegative
= !adjustedNum
.isPositive();
1130 // Apply rounding after multiplier
1132 adjustedNum
.fContext
.status
&= ~DEC_Inexact
;
1133 if (fRoundingIncrement
!= NULL
) {
1134 adjustedNum
.div(*fRoundingIncrement
, status
);
1135 adjustedNum
.toIntegralValue();
1136 adjustedNum
.mult(*fRoundingIncrement
, status
);
1139 if (fRoundingMode
== kRoundUnnecessary
&& (adjustedNum
.fContext
.status
& DEC_Inexact
)) {
1140 status
= U_FORMAT_INEXACT_ERROR
;
1145 // Special case for INFINITE,
1146 if (adjustedNum
.isInfinite()) {
1147 int32_t prefixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, TRUE
);
1149 int begin
= appendTo
.length();
1150 appendTo
+= getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1152 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1154 int32_t suffixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, FALSE
);
1156 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1160 if (fUseExponentialNotation
|| areSignificantDigitsUsed()) {
1161 int32_t sigDigits
= precision();
1162 if (sigDigits
> 0) {
1163 adjustedNum
.round(sigDigits
);
1166 // Fixed point format. Round to a set number of fraction digits.
1167 int32_t numFractionDigits
= precision();
1168 adjustedNum
.roundFixedPoint(numFractionDigits
);
1170 if (fRoundingMode
== kRoundUnnecessary
&& (adjustedNum
.fContext
.status
& DEC_Inexact
)) {
1171 status
= U_FORMAT_INEXACT_ERROR
;
1175 return subformat(appendTo
, handler
, adjustedNum
, FALSE
);
1180 DecimalFormat::format( const Formattable
& obj
,
1181 UnicodeString
& appendTo
,
1182 FieldPosition
& fieldPosition
,
1183 UErrorCode
& status
) const
1185 return NumberFormat::format(obj
, appendTo
, fieldPosition
, status
);
1189 * Return true if a grouping separator belongs at the given
1190 * position, based on whether grouping is in use and the values of
1191 * the primary and secondary grouping interval.
1192 * @param pos the number of integer digits to the right of
1193 * the current position. Zero indicates the position after the
1194 * rightmost integer digit.
1195 * @return true if a grouping character belongs at the current
1198 UBool
DecimalFormat::isGroupingPosition(int32_t pos
) const {
1199 UBool result
= FALSE
;
1200 if (isGroupingUsed() && (pos
> 0) && (fGroupingSize
> 0)) {
1201 if ((fGroupingSize2
> 0) && (pos
> fGroupingSize
)) {
1202 result
= ((pos
- fGroupingSize
) % fGroupingSize2
) == 0;
1204 result
= pos
% fGroupingSize
== 0;
1210 //------------------------------------------------------------------------------
1213 * Complete the formatting of a finite number. On entry, the DigitList must
1214 * be filled in with the correct digits.
1217 DecimalFormat::subformat(UnicodeString
& appendTo
,
1218 FieldPositionHandler
& handler
,
1220 UBool isInteger
) const
1223 // DigitList returns digits as '0' thru '9', so we will need to
1224 // always need to subtract the character 0 to get the numeric value to use for indexing.
1226 UChar32 localizedDigits
[10];
1227 localizedDigits
[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1228 localizedDigits
[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol
).char32At(0);
1229 localizedDigits
[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol
).char32At(0);
1230 localizedDigits
[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol
).char32At(0);
1231 localizedDigits
[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol
).char32At(0);
1232 localizedDigits
[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol
).char32At(0);
1233 localizedDigits
[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol
).char32At(0);
1234 localizedDigits
[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol
).char32At(0);
1235 localizedDigits
[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol
).char32At(0);
1236 localizedDigits
[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol
).char32At(0);
1238 const UnicodeString
*grouping
;
1239 if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1240 grouping
= &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
1242 grouping
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1244 const UnicodeString
*decimal
;
1245 if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1246 decimal
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1248 decimal
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1250 UBool useSigDig
= areSignificantDigitsUsed();
1251 int32_t maxIntDig
= getMaximumIntegerDigits();
1252 int32_t minIntDig
= getMinimumIntegerDigits();
1254 // Appends the prefix.
1255 double doubleValue
= digits
.getDouble();
1256 int32_t prefixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), TRUE
);
1258 if (fUseExponentialNotation
)
1260 int currentLength
= appendTo
.length();
1261 int intBegin
= currentLength
;
1265 int32_t minFracDig
= 0;
1267 maxIntDig
= minIntDig
= 1;
1268 minFracDig
= getMinimumSignificantDigits() - 1;
1270 minFracDig
= getMinimumFractionDigits();
1271 if (maxIntDig
> kMaxScientificIntegerDigits
) {
1273 if (maxIntDig
< minIntDig
) {
1274 maxIntDig
= minIntDig
;
1277 if (maxIntDig
> minIntDig
) {
1282 // Minimum integer digits are handled in exponential format by
1283 // adjusting the exponent. For example, 0.01234 with 3 minimum
1284 // integer digits is "123.4E-4".
1286 // Maximum integer digits are interpreted as indicating the
1287 // repeating range. This is useful for engineering notation, in
1288 // which the exponent is restricted to a multiple of 3. For
1289 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1290 // If maximum integer digits are defined and are larger than
1291 // minimum integer digits, then minimum integer digits are
1293 digits
.reduce(); // Removes trailing zero digits.
1294 int32_t exponent
= digits
.getDecimalAt();
1295 if (maxIntDig
> 1 && maxIntDig
!= minIntDig
) {
1296 // A exponent increment is defined; adjust to it.
1297 exponent
= (exponent
> 0) ? (exponent
- 1) / maxIntDig
1298 : (exponent
/ maxIntDig
) - 1;
1299 exponent
*= maxIntDig
;
1301 // No exponent increment is defined; use minimum integer digits.
1302 // If none is specified, as in "#E0", generate 1 integer digit.
1303 exponent
-= (minIntDig
> 0 || minFracDig
> 0)
1307 // We now output a minimum number of digits, and more if there
1308 // are more digits, up to the maximum number of digits. We
1309 // place the decimal point after the "integer" digits, which
1310 // are the first (decimalAt - exponent) digits.
1311 int32_t minimumDigits
= minIntDig
+ minFracDig
;
1312 // The number of integer digits is handled specially if the number
1313 // is zero, since then there may be no digits.
1314 int32_t integerDigits
= digits
.isZero() ? minIntDig
:
1315 digits
.getDecimalAt() - exponent
;
1316 int32_t totalDigits
= digits
.getCount();
1317 if (minimumDigits
> totalDigits
)
1318 totalDigits
= minimumDigits
;
1319 if (integerDigits
> totalDigits
)
1320 totalDigits
= integerDigits
;
1322 // totalDigits records total number of digits needs to be processed
1324 for (i
=0; i
<totalDigits
; ++i
)
1326 if (i
== integerDigits
)
1328 intEnd
= appendTo
.length();
1329 handler
.addAttribute(kIntegerField
, intBegin
, intEnd
);
1331 appendTo
+= *decimal
;
1333 fracBegin
= appendTo
.length();
1334 handler
.addAttribute(kDecimalSeparatorField
, fracBegin
- 1, fracBegin
);
1336 // Restores the digit character or pads the buffer with zeros.
1337 UChar32 c
= (UChar32
)((i
< digits
.getCount()) ?
1338 localizedDigits
[digits
.getDigitValue(i
)] :
1339 localizedDigits
[0]);
1343 currentLength
= appendTo
.length();
1346 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1348 if (fracBegin
> 0) {
1349 handler
.addAttribute(kFractionField
, fracBegin
, currentLength
);
1352 // The exponent is output using the pattern-specified minimum
1353 // exponent digits. There is no maximum limit to the exponent
1354 // digits, since truncating the exponent would appendTo in an
1355 // unacceptable inaccuracy.
1356 appendTo
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1358 handler
.addAttribute(kExponentSymbolField
, currentLength
, appendTo
.length());
1359 currentLength
= appendTo
.length();
1361 // For zero values, we force the exponent to zero. We
1362 // must do this here, and not earlier, because the value
1363 // is used to determine integer digit count above.
1364 if (digits
.isZero())
1368 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1369 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1370 } else if (fExponentSignAlwaysShown
) {
1371 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1372 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1375 currentLength
= appendTo
.length();
1377 DigitList expDigits
;
1378 expDigits
.set(exponent
);
1380 int expDig
= fMinExponentDigits
;
1381 if (fUseExponentialNotation
&& expDig
< 1) {
1384 for (i
=expDigits
.getDecimalAt(); i
<expDig
; ++i
)
1385 appendTo
+= (localizedDigits
[0]);
1387 for (i
=0; i
<expDigits
.getDecimalAt(); ++i
)
1389 UChar32 c
= (UChar32
)((i
< expDigits
.getCount()) ?
1390 localizedDigits
[expDigits
.getDigitValue(i
)] :
1391 localizedDigits
[0]);
1395 handler
.addAttribute(kExponentField
, currentLength
, appendTo
.length());
1397 else // Not using exponential notation
1399 int currentLength
= appendTo
.length();
1400 int intBegin
= currentLength
;
1402 int32_t sigCount
= 0;
1403 int32_t minSigDig
= getMinimumSignificantDigits();
1404 int32_t maxSigDig
= getMaximumSignificantDigits();
1407 maxSigDig
= INT32_MAX
;
1410 // Output the integer portion. Here 'count' is the total
1411 // number of integer digits we will display, including both
1412 // leading zeros required to satisfy getMinimumIntegerDigits,
1413 // and actual digits present in the number.
1414 int32_t count
= useSigDig
?
1415 _max(1, digits
.getDecimalAt()) : minIntDig
;
1416 if (digits
.getDecimalAt() > 0 && count
< digits
.getDecimalAt()) {
1417 count
= digits
.getDecimalAt();
1420 // Handle the case where getMaximumIntegerDigits() is smaller
1421 // than the real number of integer digits. If this is so, we
1422 // output the least significant max integer digits. For example,
1423 // the value 1997 printed with 2 max integer digits is just "97".
1425 int32_t digitIndex
= 0; // Index into digitList.fDigits[]
1426 if (count
> maxIntDig
&& maxIntDig
>= 0) {
1428 digitIndex
= digits
.getDecimalAt() - count
;
1431 int32_t sizeBeforeIntegerPart
= appendTo
.length();
1434 for (i
=count
-1; i
>=0; --i
)
1436 if (i
< digits
.getDecimalAt() && digitIndex
< digits
.getCount() &&
1437 sigCount
< maxSigDig
) {
1438 // Output a real digit
1439 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
1444 // Output a zero (leading or trailing)
1445 appendTo
+= localizedDigits
[0];
1451 // Output grouping separator if necessary.
1452 if (isGroupingPosition(i
)) {
1453 currentLength
= appendTo
.length();
1454 appendTo
.append(*grouping
);
1455 handler
.addAttribute(kGroupingSeparatorField
, currentLength
, appendTo
.length());
1459 // TODO(dlf): this looks like it was a bug, we marked the int field as ending
1460 // before the zero was generated.
1461 // Record field information for caller.
1462 // if (fieldPosition.getField() == NumberFormat::kIntegerField)
1463 // fieldPosition.setEndIndex(appendTo.length());
1465 // Determine whether or not there are any printable fractional
1466 // digits. If we've used up the digits we know there aren't.
1467 UBool fractionPresent
= (!isInteger
&& digitIndex
< digits
.getCount()) ||
1468 (useSigDig
? (sigCount
< minSigDig
) : (getMinimumFractionDigits() > 0));
1470 // If there is no fraction present, and we haven't printed any
1471 // integer digits, then print a zero. Otherwise we won't print
1472 // _any_ digits, and we won't be able to parse this string.
1473 if (!fractionPresent
&& appendTo
.length() == sizeBeforeIntegerPart
)
1474 appendTo
+= localizedDigits
[0];
1476 currentLength
= appendTo
.length();
1477 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1479 // Output the decimal separator if we always do so.
1480 if (fDecimalSeparatorAlwaysShown
|| fractionPresent
) {
1481 appendTo
+= *decimal
;
1482 handler
.addAttribute(kDecimalSeparatorField
, currentLength
, appendTo
.length());
1483 currentLength
= appendTo
.length();
1486 int fracBegin
= currentLength
;
1488 count
= useSigDig
? INT32_MAX
: getMaximumFractionDigits();
1489 if (useSigDig
&& (sigCount
== maxSigDig
||
1490 (sigCount
>= minSigDig
&& digitIndex
== digits
.getCount()))) {
1494 for (i
=0; i
< count
; ++i
) {
1495 // Here is where we escape from the loop. We escape
1496 // if we've output the maximum fraction digits
1497 // (specified in the for expression above). We also
1498 // stop when we've output the minimum digits and
1499 // either: we have an integer, so there is no
1500 // fractional stuff to display, or we're out of
1501 // significant digits.
1502 if (!useSigDig
&& i
>= getMinimumFractionDigits() &&
1503 (isInteger
|| digitIndex
>= digits
.getCount())) {
1507 // Output leading fractional zeros. These are zeros
1508 // that come after the decimal but before any
1509 // significant digits. These are only output if
1510 // abs(number being formatted) < 1.0.
1511 if (-1-i
> (digits
.getDecimalAt()-1)) {
1512 appendTo
+= localizedDigits
[0];
1516 // Output a digit, if we have any precision left, or a
1517 // zero if we don't. We don't want to output noise digits.
1518 if (!isInteger
&& digitIndex
< digits
.getCount()) {
1519 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
1521 appendTo
+= localizedDigits
[0];
1524 // If we reach the maximum number of significant
1525 // digits, or if we output all the real digits and
1526 // reach the minimum, then we are done.
1529 (sigCount
== maxSigDig
||
1530 (digitIndex
== digits
.getCount() && sigCount
>= minSigDig
))) {
1535 handler
.addAttribute(kFractionField
, fracBegin
, appendTo
.length());
1538 int32_t suffixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), FALSE
);
1540 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1545 * Inserts the character fPad as needed to expand result to fFormatWidth.
1546 * @param result the string to be padded
1548 void DecimalFormat::addPadding(UnicodeString
& appendTo
,
1549 FieldPositionHandler
& handler
,
1551 int32_t suffixLen
) const
1553 if (fFormatWidth
> 0) {
1554 int32_t len
= fFormatWidth
- appendTo
.length();
1556 UnicodeString padding
;
1557 for (int32_t i
=0; i
<len
; ++i
) {
1560 switch (fPadPosition
) {
1561 case kPadAfterPrefix
:
1562 appendTo
.insert(prefixLen
, padding
);
1564 case kPadBeforePrefix
:
1565 appendTo
.insert(0, padding
);
1567 case kPadBeforeSuffix
:
1568 appendTo
.insert(appendTo
.length() - suffixLen
, padding
);
1570 case kPadAfterSuffix
:
1571 appendTo
+= padding
;
1574 if (fPadPosition
== kPadBeforePrefix
|| fPadPosition
== kPadAfterPrefix
) {
1575 handler
.shiftLast(len
);
1581 //------------------------------------------------------------------------------
1584 DecimalFormat::parse(const UnicodeString
& text
,
1585 Formattable
& result
,
1586 UErrorCode
& status
) const
1588 NumberFormat::parse(text
, result
, status
);
1592 DecimalFormat::parse(const UnicodeString
& text
,
1593 Formattable
& result
,
1594 ParsePosition
& parsePosition
) const {
1595 parse(text
, result
, parsePosition
, NULL
);
1598 CurrencyAmount
* DecimalFormat::parseCurrency(const UnicodeString
& text
,
1599 ParsePosition
& pos
) const {
1600 Formattable parseResult
;
1601 int32_t start
= pos
.getIndex();
1603 parse(text
, parseResult
, pos
, curbuf
);
1604 if (pos
.getIndex() != start
) {
1605 UErrorCode ec
= U_ZERO_ERROR
;
1606 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curbuf
, ec
));
1607 if (U_FAILURE(ec
)) {
1608 pos
.setIndex(start
); // indicate failure
1610 return currAmt
.orphan();
1617 * Parses the given text as a number, optionally providing a currency amount.
1618 * @param text the string to parse
1619 * @param result output parameter for the numeric result.
1620 * @param parsePosition input-output position; on input, the
1621 * position within text to match; must have 0 <= pos.getIndex() <
1622 * text.length(); on output, the position after the last matched
1623 * character. If the parse fails, the position in unchanged upon
1625 * @param currency if non-NULL, it should point to a 4-UChar buffer.
1626 * In this case the text is parsed as a currency format, and the
1627 * ISO 4217 code for the parsed currency is put into the buffer.
1628 * Otherwise the text is parsed as a non-currency format.
1630 void DecimalFormat::parse(const UnicodeString
& text
,
1631 Formattable
& result
,
1632 ParsePosition
& parsePosition
,
1633 UChar
* currency
) const {
1634 int32_t startIdx
, backup
;
1635 int32_t i
= startIdx
= backup
= parsePosition
.getIndex();
1637 // clear any old contents in the result. In particular, clears any DigitList
1638 // that it may be holding.
1641 // Handle NaN as a special case:
1643 // Skip padding characters, if around prefix
1644 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforePrefix
||
1645 fPadPosition
== kPadAfterPrefix
)) {
1646 i
= skipPadding(text
, i
);
1650 // skip any leading whitespace
1651 i
= backup
= skipUWhiteSpace(text
, i
);
1654 // If the text is composed of the representation of NaN, returns NaN.length
1655 const UnicodeString
*nan
= &getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1656 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
1657 ? 0 : nan
->length());
1660 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforeSuffix
||
1661 fPadPosition
== kPadAfterSuffix
)) {
1662 i
= skipPadding(text
, i
);
1664 parsePosition
.setIndex(i
);
1665 result
.setDouble(uprv_getNaN());
1669 // NaN parse failed; start over
1671 parsePosition
.setIndex(i
);
1673 // status is used to record whether a number is infinite.
1674 UBool status
[fgStatusLength
];
1675 DigitList
*digits
= new DigitList
;
1676 if (digits
== NULL
) {
1677 return; // no way to report error from here.
1680 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
1681 if (!parseForCurrency(text
, parsePosition
, *digits
,
1682 status
, currency
)) {
1688 fNegPrefixPattern
, fNegSuffixPattern
,
1689 fPosPrefixPattern
, fPosSuffixPattern
,
1690 FALSE
, UCURR_SYMBOL_NAME
,
1691 parsePosition
, *digits
, status
, currency
)) {
1692 parsePosition
.setIndex(startIdx
);
1699 if (status
[fgStatusInfinite
]) {
1700 double inf
= uprv_getInfinity();
1701 result
.setDouble(digits
->isPositive() ? inf
: -inf
);
1702 delete digits
; // TODO: set the dl to infinity, and let it fall into the code below.
1707 if (fMultiplier
!= NULL
) {
1708 UErrorCode ec
= U_ZERO_ERROR
;
1709 digits
->div(*fMultiplier
, ec
);
1712 // Negative zero special case:
1713 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1714 // if not parsing integerOnly, leave as -0, which a double can represent.
1715 if (digits
->isZero() && !digits
->isPositive() && isParseIntegerOnly()) {
1716 digits
->setPositive(TRUE
);
1718 result
.adoptDigitList(digits
);
1725 DecimalFormat::parseForCurrency(const UnicodeString
& text
,
1726 ParsePosition
& parsePosition
,
1729 UChar
* currency
) const {
1730 int origPos
= parsePosition
.getIndex();
1731 int maxPosIndex
= origPos
;
1732 int maxErrorPos
= -1;
1733 // First, parse against current pattern.
1734 // Since current pattern could be set by applyPattern(),
1735 // it could be an arbitrary pattern, and it may not be the one
1736 // defined in current locale.
1737 UBool tmpStatus
[fgStatusLength
];
1738 ParsePosition
tmpPos(origPos
);
1739 DigitList tmpDigitList
;
1741 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
1742 found
= subparse(text
,
1743 fNegPrefixPattern
, fNegSuffixPattern
,
1744 fPosPrefixPattern
, fPosSuffixPattern
,
1745 TRUE
, UCURR_LONG_NAME
,
1746 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1748 found
= subparse(text
,
1749 fNegPrefixPattern
, fNegSuffixPattern
,
1750 fPosPrefixPattern
, fPosSuffixPattern
,
1751 TRUE
, UCURR_SYMBOL_NAME
,
1752 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1755 if (tmpPos
.getIndex() > maxPosIndex
) {
1756 maxPosIndex
= tmpPos
.getIndex();
1757 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1758 status
[i
] = tmpStatus
[i
];
1760 digits
= tmpDigitList
;
1763 maxErrorPos
= tmpPos
.getErrorIndex();
1765 // Then, parse against affix patterns.
1766 // Those are currency patterns and currency plural patterns.
1768 const UHashElement
* element
= NULL
;
1769 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
1770 const UHashTok valueTok
= element
->value
;
1771 const AffixPatternsForCurrency
* affixPtn
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
1772 UBool tmpStatus
[fgStatusLength
];
1773 ParsePosition
tmpPos(origPos
);
1774 DigitList tmpDigitList
;
1775 UBool result
= subparse(text
,
1776 &affixPtn
->negPrefixPatternForCurrency
,
1777 &affixPtn
->negSuffixPatternForCurrency
,
1778 &affixPtn
->posPrefixPatternForCurrency
,
1779 &affixPtn
->posSuffixPatternForCurrency
,
1780 TRUE
, affixPtn
->patternType
,
1781 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1784 if (tmpPos
.getIndex() > maxPosIndex
) {
1785 maxPosIndex
= tmpPos
.getIndex();
1786 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1787 status
[i
] = tmpStatus
[i
];
1789 digits
= tmpDigitList
;
1792 maxErrorPos
= (tmpPos
.getErrorIndex() > maxErrorPos
) ?
1793 tmpPos
.getErrorIndex() : maxErrorPos
;
1796 // Finally, parse against simple affix to find the match.
1797 // For example, in TestMonster suite,
1798 // if the to-be-parsed text is "-\u00A40,00".
1799 // complexAffixCompare will not find match,
1800 // since there is no ISO code matches "\u00A4",
1801 // and the parse stops at "\u00A4".
1802 // We will just use simple affix comparison (look for exact match)
1804 UBool tmpStatus_2
[fgStatusLength
];
1805 ParsePosition
tmpPos_2(origPos
);
1806 DigitList tmpDigitList_2
;
1807 // set currencySignCount to 0 so that compareAffix function will
1808 // fall to compareSimpleAffix path, not compareComplexAffix path.
1809 // ?? TODO: is it right? need "false"?
1810 UBool result
= subparse(text
,
1811 &fNegativePrefix
, &fNegativeSuffix
,
1812 &fPositivePrefix
, &fPositiveSuffix
,
1813 FALSE
, UCURR_SYMBOL_NAME
,
1814 tmpPos_2
, tmpDigitList_2
, tmpStatus_2
,
1817 if (tmpPos_2
.getIndex() > maxPosIndex
) {
1818 maxPosIndex
= tmpPos_2
.getIndex();
1819 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1820 status
[i
] = tmpStatus_2
[i
];
1822 digits
= tmpDigitList_2
;
1826 maxErrorPos
= (tmpPos_2
.getErrorIndex() > maxErrorPos
) ?
1827 tmpPos_2
.getErrorIndex() : maxErrorPos
;
1831 //parsePosition.setIndex(origPos);
1832 parsePosition
.setErrorIndex(maxErrorPos
);
1834 parsePosition
.setIndex(maxPosIndex
);
1835 parsePosition
.setErrorIndex(-1);
1842 * Parse the given text into a number. The text is parsed beginning at
1843 * parsePosition, until an unparseable character is seen.
1844 * @param text the string to parse.
1845 * @param negPrefix negative prefix.
1846 * @param negSuffix negative suffix.
1847 * @param posPrefix positive prefix.
1848 * @param posSuffix positive suffix.
1849 * @param currencyParsing whether it is currency parsing or not.
1850 * @param type the currency type to parse against, LONG_NAME only or not.
1851 * @param parsePosition The position at which to being parsing. Upon
1852 * return, the first unparsed character.
1853 * @param digits the DigitList to set to the parsed value.
1854 * @param status output param containing boolean status flags indicating
1855 * whether the value was infinite and whether it was positive.
1856 * @param currency return value for parsed currency, for generic
1857 * currency parsing mode, or NULL for normal parsing. In generic
1858 * currency parsing mode, any currency is parsed, not just the
1859 * currency that this formatter is set to.
1861 UBool
DecimalFormat::subparse(const UnicodeString
& text
,
1862 const UnicodeString
* negPrefix
,
1863 const UnicodeString
* negSuffix
,
1864 const UnicodeString
* posPrefix
,
1865 const UnicodeString
* posSuffix
,
1866 UBool currencyParsing
,
1868 ParsePosition
& parsePosition
,
1869 DigitList
& digits
, UBool
* status
,
1870 UChar
* currency
) const
1872 // The parsing process builds up the number as char string, in the neutral format that
1873 // will be acceptable to the decNumber library, then at the end passes that string
1874 // off for conversion to a decNumber.
1875 UErrorCode err
= U_ZERO_ERROR
;
1876 CharString parsedNum
;
1879 int32_t position
= parsePosition
.getIndex();
1880 int32_t oldStart
= position
;
1881 UBool strictParse
= !isLenient();
1883 // Match padding before prefix
1884 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforePrefix
) {
1885 position
= skipPadding(text
, position
);
1888 // Match positive and negative prefixes; prefer longest match.
1889 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, posPrefix
, currencyParsing
, type
, currency
);
1890 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, negPrefix
, currencyParsing
, type
, currency
);
1891 if (posMatch
>= 0 && negMatch
>= 0) {
1892 if (posMatch
> negMatch
) {
1894 } else if (negMatch
> posMatch
) {
1898 if (posMatch
>= 0) {
1899 position
+= posMatch
;
1900 parsedNum
.append('+', err
);
1901 } else if (negMatch
>= 0) {
1902 position
+= negMatch
;
1903 parsedNum
.append('-', err
);
1904 } else if (strictParse
){
1905 parsePosition
.setErrorIndex(position
);
1908 // Temporary set positive. This might be changed after checking suffix
1909 parsedNum
.append('+', err
);
1912 // Match padding before prefix
1913 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterPrefix
) {
1914 position
= skipPadding(text
, position
);
1917 if (! strictParse
) {
1918 position
= skipUWhiteSpace(text
, position
);
1921 // process digits or Inf, find decimal position
1922 const UnicodeString
*inf
= &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1923 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
1924 ? 0 : inf
->length());
1925 position
+= infLen
; // infLen is non-zero when it does equal to infinity
1926 status
[fgStatusInfinite
] = infLen
!= 0;
1929 parsedNum
.append("Infinity", err
);
1931 // We now have a string of digits, possibly with grouping symbols,
1932 // and decimal points. We want to process these into a DigitList.
1933 // We don't want to put a bunch of leading zeros into the DigitList
1934 // though, so we keep track of the location of the decimal point,
1935 // put only significant digits into the DigitList, and adjust the
1936 // exponent as needed.
1938 UChar32 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1940 UBool strictFail
= FALSE
; // did we exit with a strict parse failure?
1941 int32_t lastGroup
= -1; // where did we last see a grouping separator?
1942 int32_t digitStart
= position
;
1943 int32_t gs2
= fGroupingSize2
== 0 ? fGroupingSize
: fGroupingSize2
;
1945 const UnicodeString
*decimalString
;
1946 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
1947 decimalString
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1949 decimalString
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1951 UChar32 decimalChar
= decimalString
->char32At(0);
1953 const UnicodeString
*groupingString
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1954 UChar32 groupingChar
= groupingString
->char32At(0);
1955 UBool sawDecimal
= FALSE
;
1956 UChar32 sawDecimalChar
= 0xFFFF;
1957 UBool sawGrouping
= FALSE
;
1958 UChar32 sawGroupingChar
= 0xFFFF;
1959 UBool sawDigit
= FALSE
;
1960 int32_t backup
= -1;
1962 int32_t textLength
= text
.length(); // One less pointer to follow
1963 int32_t decimalStringLength
= decimalString
->length();
1964 int32_t decimalCharLength
= U16_LENGTH(decimalChar
);
1965 int32_t groupingStringLength
= groupingString
->length();
1966 int32_t groupingCharLength
= U16_LENGTH(groupingChar
);
1968 // equivalent grouping and decimal support
1969 const UnicodeSet
*decimalSet
= NULL
;
1970 const UnicodeSet
*groupingSet
= NULL
;
1972 if (decimalCharLength
== decimalStringLength
) {
1973 decimalSet
= DecimalFormatStaticSets::getSimilarDecimals(decimalChar
, strictParse
);
1976 if (groupingCharLength
== groupingStringLength
) {
1978 groupingSet
= DecimalFormatStaticSets::gStaticSets
->fStrictDefaultGroupingSeparators
;
1980 groupingSet
= DecimalFormatStaticSets::gStaticSets
->fDefaultGroupingSeparators
;
1984 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
1985 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
1986 // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
1988 // We have to track digitCount ourselves, because digits.fCount will
1989 // pin when the maximum allowable digits is reached.
1990 int32_t digitCount
= 0;
1991 int32_t integerDigitCount
= 0;
1993 for (; position
< textLength
; )
1995 UChar32 ch
= text
.char32At(position
);
1997 /* We recognize all digit ranges, not only the Latin digit range
1998 * '0'..'9'. We do so by using the Character.digit() method,
1999 * which converts a valid Unicode digit to the range 0..9.
2001 * The character 'ch' may be a digit. If so, place its value
2002 * from 0 to 9 in 'digit'. First try using the locale digit,
2003 * which may or MAY NOT be a standard Unicode digit range. If
2004 * this fails, try using the standard Unicode digit ranges by
2005 * calling Character.digit(). If this also fails, digit will
2006 * have a value outside the range 0..9.
2009 if (digit
< 0 || digit
> 9)
2011 digit
= u_charDigitValue(ch
);
2014 // As a last resort, look through the localized digits if the zero digit
2015 // is not a "standard" Unicode digit.
2016 if ( (digit
< 0 || digit
> 9) && u_charDigitValue(zero
) != 0) {
2018 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is:
2019 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits.
2020 if ( zero
!=0x3007 || ch
!=0x96F6 ) {
2021 for (digit
= 1 ; digit
< 10 ; digit
++ ) {
2022 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)(DecimalFormatSymbols::kOneDigitSymbol
+digit
-1)).char32At(0) == ch
) {
2029 if (digit
>= 0 && digit
<= 9)
2031 if (strictParse
&& backup
!= -1) {
2032 // comma followed by digit, so group before comma is a
2033 // secondary group. If there was a group separator
2034 // before that, the group must == the secondary group
2035 // length, else it can be <= the the secondary group
2037 if ((lastGroup
!= -1 && backup
- lastGroup
- 1 != gs2
) ||
2038 (lastGroup
== -1 && position
- digitStart
- 1 > gs2
)) {
2046 // Cancel out backup setting (see grouping handler below)
2050 // Note: this will append leading zeros
2051 parsedNum
.append((char)(digit
+ '0'), err
);
2053 // count any digit that's not a leading zero
2054 if (digit
> 0 || digitCount
> 0 || sawDecimal
) {
2057 // count any integer digit that's not a leading zero
2059 integerDigitCount
+= 1;
2063 position
+= U16_LENGTH(ch
);
2065 else if (groupingStringLength
> 0 &&
2066 matchGrouping(groupingChar
, sawGrouping
, sawGroupingChar
, groupingSet
,
2067 decimalChar
, decimalSet
,
2068 ch
) && isGroupingUsed())
2075 if ( (!sawDigit
&& groupingSet
!=NULL
&& u_isWhitespace(ch
)) || backup
!= -1 ) {
2076 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for
2077 // backward compatibility) as long as it is not one of the breaking whitespace characters
2078 // that is only treated as a group separator because of the equivalence set. If we get
2079 // here it is because the leading sep was such a breaking space, or there were multiple
2080 // group separators in a row. Note that the DecimalFormat documentation says
2081 // "During parsing, grouping separators are ignored" and that was for strict parsing,
2082 // so we may need to further revisit this strictParse restriction to ensure compatibility.
2083 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F.
2084 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP).
2090 // Ignore grouping characters, if we are using them, but require
2091 // that they be followed by a digit. Otherwise we backup and
2094 position
+= groupingStringLength
;
2096 // Once we see a grouping character, we only accept that grouping character from then on.
2099 else if (matchDecimal(decimalChar
,sawDecimal
,sawDecimalChar
, decimalSet
, ch
))
2103 (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1)) {
2109 // If we're only parsing integers, or if we ALREADY saw the
2110 // decimal, then don't parse this one.
2111 if (isParseIntegerOnly() || sawDecimal
) {
2115 parsedNum
.append('.', err
);
2116 position
+= decimalStringLength
;
2118 // Once we see a decimal character, we only accept that decimal character from then on.
2120 // decimalSet is considered to consist of (ch,ch)
2123 const UnicodeString
*tmp
;
2124 tmp
= &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
2125 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
2127 // Parse sign, if present
2128 int32_t pos
= position
+ tmp
->length();
2129 char exponentSign
= '+';
2131 if (pos
< textLength
)
2133 tmp
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2134 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2136 pos
+= tmp
->length();
2139 tmp
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2140 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2143 pos
+= tmp
->length();
2148 UBool sawExponentDigit
= FALSE
;
2149 while (pos
< textLength
) {
2150 ch
= text
[(int32_t)pos
];
2153 if (digit
< 0 || digit
> 9) {
2154 digit
= u_charDigitValue(ch
);
2156 if (0 <= digit
&& digit
<= 9) {
2157 if (!sawExponentDigit
) {
2158 parsedNum
.append('E', err
);
2159 parsedNum
.append(exponentSign
, err
);
2160 sawExponentDigit
= TRUE
;
2163 parsedNum
.append((char)(digit
+ '0'), err
);
2169 if (sawExponentDigit
) {
2170 position
= pos
; // Advance past the exponent
2173 break; // Whether we fail or succeed, we exit this loop
2186 if (strictParse
&& !sawDecimal
) {
2187 if (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1) {
2193 // only set with strictParse and a grouping separator error
2195 parsePosition
.setIndex(oldStart
);
2196 parsePosition
.setErrorIndex(position
);
2200 // If there was no decimal point we have an integer
2202 // If none of the text string was recognized. For example, parse
2203 // "x" with pattern "#0.00" (return index and error index both 0)
2204 // parse "$" with pattern "$#0.00". (return index 0 and error index
2206 if (!sawDigit
&& digitCount
== 0) {
2207 parsePosition
.setIndex(oldStart
);
2208 parsePosition
.setErrorIndex(oldStart
);
2213 // Match padding before suffix
2214 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforeSuffix
) {
2215 position
= skipPadding(text
, position
);
2218 int32_t posSuffixMatch
= -1, negSuffixMatch
= -1;
2220 // Match positive and negative suffixes; prefer longest match.
2221 if (posMatch
>= 0 || (!strictParse
&& negMatch
< 0)) {
2222 posSuffixMatch
= compareAffix(text
, position
, FALSE
, FALSE
, posSuffix
, currencyParsing
, type
, currency
);
2224 if (negMatch
>= 0) {
2225 negSuffixMatch
= compareAffix(text
, position
, TRUE
, FALSE
, negSuffix
, currencyParsing
, type
, currency
);
2227 if (posSuffixMatch
>= 0 && negSuffixMatch
>= 0) {
2228 if (posSuffixMatch
> negSuffixMatch
) {
2229 negSuffixMatch
= -1;
2230 } else if (negSuffixMatch
> posSuffixMatch
) {
2231 posSuffixMatch
= -1;
2235 // Fail if neither or both
2236 if (strictParse
&& ((posSuffixMatch
>= 0) == (negSuffixMatch
>= 0))) {
2237 parsePosition
.setErrorIndex(position
);
2241 position
+= (posSuffixMatch
>= 0 ? posSuffixMatch
: (negSuffixMatch
>= 0 ? negSuffixMatch
: 0));
2243 // Match padding before suffix
2244 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterSuffix
) {
2245 position
= skipPadding(text
, position
);
2248 parsePosition
.setIndex(position
);
2250 parsedNum
.data()[0] = (posSuffixMatch
>= 0 || (!strictParse
&& negMatch
< 0 && negSuffixMatch
< 0)) ? '+' : '-';
2252 if(parsePosition
.getIndex() == oldStart
)
2254 parsePosition
.setErrorIndex(position
);
2257 digits
.set(parsedNum
.toStringPiece(), err
);
2259 if (U_FAILURE(err
)) {
2260 parsePosition
.setErrorIndex(position
);
2267 * Starting at position, advance past a run of pad characters, if any.
2268 * Return the index of the first character after position that is not a pad
2269 * character. Result is >= position.
2271 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
2272 int32_t padLen
= U16_LENGTH(fPad
);
2273 while (position
< text
.length() &&
2274 text
.char32At(position
) == fPad
) {
2281 * Return the length matched by the given affix, or -1 if none.
2282 * Runs of white space in the affix, match runs of white space in
2283 * the input. Pattern white space and input white space are
2284 * determined differently; see code.
2285 * @param text input text
2286 * @param pos offset into input at which to begin matching
2289 * @param affixPat affix pattern used for currency affix comparison.
2290 * @param currencyParsing whether it is currency parsing or not
2291 * @param type the currency type to parse against, LONG_NAME only or not.
2292 * @param currency return value for parsed currency, for generic
2293 * currency parsing mode, or null for normal parsing. In generic
2294 * currency parsing mode, any currency is parsed, not just the
2295 * currency that this formatter is set to.
2296 * @return length of input that matches, or -1 if match failure
2298 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
2302 const UnicodeString
* affixPat
,
2303 UBool currencyParsing
,
2305 UChar
* currency
) const
2307 const UnicodeString
*patternToCompare
;
2308 if (fCurrencyChoice
!= NULL
|| currency
!= NULL
||
2309 (fCurrencySignCount
> fgCurrencySignCountZero
&& currencyParsing
)) {
2311 if (affixPat
!= NULL
) {
2312 return compareComplexAffix(*affixPat
, text
, pos
, type
, currency
);
2318 patternToCompare
= &fNegativePrefix
;
2321 patternToCompare
= &fNegativeSuffix
;
2326 patternToCompare
= &fPositivePrefix
;
2329 patternToCompare
= &fPositiveSuffix
;
2332 return compareSimpleAffix(*patternToCompare
, text
, pos
, isLenient());
2336 * Return the length matched by the given affix, or -1 if none.
2337 * Runs of white space in the affix, match runs of white space in
2338 * the input. Pattern white space and input white space are
2339 * determined differently; see code.
2340 * @param affix pattern string, taken as a literal
2341 * @param input input text
2342 * @param pos offset into input at which to begin matching
2343 * @return length of input that matches, or -1 if match failure
2345 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
2346 const UnicodeString
& input
,
2349 UErrorCode status
= U_ZERO_ERROR
;
2350 int32_t start
= pos
;
2351 UChar32 affixChar
= affix
.char32At(0);
2352 int32_t affixLength
= affix
.length();
2353 int32_t inputLength
= input
.length();
2354 int32_t affixCharLength
= U16_LENGTH(affixChar
);
2355 UnicodeSet
*affixSet
;
2357 DecimalFormatStaticSets::initSets(&status
);
2360 affixSet
= DecimalFormatStaticSets::gStaticSets
->fStrictDashEquivalents
;
2362 // If the affix is exactly one character long and that character
2363 // is in the dash set and the very next input character is also
2364 // in the dash set, return a match.
2365 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2366 if (affixSet
->contains(input
.char32At(pos
))) {
2371 for (int32_t i
= 0; i
< affixLength
; ) {
2372 UChar32 c
= affix
.char32At(i
);
2373 int32_t len
= U16_LENGTH(c
);
2374 if (PatternProps::isWhiteSpace(c
)) {
2375 // We may have a pattern like: \u200F \u0020
2376 // and input text like: \u200F \u0020
2377 // Note that U+200F and U+0020 are Pattern_White_Space but only
2378 // U+0020 is UWhiteSpace. So we have to first do a direct
2379 // match of the run of Pattern_White_Space in the pattern,
2380 // then match any extra characters.
2381 UBool literalMatch
= FALSE
;
2382 while (pos
< inputLength
&&
2383 input
.char32At(pos
) == c
) {
2384 literalMatch
= TRUE
;
2387 if (i
== affixLength
) {
2390 c
= affix
.char32At(i
);
2391 len
= U16_LENGTH(c
);
2392 if (!PatternProps::isWhiteSpace(c
)) {
2397 // Advance over run in pattern
2398 i
= skipPatternWhiteSpace(affix
, i
);
2400 // Advance over run in input text
2401 // Must see at least one white space char in input,
2402 // unless we've already matched some characters literally.
2404 pos
= skipUWhiteSpace(input
, pos
);
2405 if (pos
== s
&& !literalMatch
) {
2409 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2410 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2411 // is also in the affix.
2412 i
= skipUWhiteSpace(affix
, i
);
2414 if (pos
< inputLength
&&
2415 input
.char32At(pos
) == c
) {
2424 UBool match
= FALSE
;
2426 affixSet
= DecimalFormatStaticSets::gStaticSets
->fDashEquivalents
;
2428 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2429 pos
= skipUWhiteSpace(input
, pos
);
2431 if (affixSet
->contains(input
.char32At(pos
))) {
2432 return pos
- start
+ 1;
2436 for (int32_t i
= 0; i
< affixLength
; )
2438 //i = skipRuleWhiteSpace(affix, i);
2439 i
= skipUWhiteSpace(affix
, i
);
2440 pos
= skipUWhiteSpace(input
, pos
);
2442 if (i
>= affixLength
|| pos
>= inputLength
) {
2446 UChar32 c
= affix
.char32At(i
);
2447 int32_t len
= U16_LENGTH(c
);
2449 if (input
.char32At(pos
) != c
) {
2458 if (affixLength
> 0 && ! match
) {
2466 * Skip over a run of zero or more Pattern_White_Space characters at
2469 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2470 const UChar
* s
= text
.getBuffer();
2471 return (int32_t)(PatternProps::skipWhiteSpace(s
+ pos
, text
.length() - pos
) - s
);
2475 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2478 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2479 while (pos
< text
.length()) {
2480 UChar32 c
= text
.char32At(pos
);
2481 if (!u_isUWhiteSpace(c
)) {
2484 pos
+= U16_LENGTH(c
);
2490 * Return the length matched by the given affix, or -1 if none.
2491 * @param affixPat pattern string
2492 * @param input input text
2493 * @param pos offset into input at which to begin matching
2494 * @param type the currency type to parse against, LONG_NAME only or not.
2495 * @param currency return value for parsed currency, for generic
2496 * currency parsing mode, or null for normal parsing. In generic
2497 * currency parsing mode, any currency is parsed, not just the
2498 * currency that this formatter is set to.
2499 * @return length of input that matches, or -1 if match failure
2501 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
2502 const UnicodeString
& text
,
2505 UChar
* currency
) const
2507 int32_t start
= pos
;
2508 U_ASSERT(currency
!= NULL
||
2509 (fCurrencyChoice
!= NULL
&& *getCurrency() != 0) ||
2510 fCurrencySignCount
> fgCurrencySignCountZero
);
2513 i
<affixPat
.length() && pos
>= 0; ) {
2514 UChar32 c
= affixPat
.char32At(i
);
2518 U_ASSERT(i
<= affixPat
.length());
2519 c
= affixPat
.char32At(i
);
2522 const UnicodeString
* affix
= NULL
;
2525 case kCurrencySign
: {
2526 // since the currency names in choice format is saved
2527 // the same way as other currency names,
2528 // do not need to do currency choice parsing here.
2529 // the general currency parsing parse against all names,
2530 // including names in choice format.
2531 UBool intl
= i
<affixPat
.length() &&
2532 affixPat
.char32At(i
) == kCurrencySign
;
2536 UBool plural
= i
<affixPat
.length() &&
2537 affixPat
.char32At(i
) == kCurrencySign
;
2542 // Parse generic currency -- anything for which we
2543 // have a display name, or any 3-letter ISO code.
2544 // Try to parse display name for our locale; first
2545 // determine our locale.
2546 const char* loc
= fCurrencyPluralInfo
->getLocale().getName();
2547 ParsePosition
ppos(pos
);
2549 UErrorCode ec
= U_ZERO_ERROR
;
2550 // Delegate parse of display name => ISO code to Currency
2551 uprv_parseCurrency(loc
, text
, ppos
, type
, curr
, ec
);
2553 // If parse succeeds, populate currency[0]
2554 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
2556 u_strcpy(currency
, curr
);
2558 // The formatter is currency-style but the client has not requested
2559 // the value of the parsed currency. In this case, if that value does
2560 // not match the formatter's current value, then the parse fails.
2561 UChar effectiveCurr
[4];
2562 getEffectiveCurrency(effectiveCurr
, ec
);
2563 if ( U_FAILURE(ec
) || u_strncmp(curr
,effectiveCurr
,4) != 0 ) {
2568 pos
= ppos
.getIndex();
2569 } else if (!isLenient()){
2574 case kPatternPercent
:
2575 affix
= &getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
2577 case kPatternPerMill
:
2578 affix
= &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
2581 affix
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2584 affix
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2587 // fall through to affix!=0 test, which will fail
2591 if (affix
!= NULL
) {
2592 pos
= match(text
, pos
, *affix
);
2597 pos
= match(text
, pos
, c
);
2598 if (PatternProps::isWhiteSpace(c
)) {
2599 i
= skipPatternWhiteSpace(affixPat
, i
);
2606 * Match a single character at text[pos] and return the index of the
2607 * next character upon success. Return -1 on failure. If
2608 * ch is a Pattern_White_Space then match a run of white space in text.
2610 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
2611 if (PatternProps::isWhiteSpace(ch
)) {
2612 // Advance over run of white space in input text
2613 // Must see at least one white space char in input
2615 pos
= skipPatternWhiteSpace(text
, pos
);
2621 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
2622 (pos
+ U16_LENGTH(ch
)) : -1;
2626 * Match a string at text[pos] and return the index of the next
2627 * character upon success. Return -1 on failure. Match a run of
2628 * white space in str with a run of white space in text.
2630 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
2631 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
2632 UChar32 ch
= str
.char32At(i
);
2633 i
+= U16_LENGTH(ch
);
2634 if (PatternProps::isWhiteSpace(ch
)) {
2635 i
= skipPatternWhiteSpace(str
, i
);
2637 pos
= match(text
, pos
, ch
);
2642 UBool
DecimalFormat::matchSymbol(const UnicodeString
&text
, int32_t position
, int32_t length
, const UnicodeString
&symbol
,
2643 UnicodeSet
*sset
, UChar32 schar
)
2646 return sset
->contains(schar
);
2649 return text
.compare(position
, length
, symbol
) == 0;
2652 UBool
DecimalFormat::matchDecimal(UChar32 symbolChar
,
2653 UBool sawDecimal
, UChar32 sawDecimalChar
,
2654 const UnicodeSet
*sset
, UChar32 schar
) {
2656 return schar
==sawDecimalChar
;
2657 } else if(schar
==symbolChar
) {
2659 } else if(sset
!=NULL
) {
2660 return sset
->contains(schar
);
2666 UBool
DecimalFormat::matchGrouping(UChar32 groupingChar
,
2667 UBool sawGrouping
, UChar32 sawGroupingChar
,
2668 const UnicodeSet
*sset
,
2669 UChar32
/*decimalChar*/, const UnicodeSet
*decimalSet
,
2672 return schar
==sawGroupingChar
; // previously found
2673 } else if(schar
==groupingChar
) {
2674 return TRUE
; // char from symbols
2675 } else if(sset
!=NULL
) {
2676 return sset
->contains(schar
) && // in groupingSet but...
2677 ((decimalSet
==NULL
) || !decimalSet
->contains(schar
)); // Exclude decimalSet from groupingSet
2685 //------------------------------------------------------------------------------
2686 // Gets the pointer to the localized decimal format symbols
2688 const DecimalFormatSymbols
*
2689 DecimalFormat::getDecimalFormatSymbols() const
2694 //------------------------------------------------------------------------------
2695 // De-owning the current localized symbols and adopt the new symbols.
2698 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
2700 if (symbolsToAdopt
== NULL
) {
2701 return; // do not allow caller to set fSymbols to NULL
2704 UBool sameSymbols
= FALSE
;
2705 if (fSymbols
!= NULL
) {
2706 sameSymbols
= (UBool
)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) ==
2707 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) &&
2708 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) ==
2709 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
2713 fSymbols
= symbolsToAdopt
;
2715 // If the currency symbols are the same, there is no need to recalculate.
2716 setCurrencyForSymbols();
2718 expandAffixes(NULL
);
2720 //------------------------------------------------------------------------------
2721 // Setting the symbols is equlivalent to adopting a newly created localized
2725 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
2727 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
2731 const CurrencyPluralInfo
*
2732 DecimalFormat::getCurrencyPluralInfo(void) const
2734 return fCurrencyPluralInfo
;
2739 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo
* toAdopt
)
2741 if (toAdopt
!= NULL
) {
2742 delete fCurrencyPluralInfo
;
2743 fCurrencyPluralInfo
= toAdopt
;
2744 // re-set currency affix patterns and currency affixes.
2745 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
2746 UErrorCode status
= U_ZERO_ERROR
;
2747 if (fAffixPatternsForCurrency
) {
2748 deleteHashForAffixPattern();
2750 setupCurrencyAffixPatterns(status
);
2751 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
2752 // only setup the affixes of the plural pattern.
2753 setupCurrencyAffixes(fFormatPattern
, FALSE
, TRUE
, status
);
2760 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo
& info
)
2762 adoptCurrencyPluralInfo(info
.clone());
2767 * Update the currency object to match the symbols. This method
2768 * is used only when the caller has passed in a symbols object
2769 * that may not be the default object for its locale.
2772 DecimalFormat::setCurrencyForSymbols() {
2774 Update the affix strings accroding to symbols in order to keep
2775 the affix strings up to date.
2779 // With the introduction of the Currency object, the currency
2780 // symbols in the DFS object are ignored. For backward
2781 // compatibility, we check any explicitly set DFS object. If it
2782 // is a default symbols object for its locale, we change the
2783 // currency object to one for that locale. If it is custom,
2784 // we set the currency to null.
2785 UErrorCode ec
= U_ZERO_ERROR
;
2786 const UChar
* c
= NULL
;
2787 const char* loc
= fSymbols
->getLocale().getName();
2788 UChar intlCurrencySymbol
[4];
2789 ucurr_forLocale(loc
, intlCurrencySymbol
, 4, &ec
);
2790 UnicodeString currencySymbol
;
2792 uprv_getStaticCurrencyName(intlCurrencySymbol
, loc
, currencySymbol
, ec
);
2794 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) == currencySymbol
2795 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) == UnicodeString(intlCurrencySymbol
))
2797 // Trap an error in mapping locale to currency. If we can't
2798 // map, then don't fail and set the currency to "".
2799 c
= intlCurrencySymbol
;
2801 ec
= U_ZERO_ERROR
; // reset local error code!
2802 setCurrencyInternally(c
, ec
);
2806 //------------------------------------------------------------------------------
2807 // Gets the positive prefix of the number pattern.
2810 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
2812 result
= fPositivePrefix
;
2816 //------------------------------------------------------------------------------
2817 // Sets the positive prefix of the number pattern.
2820 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
2822 fPositivePrefix
= newValue
;
2823 delete fPosPrefixPattern
;
2824 fPosPrefixPattern
= 0;
2827 //------------------------------------------------------------------------------
2828 // Gets the negative prefix of the number pattern.
2831 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
2833 result
= fNegativePrefix
;
2837 //------------------------------------------------------------------------------
2838 // Gets the negative prefix of the number pattern.
2841 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
2843 fNegativePrefix
= newValue
;
2844 delete fNegPrefixPattern
;
2845 fNegPrefixPattern
= 0;
2848 //------------------------------------------------------------------------------
2849 // Gets the positive suffix of the number pattern.
2852 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
2854 result
= fPositiveSuffix
;
2858 //------------------------------------------------------------------------------
2859 // Sets the positive suffix of the number pattern.
2862 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
2864 fPositiveSuffix
= newValue
;
2865 delete fPosSuffixPattern
;
2866 fPosSuffixPattern
= 0;
2869 //------------------------------------------------------------------------------
2870 // Gets the negative suffix of the number pattern.
2873 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
2875 result
= fNegativeSuffix
;
2879 //------------------------------------------------------------------------------
2880 // Sets the negative suffix of the number pattern.
2883 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
2885 fNegativeSuffix
= newValue
;
2886 delete fNegSuffixPattern
;
2887 fNegSuffixPattern
= 0;
2890 //------------------------------------------------------------------------------
2891 // Gets the multiplier of the number pattern.
2892 // Multipliers are stored as decimal numbers (DigitLists) because that
2893 // is the most convenient for muliplying or dividing the numbers to be formatted.
2894 // A NULL multiplier implies one, and the scaling operations are skipped.
2897 DecimalFormat::getMultiplier() const
2899 if (fMultiplier
== NULL
) {
2902 return fMultiplier
->getLong();
2906 //------------------------------------------------------------------------------
2907 // Sets the multiplier of the number pattern.
2909 DecimalFormat::setMultiplier(int32_t newValue
)
2911 // if (newValue == 0) {
2912 // throw new IllegalArgumentException("Bad multiplier: " + newValue);
2914 if (newValue
== 0) {
2915 newValue
= 1; // one being the benign default value for a multiplier.
2917 if (newValue
== 1) {
2921 if (fMultiplier
== NULL
) {
2922 fMultiplier
= new DigitList
;
2924 if (fMultiplier
!= NULL
) {
2925 fMultiplier
->set(newValue
);
2931 * Get the rounding increment.
2932 * @return A positive rounding increment, or 0.0 if rounding
2934 * @see #setRoundingIncrement
2935 * @see #getRoundingMode
2936 * @see #setRoundingMode
2938 double DecimalFormat::getRoundingIncrement() const {
2939 if (fRoundingIncrement
== NULL
) {
2942 return fRoundingIncrement
->getDouble();
2947 * Set the rounding increment. This method also controls whether
2948 * rounding is enabled.
2949 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2950 * Negative increments are equivalent to 0.0.
2951 * @see #getRoundingIncrement
2952 * @see #getRoundingMode
2953 * @see #setRoundingMode
2955 void DecimalFormat::setRoundingIncrement(double newValue
) {
2956 if (newValue
> 0.0) {
2957 if (fRoundingIncrement
== NULL
) {
2958 fRoundingIncrement
= new DigitList();
2960 if (fRoundingIncrement
!= NULL
) {
2961 fRoundingIncrement
->set(newValue
);
2965 // These statements are executed if newValue is less than 0.0
2966 // or fRoundingIncrement could not be created.
2967 delete fRoundingIncrement
;
2968 fRoundingIncrement
= NULL
;
2972 * Get the rounding mode.
2973 * @return A rounding mode
2974 * @see #setRoundingIncrement
2975 * @see #getRoundingIncrement
2976 * @see #setRoundingMode
2978 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
2979 return fRoundingMode
;
2983 * Set the rounding mode. This has no effect unless the rounding
2984 * increment is greater than zero.
2985 * @param roundingMode A rounding mode
2986 * @see #setRoundingIncrement
2987 * @see #getRoundingIncrement
2988 * @see #getRoundingMode
2990 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
2991 fRoundingMode
= roundingMode
;
2995 * Get the width to which the output of <code>format()</code> is padded.
2996 * @return the format width, or zero if no padding is in effect
2997 * @see #setFormatWidth
2998 * @see #getPadCharacter
2999 * @see #setPadCharacter
3000 * @see #getPadPosition
3001 * @see #setPadPosition
3003 int32_t DecimalFormat::getFormatWidth() const {
3004 return fFormatWidth
;
3008 * Set the width to which the output of <code>format()</code> is padded.
3009 * This method also controls whether padding is enabled.
3010 * @param width the width to which to pad the result of
3011 * <code>format()</code>, or zero to disable padding. A negative
3012 * width is equivalent to 0.
3013 * @see #getFormatWidth
3014 * @see #getPadCharacter
3015 * @see #setPadCharacter
3016 * @see #getPadPosition
3017 * @see #setPadPosition
3019 void DecimalFormat::setFormatWidth(int32_t width
) {
3020 fFormatWidth
= (width
> 0) ? width
: 0;
3023 UnicodeString
DecimalFormat::getPadCharacterString() const {
3024 return UnicodeString(fPad
);
3027 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
3028 if (padChar
.length() > 0) {
3029 fPad
= padChar
.char32At(0);
3037 * Get the position at which padding will take place. This is the location
3038 * at which padding will be inserted if the result of <code>format()</code>
3039 * is shorter than the format width.
3040 * @return the pad position, one of <code>kPadBeforePrefix</code>,
3041 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3042 * <code>kPadAfterSuffix</code>.
3043 * @see #setFormatWidth
3044 * @see #getFormatWidth
3045 * @see #setPadCharacter
3046 * @see #getPadCharacter
3047 * @see #setPadPosition
3048 * @see #kPadBeforePrefix
3049 * @see #kPadAfterPrefix
3050 * @see #kPadBeforeSuffix
3051 * @see #kPadAfterSuffix
3053 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
3054 return fPadPosition
;
3058 * <strong><font face=helvetica color=red>NEW</font></strong>
3059 * Set the position at which padding will take place. This is the location
3060 * at which padding will be inserted if the result of <code>format()</code>
3061 * is shorter than the format width. This has no effect unless padding is
3063 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
3064 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3065 * <code>kPadAfterSuffix</code>.
3066 * @see #setFormatWidth
3067 * @see #getFormatWidth
3068 * @see #setPadCharacter
3069 * @see #getPadCharacter
3070 * @see #getPadPosition
3071 * @see #kPadBeforePrefix
3072 * @see #kPadAfterPrefix
3073 * @see #kPadBeforeSuffix
3074 * @see #kPadAfterSuffix
3076 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
3077 fPadPosition
= padPos
;
3081 * Return whether or not scientific notation is used.
3082 * @return TRUE if this object formats and parses scientific notation
3083 * @see #setScientificNotation
3084 * @see #getMinimumExponentDigits
3085 * @see #setMinimumExponentDigits
3086 * @see #isExponentSignAlwaysShown
3087 * @see #setExponentSignAlwaysShown
3089 UBool
DecimalFormat::isScientificNotation() {
3090 return fUseExponentialNotation
;
3094 * Set whether or not scientific notation is used.
3095 * @param useScientific TRUE if this object formats and parses scientific
3097 * @see #isScientificNotation
3098 * @see #getMinimumExponentDigits
3099 * @see #setMinimumExponentDigits
3100 * @see #isExponentSignAlwaysShown
3101 * @see #setExponentSignAlwaysShown
3103 void DecimalFormat::setScientificNotation(UBool useScientific
) {
3104 fUseExponentialNotation
= useScientific
;
3108 * Return the minimum exponent digits that will be shown.
3109 * @return the minimum exponent digits that will be shown
3110 * @see #setScientificNotation
3111 * @see #isScientificNotation
3112 * @see #setMinimumExponentDigits
3113 * @see #isExponentSignAlwaysShown
3114 * @see #setExponentSignAlwaysShown
3116 int8_t DecimalFormat::getMinimumExponentDigits() const {
3117 return fMinExponentDigits
;
3121 * Set the minimum exponent digits that will be shown. This has no
3122 * effect unless scientific notation is in use.
3123 * @param minExpDig a value >= 1 indicating the fewest exponent digits
3124 * that will be shown. Values less than 1 will be treated as 1.
3125 * @see #setScientificNotation
3126 * @see #isScientificNotation
3127 * @see #getMinimumExponentDigits
3128 * @see #isExponentSignAlwaysShown
3129 * @see #setExponentSignAlwaysShown
3131 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
3132 fMinExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
3136 * Return whether the exponent sign is always shown.
3137 * @return TRUE if the exponent is always prefixed with either the
3138 * localized minus sign or the localized plus sign, false if only negative
3139 * exponents are prefixed with the localized minus sign.
3140 * @see #setScientificNotation
3141 * @see #isScientificNotation
3142 * @see #setMinimumExponentDigits
3143 * @see #getMinimumExponentDigits
3144 * @see #setExponentSignAlwaysShown
3146 UBool
DecimalFormat::isExponentSignAlwaysShown() {
3147 return fExponentSignAlwaysShown
;
3151 * Set whether the exponent sign is always shown. This has no effect
3152 * unless scientific notation is in use.
3153 * @param expSignAlways TRUE if the exponent is always prefixed with either
3154 * the localized minus sign or the localized plus sign, false if only
3155 * negative exponents are prefixed with the localized minus sign.
3156 * @see #setScientificNotation
3157 * @see #isScientificNotation
3158 * @see #setMinimumExponentDigits
3159 * @see #getMinimumExponentDigits
3160 * @see #isExponentSignAlwaysShown
3162 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
3163 fExponentSignAlwaysShown
= expSignAlways
;
3166 //------------------------------------------------------------------------------
3167 // Gets the grouping size of the number pattern. For example, thousand or 10
3168 // thousand groupings.
3171 DecimalFormat::getGroupingSize() const
3173 return fGroupingSize
;
3176 //------------------------------------------------------------------------------
3177 // Gets the grouping size of the number pattern.
3180 DecimalFormat::setGroupingSize(int32_t newValue
)
3182 fGroupingSize
= newValue
;
3185 //------------------------------------------------------------------------------
3188 DecimalFormat::getSecondaryGroupingSize() const
3190 return fGroupingSize2
;
3193 //------------------------------------------------------------------------------
3196 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
3198 fGroupingSize2
= newValue
;
3201 //------------------------------------------------------------------------------
3202 // Checks if to show the decimal separator.
3205 DecimalFormat::isDecimalSeparatorAlwaysShown() const
3207 return fDecimalSeparatorAlwaysShown
;
3210 //------------------------------------------------------------------------------
3211 // Sets to always show the decimal separator.
3214 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
3216 fDecimalSeparatorAlwaysShown
= newValue
;
3219 //------------------------------------------------------------------------------
3220 // Emits the pattern of this DecimalFormat instance.
3223 DecimalFormat::toPattern(UnicodeString
& result
) const
3225 return toPattern(result
, FALSE
);
3228 //------------------------------------------------------------------------------
3229 // Emits the localized pattern this DecimalFormat instance.
3232 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
3234 return toPattern(result
, TRUE
);
3237 //------------------------------------------------------------------------------
3239 * Expand the affix pattern strings into the expanded affix strings. If any
3240 * affix pattern string is null, do not expand it. This method should be
3241 * called any time the symbols or the affix patterns change in order to keep
3242 * the expanded affix strings up to date.
3243 * This method also will be called before formatting if format currency
3244 * plural names, since the plural name is not a static one, it is
3245 * based on the currency plural count, the affix will be known only
3246 * after the currency plural count is know.
3247 * In which case, the parameter
3248 * 'pluralCount' will be a non-null currency plural count.
3249 * In all other cases, the 'pluralCount' is null, which means it is not needed.
3251 void DecimalFormat::expandAffixes(const UnicodeString
* pluralCount
) {
3252 FieldPositionHandler none
;
3253 if (fPosPrefixPattern
!= 0) {
3254 expandAffix(*fPosPrefixPattern
, fPositivePrefix
, 0, none
, FALSE
, pluralCount
);
3256 if (fPosSuffixPattern
!= 0) {
3257 expandAffix(*fPosSuffixPattern
, fPositiveSuffix
, 0, none
, FALSE
, pluralCount
);
3259 if (fNegPrefixPattern
!= 0) {
3260 expandAffix(*fNegPrefixPattern
, fNegativePrefix
, 0, none
, FALSE
, pluralCount
);
3262 if (fNegSuffixPattern
!= 0) {
3263 expandAffix(*fNegSuffixPattern
, fNegativeSuffix
, 0, none
, FALSE
, pluralCount
);
3268 .append(*fPosPrefixPattern
).append("|").append(*fPosSuffixPattern
)
3269 .append(";") .append(*fNegPrefixPattern
).append("|").append(*fNegSuffixPattern
)
3271 .append(fPositivePrefix
).append("|").append(fPositiveSuffix
)
3272 .append(";") .append(fNegativePrefix
).append("|").append(fNegativeSuffix
)
3279 * Expand an affix pattern into an affix string. All characters in the
3280 * pattern are literal unless prefixed by kQuote. The following characters
3281 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
3282 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
3283 * kCurrencySign + kCurrencySign), it is interpreted as an international
3284 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
3285 * currency plural long names, such as "US Dollars".
3286 * Any other character after a kQuote represents itself.
3287 * kQuote must be followed by another character; kQuote may not occur by
3288 * itself at the end of the pattern.
3290 * This method is used in two distinct ways. First, it is used to expand
3291 * the stored affix patterns into actual affixes. For this usage, doFormat
3292 * must be false. Second, it is used to expand the stored affix patterns
3293 * given a specific number (doFormat == true), for those rare cases in
3294 * which a currency format references a ChoiceFormat (e.g., en_IN display
3295 * name for INR). The number itself is taken from digitList.
3297 * When used in the first way, this method has a side effect: It sets
3298 * currencyChoice to a ChoiceFormat object, if the currency's display name
3299 * in this locale is a ChoiceFormat pattern (very rare). It only does this
3300 * if currencyChoice is null to start with.
3302 * @param pattern the non-null, fPossibly empty pattern
3303 * @param affix string to receive the expanded equivalent of pattern.
3304 * Previous contents are deleted.
3305 * @param doFormat if false, then the pattern will be expanded, and if a
3306 * currency symbol is encountered that expands to a ChoiceFormat, the
3307 * currencyChoice member variable will be initialized if it is null. If
3308 * doFormat is true, then it is assumed that the currencyChoice has been
3309 * created, and it will be used to format the value in digitList.
3310 * @param pluralCount the plural count. It is only used for currency
3311 * plural format. In which case, it is the plural
3312 * count of the currency amount. For example,
3313 * in en_US, it is the singular "one", or the plural
3314 * "other". For all other cases, it is null, and
3315 * is not being used.
3317 void DecimalFormat::expandAffix(const UnicodeString
& pattern
,
3318 UnicodeString
& affix
,
3320 FieldPositionHandler
& handler
,
3322 const UnicodeString
* pluralCount
) const {
3324 for (int i
=0; i
<pattern
.length(); ) {
3325 UChar32 c
= pattern
.char32At(i
);
3328 c
= pattern
.char32At(i
);
3330 int beginIdx
= affix
.length();
3332 case kCurrencySign
: {
3333 // As of ICU 2.2 we use the currency object, and
3334 // ignore the currency symbols in the DFS, unless
3335 // we have a null currency object. This occurs if
3336 // resurrecting a pre-2.2 object or if the user
3337 // sets a custom DFS.
3338 UBool intl
= i
<pattern
.length() &&
3339 pattern
.char32At(i
) == kCurrencySign
;
3340 UBool plural
= FALSE
;
3343 plural
= i
<pattern
.length() &&
3344 pattern
.char32At(i
) == kCurrencySign
;
3350 const UChar
* currencyUChars
= getCurrency();
3351 if (currencyUChars
[0] != 0) {
3352 UErrorCode ec
= U_ZERO_ERROR
;
3353 if (plural
&& pluralCount
!= NULL
) {
3354 // plural name is only needed when pluralCount != null,
3355 // which means when formatting currency plural names.
3356 // For other cases, pluralCount == null,
3357 // and plural names are not needed.
3359 CharString pluralCountChar
;
3360 pluralCountChar
.appendInvariantChars(*pluralCount
, ec
);
3361 UBool isChoiceFormat
;
3362 const UChar
* s
= ucurr_getPluralName(currencyUChars
,
3363 fSymbols
!= NULL
? fSymbols
->getLocale().getName() :
3364 Locale::getDefault().getName(), &isChoiceFormat
,
3365 pluralCountChar
.data(), &len
, &ec
);
3366 affix
+= UnicodeString(s
, len
);
3367 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3369 affix
.append(currencyUChars
, -1);
3370 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3373 UBool isChoiceFormat
;
3374 // If fSymbols is NULL, use default locale
3375 const UChar
* s
= ucurr_getName(currencyUChars
,
3376 fSymbols
!= NULL
? fSymbols
->getLocale().getName() : Locale::getDefault().getName(),
3377 UCURR_SYMBOL_NAME
, &isChoiceFormat
, &len
, &ec
);
3378 if (isChoiceFormat
) {
3379 // Two modes here: If doFormat is false, we set up
3380 // currencyChoice. If doFormat is true, we use the
3381 // previously created currencyChoice to format the
3382 // value in digitList.
3384 // If the currency is handled by a ChoiceFormat,
3385 // then we're not going to use the expanded
3386 // patterns. Instantiate the ChoiceFormat and
3388 if (fCurrencyChoice
== NULL
) {
3389 // TODO Replace double-check with proper thread-safe code
3390 ChoiceFormat
* fmt
= new ChoiceFormat(UnicodeString(s
), ec
);
3391 if (U_SUCCESS(ec
)) {
3393 if (fCurrencyChoice
== NULL
) {
3395 ((DecimalFormat
*)this)->fCurrencyChoice
= fmt
;
3402 // We could almost return null or "" here, since the
3403 // expanded affixes are almost not used at all
3404 // in this situation. However, one method --
3405 // toPattern() -- still does use the expanded
3406 // affixes, in order to set up a padding
3407 // pattern. We use the CURRENCY_SIGN as a
3409 affix
.append(kCurrencySign
);
3411 if (fCurrencyChoice
!= NULL
) {
3412 FieldPosition
pos(0); // ignored
3416 fCurrencyChoice
->format(number
, affix
, pos
);
3418 // We only arrive here if the currency choice
3419 // format in the locale data is INVALID.
3420 affix
.append(currencyUChars
, -1);
3421 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3426 affix
+= UnicodeString(s
, len
);
3427 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3431 affix
+= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3433 affix
+= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
3435 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3439 case kPatternPercent
:
3440 affix
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3441 handler
.addAttribute(kPercentField
, beginIdx
, affix
.length());
3443 case kPatternPerMill
:
3444 affix
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3445 handler
.addAttribute(kPermillField
, beginIdx
, affix
.length());
3448 affix
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3449 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
3452 affix
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3453 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
3467 * Append an affix to the given StringBuffer.
3468 * @param buf buffer to append to
3472 int32_t DecimalFormat::appendAffix(UnicodeString
& buf
, double number
,
3473 FieldPositionHandler
& handler
,
3474 UBool isNegative
, UBool isPrefix
) const {
3475 // plural format precedes choice format
3476 if (fCurrencyChoice
!= 0 &&
3477 fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
3478 const UnicodeString
* affixPat
;
3480 affixPat
= isNegative
? fNegPrefixPattern
: fPosPrefixPattern
;
3482 affixPat
= isNegative
? fNegSuffixPattern
: fPosSuffixPattern
;
3485 UnicodeString affixBuf
;
3486 expandAffix(*affixPat
, affixBuf
, number
, handler
, TRUE
, NULL
);
3487 buf
.append(affixBuf
);
3488 return affixBuf
.length();
3490 // else someone called a function that reset the pattern.
3493 const UnicodeString
* affix
;
3494 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
3495 UnicodeString pluralCount
= fCurrencyPluralInfo
->getPluralRules()->select(number
);
3496 AffixesForCurrency
* oneSet
;
3497 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
3498 oneSet
= (AffixesForCurrency
*)fPluralAffixesForCurrency
->get(pluralCount
);
3500 oneSet
= (AffixesForCurrency
*)fAffixesForCurrency
->get(pluralCount
);
3503 affix
= isNegative
? &oneSet
->negPrefixForCurrency
:
3504 &oneSet
->posPrefixForCurrency
;
3506 affix
= isNegative
? &oneSet
->negSuffixForCurrency
:
3507 &oneSet
->posSuffixForCurrency
;
3511 affix
= isNegative
? &fNegativePrefix
: &fPositivePrefix
;
3513 affix
= isNegative
? &fNegativeSuffix
: &fPositiveSuffix
;
3517 int32_t begin
= (int) buf
.length();
3521 if (handler
.isRecording()) {
3522 int32_t offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
));
3524 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
3525 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3528 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
3530 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3531 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3534 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
3536 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3537 handler
.addAttribute(kSignField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3540 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
3542 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3543 handler
.addAttribute(kPercentField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3546 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
3548 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3549 handler
.addAttribute(kPermillField
, begin
+ offset
, begin
+ offset
+ aff
.length());
3552 return affix
->length();
3556 * Appends an affix pattern to the given StringBuffer, quoting special
3557 * characters as needed. Uses the internal affix pattern, if that exists,
3558 * or the literal affix, if the internal affix pattern is null. The
3559 * appended string will generate the same affix pattern (or literal affix)
3560 * when passed to toPattern().
3562 * @param appendTo the affix string is appended to this
3563 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
3564 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
3565 * Ignored unless affixPattern is null. If affixPattern is null, then
3566 * expAffix is appended as a literal affix.
3567 * @param localized true if the appended pattern should contain localized
3568 * pattern characters; otherwise, non-localized pattern chars are appended
3570 void DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
3571 const UnicodeString
* affixPattern
,
3572 const UnicodeString
& expAffix
,
3573 UBool localized
) const {
3574 if (affixPattern
== 0) {
3575 appendAffixPattern(appendTo
, expAffix
, localized
);
3578 for (int pos
=0; pos
<affixPattern
->length(); pos
=i
) {
3579 i
= affixPattern
->indexOf(kQuote
, pos
);
3582 affixPattern
->extractBetween(pos
, affixPattern
->length(), s
);
3583 appendAffixPattern(appendTo
, s
, localized
);
3588 affixPattern
->extractBetween(pos
, i
, s
);
3589 appendAffixPattern(appendTo
, s
, localized
);
3591 UChar32 c
= affixPattern
->char32At(++i
);
3594 appendTo
.append(c
).append(c
);
3595 // Fall through and append another kQuote below
3596 } else if (c
== kCurrencySign
&&
3597 i
<affixPattern
->length() &&
3598 affixPattern
->char32At(i
) == kCurrencySign
) {
3600 appendTo
.append(c
).append(c
);
3601 } else if (localized
) {
3603 case kPatternPercent
:
3604 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3606 case kPatternPerMill
:
3607 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3610 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3613 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3626 * Append an affix to the given StringBuffer, using quotes if
3627 * there are special characters. Single quotes themselves must be
3628 * escaped in either case.
3631 DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
3632 const UnicodeString
& affix
,
3633 UBool localized
) const {
3636 needQuote
= affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
)) >= 0
3637 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
)) >= 0
3638 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
)) >= 0
3639 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
)) >= 0
3640 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
)) >= 0
3641 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
)) >= 0
3642 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
)) >= 0
3643 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
)) >= 0
3644 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) >= 0
3645 || affix
.indexOf(kCurrencySign
) >= 0;
3648 needQuote
= affix
.indexOf(kPatternZeroDigit
) >= 0
3649 || affix
.indexOf(kPatternGroupingSeparator
) >= 0
3650 || affix
.indexOf(kPatternDecimalSeparator
) >= 0
3651 || affix
.indexOf(kPatternPercent
) >= 0
3652 || affix
.indexOf(kPatternPerMill
) >= 0
3653 || affix
.indexOf(kPatternDigit
) >= 0
3654 || affix
.indexOf(kPatternSeparator
) >= 0
3655 || affix
.indexOf(kPatternExponent
) >= 0
3656 || affix
.indexOf(kPatternPlus
) >= 0
3657 || affix
.indexOf(kPatternMinus
) >= 0
3658 || affix
.indexOf(kCurrencySign
) >= 0;
3661 appendTo
+= (UChar
)0x0027 /*'\''*/;
3662 if (affix
.indexOf((UChar
)0x0027 /*'\''*/) < 0)
3665 for (int32_t j
= 0; j
< affix
.length(); ) {
3666 UChar32 c
= affix
.char32At(j
);
3669 if (c
== 0x0027 /*'\''*/)
3674 appendTo
+= (UChar
)0x0027 /*'\''*/;
3677 //------------------------------------------------------------------------------
3680 DecimalFormat::toPattern(UnicodeString
& result
, UBool localized
) const
3682 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
3683 // the prefix or suffix pattern might not be defined yet,
3684 // so they can not be synthesized,
3685 // instead, get them directly.
3686 // but it might not be the actual pattern used in formatting.
3687 // the actual pattern used in formatting depends on the
3688 // formatted number's plural count.
3689 result
= fFormatPattern
;
3693 UChar32 zero
, sigDigit
= kPatternSignificantDigit
;
3694 UnicodeString digit
, group
;
3696 int32_t roundingDecimalPos
= 0; // Pos of decimal in roundingDigits
3697 UnicodeString roundingDigits
;
3698 int32_t padPos
= (fFormatWidth
> 0) ? fPadPosition
: -1;
3699 UnicodeString padSpec
;
3700 UBool useSigDig
= areSignificantDigitsUsed();
3703 digit
.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
3704 group
.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
3705 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
3707 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
3711 digit
.append((UChar
)kPatternDigit
);
3712 group
.append((UChar
)kPatternGroupingSeparator
);
3713 zero
= (UChar32
)kPatternZeroDigit
;
3715 if (fFormatWidth
> 0) {
3717 padSpec
.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
3720 padSpec
.append((UChar
)kPatternPadEscape
);
3722 padSpec
.append(fPad
);
3724 if (fRoundingIncrement
!= NULL
) {
3725 for(i
=0; i
<fRoundingIncrement
->getCount(); ++i
) {
3726 roundingDigits
.append(zero
+(fRoundingIncrement
->getDigitValue(i
))); // Convert to Unicode digit
3728 roundingDecimalPos
= fRoundingIncrement
->getDecimalAt();
3730 for (int32_t part
=0; part
<2; ++part
) {
3731 if (padPos
== kPadBeforePrefix
) {
3732 result
.append(padSpec
);
3734 appendAffixPattern(result
,
3735 (part
==0 ? fPosPrefixPattern
: fNegPrefixPattern
),
3736 (part
==0 ? fPositivePrefix
: fNegativePrefix
),
3738 if (padPos
== kPadAfterPrefix
&& ! padSpec
.isEmpty()) {
3739 result
.append(padSpec
);
3741 int32_t sub0Start
= result
.length();
3742 int32_t g
= isGroupingUsed() ? _max(0, fGroupingSize
) : 0;
3743 if (g
> 0 && fGroupingSize2
> 0 && fGroupingSize2
!= fGroupingSize
) {
3744 g
+= fGroupingSize2
;
3746 int32_t maxDig
= 0, minDig
= 0, maxSigDig
= 0;
3748 minDig
= getMinimumSignificantDigits();
3749 maxDig
= maxSigDig
= getMaximumSignificantDigits();
3751 minDig
= getMinimumIntegerDigits();
3752 maxDig
= getMaximumIntegerDigits();
3754 if (fUseExponentialNotation
) {
3755 if (maxDig
> kMaxScientificIntegerDigits
) {
3758 } else if (useSigDig
) {
3759 maxDig
= _max(maxDig
, g
+1);
3761 maxDig
= _max(_max(g
, getMinimumIntegerDigits()),
3762 roundingDecimalPos
) + 1;
3764 for (i
= maxDig
; i
> 0; --i
) {
3765 if (!fUseExponentialNotation
&& i
<maxDig
&&
3766 isGroupingPosition(i
)) {
3767 result
.append(group
);
3770 // #@,@### (maxSigDig == 5, minSigDig == 2)
3771 // 65 4321 (1-based pos, count from the right)
3772 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
3773 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
3774 if (maxSigDig
>= i
&& i
> (maxSigDig
- minDig
)) {
3775 result
.append(sigDigit
);
3777 result
.append(digit
);
3780 if (! roundingDigits
.isEmpty()) {
3781 int32_t pos
= roundingDecimalPos
- i
;
3782 if (pos
>= 0 && pos
< roundingDigits
.length()) {
3783 result
.append((UChar
) (roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
3788 result
.append(zero
);
3790 result
.append(digit
);
3795 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown
) {
3797 result
+= getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
3800 result
.append((UChar
)kPatternDecimalSeparator
);
3803 int32_t pos
= roundingDecimalPos
;
3804 for (i
= 0; i
< getMaximumFractionDigits(); ++i
) {
3805 if (! roundingDigits
.isEmpty() && pos
< roundingDigits
.length()) {
3807 result
.append(zero
);
3810 result
.append((UChar
)(roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
3815 if (i
<getMinimumFractionDigits()) {
3816 result
.append(zero
);
3819 result
.append(digit
);
3823 if (fUseExponentialNotation
) {
3825 result
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
3828 result
.append((UChar
)kPatternExponent
);
3830 if (fExponentSignAlwaysShown
) {
3832 result
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3835 result
.append((UChar
)kPatternPlus
);
3838 for (i
=0; i
<fMinExponentDigits
; ++i
) {
3839 result
.append(zero
);
3842 if (! padSpec
.isEmpty() && !fUseExponentialNotation
) {
3843 int32_t add
= fFormatWidth
- result
.length() + sub0Start
3845 ? fPositivePrefix
.length() + fPositiveSuffix
.length()
3846 : fNegativePrefix
.length() + fNegativeSuffix
.length());
3848 result
.insert(sub0Start
, digit
);
3851 // Only add a grouping separator if we have at least
3852 // 2 additional characters to be added, so we don't
3853 // end up with ",###".
3854 if (add
>1 && isGroupingPosition(maxDig
)) {
3855 result
.insert(sub0Start
, group
);
3860 if (fPadPosition
== kPadBeforeSuffix
&& ! padSpec
.isEmpty()) {
3861 result
.append(padSpec
);
3864 appendAffixPattern(result
, fPosSuffixPattern
, fPositiveSuffix
, localized
);
3865 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
3866 result
.append(padSpec
);
3868 UBool isDefault
= FALSE
;
3869 if ((fNegSuffixPattern
== fPosSuffixPattern
&& // both null
3870 fNegativeSuffix
== fPositiveSuffix
)
3871 || (fNegSuffixPattern
!= 0 && fPosSuffixPattern
!= 0 &&
3872 *fNegSuffixPattern
== *fPosSuffixPattern
))
3874 if (fNegPrefixPattern
!= NULL
&& fPosPrefixPattern
!= NULL
)
3876 int32_t length
= fPosPrefixPattern
->length();
3877 isDefault
= fNegPrefixPattern
->length() == (length
+2) &&
3878 (*fNegPrefixPattern
)[(int32_t)0] == kQuote
&&
3879 (*fNegPrefixPattern
)[(int32_t)1] == kPatternMinus
&&
3880 fNegPrefixPattern
->compare(2, length
, *fPosPrefixPattern
, 0, length
) == 0;
3883 fNegPrefixPattern
== NULL
&& fPosPrefixPattern
== NULL
)
3885 int32_t length
= fPositivePrefix
.length();
3886 isDefault
= fNegativePrefix
.length() == (length
+1) &&
3887 fNegativePrefix
.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) == 0 &&
3888 fNegativePrefix
.compare(1, length
, fPositivePrefix
, 0, length
) == 0;
3892 break; // Don't output default negative subpattern
3895 result
+= getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
);
3898 result
.append((UChar
)kPatternSeparator
);
3902 appendAffixPattern(result
, fNegSuffixPattern
, fNegativeSuffix
, localized
);
3903 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
3904 result
.append(padSpec
);
3912 //------------------------------------------------------------------------------
3915 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
3917 UParseError parseError
;
3918 applyPattern(pattern
, FALSE
, parseError
, status
);
3921 //------------------------------------------------------------------------------
3924 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
3925 UParseError
& parseError
,
3928 applyPattern(pattern
, FALSE
, parseError
, status
);
3930 //------------------------------------------------------------------------------
3933 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
3935 UParseError parseError
;
3936 applyPattern(pattern
, TRUE
,parseError
,status
);
3939 //------------------------------------------------------------------------------
3942 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
3943 UParseError
& parseError
,
3946 applyPattern(pattern
, TRUE
,parseError
,status
);
3949 //------------------------------------------------------------------------------
3952 DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString
& pattern
,
3954 UParseError
& parseError
,
3957 if (U_FAILURE(status
))
3961 // Clear error struct
3962 parseError
.offset
= -1;
3963 parseError
.preContext
[0] = parseError
.postContext
[0] = (UChar
)0;
3965 // Set the significant pattern symbols
3966 UChar32 zeroDigit
= kPatternZeroDigit
; // '0'
3967 UChar32 sigDigit
= kPatternSignificantDigit
; // '@'
3968 UnicodeString
groupingSeparator ((UChar
)kPatternGroupingSeparator
);
3969 UnicodeString
decimalSeparator ((UChar
)kPatternDecimalSeparator
);
3970 UnicodeString
percent ((UChar
)kPatternPercent
);
3971 UnicodeString
perMill ((UChar
)kPatternPerMill
);
3972 UnicodeString
digit ((UChar
)kPatternDigit
); // '#'
3973 UnicodeString
separator ((UChar
)kPatternSeparator
);
3974 UnicodeString
exponent ((UChar
)kPatternExponent
);
3975 UnicodeString
plus ((UChar
)kPatternPlus
);
3976 UnicodeString
minus ((UChar
)kPatternMinus
);
3977 UnicodeString
padEscape ((UChar
)kPatternPadEscape
);
3978 // Substitute with the localized symbols if necessary
3980 zeroDigit
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
3981 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
3982 groupingSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
3983 decimalSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
));
3984 percent
. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
3985 perMill
. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
3986 digit
. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
3987 separator
. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
));
3988 exponent
. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
));
3989 plus
. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
));
3990 minus
. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
3991 padEscape
. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
3993 UChar nineDigit
= (UChar
)(zeroDigit
+ 9);
3994 int32_t digitLen
= digit
.length();
3995 int32_t groupSepLen
= groupingSeparator
.length();
3996 int32_t decimalSepLen
= decimalSeparator
.length();
3999 int32_t patLen
= pattern
.length();
4000 // Part 0 is the positive pattern. Part 1, if present, is the negative
4002 for (int32_t part
=0; part
<2 && pos
<patLen
; ++part
) {
4003 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
4004 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
4005 // between the prefix and suffix, and consists of pattern
4006 // characters. In the prefix and suffix, percent, perMill, and
4007 // currency symbols are recognized and translated.
4008 int32_t subpart
= 1, sub0Start
= 0, sub0Limit
= 0, sub2Limit
= 0;
4010 // It's important that we don't change any fields of this object
4011 // prematurely. We set the following variables for the multiplier,
4012 // grouping, etc., and then only change the actual object fields if
4013 // everything parses correctly. This also lets us register
4014 // the data from part 0 and ignore the part 1, except for the
4015 // prefix and suffix.
4016 UnicodeString prefix
;
4017 UnicodeString suffix
;
4018 int32_t decimalPos
= -1;
4019 int32_t multiplier
= 1;
4020 int32_t digitLeftCount
= 0, zeroDigitCount
= 0, digitRightCount
= 0, sigDigitCount
= 0;
4021 int8_t groupingCount
= -1;
4022 int8_t groupingCount2
= -1;
4023 int32_t padPos
= -1;
4024 UChar32 padChar
= 0;
4025 int32_t roundingPos
= -1;
4026 DigitList roundingInc
;
4027 int8_t expDigits
= -1;
4028 UBool expSignAlways
= FALSE
;
4030 // The affix is either the prefix or the suffix.
4031 UnicodeString
* affix
= &prefix
;
4033 int32_t start
= pos
;
4034 UBool isPartDone
= FALSE
;
4037 for (; !isPartDone
&& pos
< patLen
; ) {
4038 // Todo: account for surrogate pairs
4039 ch
= pattern
.char32At(pos
);
4041 case 0: // Pattern proper subpart (between prefix & suffix)
4042 // Process the digits, decimal, and grouping characters. We
4043 // record five pieces of information. We expect the digits
4044 // to occur in the pattern ####00.00####, and we record the
4045 // number of left digits, zero (central) digits, and right
4046 // digits. The position of the last grouping character is
4047 // recorded (should be somewhere within the first two blocks
4048 // of characters), as is the position of the decimal point,
4049 // if any (should be in the zero digits). If there is no
4050 // decimal point, then there should be no right digits.
4051 if (pattern
.compare(pos
, digitLen
, digit
) == 0) {
4052 if (zeroDigitCount
> 0 || sigDigitCount
> 0) {
4057 if (groupingCount
>= 0 && decimalPos
< 0) {
4061 } else if ((ch
>= zeroDigit
&& ch
<= nineDigit
) ||
4063 if (digitRightCount
> 0) {
4065 debug("Unexpected '0'")
4066 status
= U_UNEXPECTED_TOKEN
;
4067 syntaxError(pattern
,pos
,parseError
);
4070 if (ch
== sigDigit
) {
4073 if (ch
!= zeroDigit
&& roundingPos
< 0) {
4074 roundingPos
= digitLeftCount
+ zeroDigitCount
;
4076 if (roundingPos
>= 0) {
4077 roundingInc
.append((char)(ch
- zeroDigit
+ '0'));
4081 if (groupingCount
>= 0 && decimalPos
< 0) {
4084 pos
+= U16_LENGTH(ch
);
4085 } else if (pattern
.compare(pos
, groupSepLen
, groupingSeparator
) == 0) {
4086 if (decimalPos
>= 0) {
4087 // Grouping separator after decimal
4088 debug("Grouping separator after decimal")
4089 status
= U_UNEXPECTED_TOKEN
;
4090 syntaxError(pattern
,pos
,parseError
);
4093 groupingCount2
= groupingCount
;
4096 } else if (pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) == 0) {
4097 if (decimalPos
>= 0) {
4098 // Multiple decimal separators
4099 debug("Multiple decimal separators")
4100 status
= U_MULTIPLE_DECIMAL_SEPARATORS
;
4101 syntaxError(pattern
,pos
,parseError
);
4104 // Intentionally incorporate the digitRightCount,
4105 // even though it is illegal for this to be > 0
4106 // at this point. We check pattern syntax below.
4107 decimalPos
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
4108 pos
+= decimalSepLen
;
4110 if (pattern
.compare(pos
, exponent
.length(), exponent
) == 0) {
4111 if (expDigits
>= 0) {
4112 // Multiple exponential symbols
4113 debug("Multiple exponential symbols")
4114 status
= U_MULTIPLE_EXPONENTIAL_SYMBOLS
;
4115 syntaxError(pattern
,pos
,parseError
);
4118 if (groupingCount
>= 0) {
4119 // Grouping separator in exponential pattern
4120 debug("Grouping separator in exponential pattern")
4121 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
4122 syntaxError(pattern
,pos
,parseError
);
4125 pos
+= exponent
.length();
4126 // Check for positive prefix
4128 && pattern
.compare(pos
, plus
.length(), plus
) == 0) {
4129 expSignAlways
= TRUE
;
4130 pos
+= plus
.length();
4132 // Use lookahead to parse out the exponential part of the
4133 // pattern, then jump into suffix subpart.
4135 while (pos
< patLen
&&
4136 pattern
.char32At(pos
) == zeroDigit
) {
4138 pos
+= U16_LENGTH(zeroDigit
);
4141 // 1. Require at least one mantissa pattern digit
4142 // 2. Disallow "#+ @" in mantissa
4143 // 3. Require at least one exponent pattern digit
4144 if (((digitLeftCount
+ zeroDigitCount
) < 1 &&
4145 (sigDigitCount
+ digitRightCount
) < 1) ||
4146 (sigDigitCount
> 0 && digitLeftCount
> 0) ||
4148 // Malformed exponential pattern
4149 debug("Malformed exponential pattern")
4150 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
4151 syntaxError(pattern
,pos
,parseError
);
4155 // Transition to suffix subpart
4156 subpart
= 2; // suffix subpart
4162 case 1: // Prefix subpart
4163 case 2: // Suffix subpart
4164 // Process the prefix / suffix characters
4165 // Process unquoted characters seen in prefix or suffix
4168 // Several syntax characters implicitly begins the
4169 // next subpart if we are in the prefix; otherwise
4170 // they are illegal if unquoted.
4171 if (!pattern
.compare(pos
, digitLen
, digit
) ||
4172 !pattern
.compare(pos
, groupSepLen
, groupingSeparator
) ||
4173 !pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) ||
4174 (ch
>= zeroDigit
&& ch
<= nineDigit
) ||
4176 if (subpart
== 1) { // prefix subpart
4177 subpart
= 0; // pattern proper subpart
4178 sub0Start
= pos
; // Reprocess this character
4181 status
= U_UNQUOTED_SPECIAL
;
4182 syntaxError(pattern
,pos
,parseError
);
4185 } else if (ch
== kCurrencySign
) {
4186 affix
->append(kQuote
); // Encode currency
4187 // Use lookahead to determine if the currency sign is
4189 U_ASSERT(U16_LENGTH(kCurrencySign
) == 1);
4190 if ((pos
+1) < pattern
.length() && pattern
[pos
+1] == kCurrencySign
) {
4191 affix
->append(kCurrencySign
);
4192 ++pos
; // Skip over the doubled character
4193 if ((pos
+1) < pattern
.length() &&
4194 pattern
[pos
+1] == kCurrencySign
) {
4195 affix
->append(kCurrencySign
);
4196 ++pos
; // Skip over the doubled character
4197 fCurrencySignCount
= fgCurrencySignCountInPluralFormat
;
4199 fCurrencySignCount
= fgCurrencySignCountInISOFormat
;
4202 fCurrencySignCount
= fgCurrencySignCountInSymbolFormat
;
4204 // Fall through to append(ch)
4205 } else if (ch
== kQuote
) {
4206 // A quote outside quotes indicates either the opening
4207 // quote or two quotes, which is a quote literal. That is,
4208 // we have the first quote in 'do' or o''clock.
4209 U_ASSERT(U16_LENGTH(kQuote
) == 1);
4211 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
4212 affix
->append(kQuote
); // Encode quote
4213 // Fall through to append(ch)
4215 subpart
+= 2; // open quote
4218 } else if (pattern
.compare(pos
, separator
.length(), separator
) == 0) {
4219 // Don't allow separators in the prefix, and don't allow
4220 // separators in the second pattern (part == 1).
4221 if (subpart
== 1 || part
== 1) {
4222 // Unexpected separator
4223 debug("Unexpected separator")
4224 status
= U_UNEXPECTED_TOKEN
;
4225 syntaxError(pattern
,pos
,parseError
);
4229 isPartDone
= TRUE
; // Go to next part
4230 pos
+= separator
.length();
4232 } else if (pattern
.compare(pos
, percent
.length(), percent
) == 0) {
4233 // Next handle characters which are appended directly.
4234 if (multiplier
!= 1) {
4235 // Too many percent/perMill characters
4236 debug("Too many percent characters")
4237 status
= U_MULTIPLE_PERCENT_SYMBOLS
;
4238 syntaxError(pattern
,pos
,parseError
);
4241 affix
->append(kQuote
); // Encode percent/perMill
4242 affix
->append(kPatternPercent
); // Use unlocalized pattern char
4244 pos
+= percent
.length();
4246 } else if (pattern
.compare(pos
, perMill
.length(), perMill
) == 0) {
4247 // Next handle characters which are appended directly.
4248 if (multiplier
!= 1) {
4249 // Too many percent/perMill characters
4250 debug("Too many perMill characters")
4251 status
= U_MULTIPLE_PERMILL_SYMBOLS
;
4252 syntaxError(pattern
,pos
,parseError
);
4255 affix
->append(kQuote
); // Encode percent/perMill
4256 affix
->append(kPatternPerMill
); // Use unlocalized pattern char
4258 pos
+= perMill
.length();
4260 } else if (pattern
.compare(pos
, padEscape
.length(), padEscape
) == 0) {
4261 if (padPos
>= 0 || // Multiple pad specifiers
4262 (pos
+1) == pattern
.length()) { // Nothing after padEscape
4263 debug("Multiple pad specifiers")
4264 status
= U_MULTIPLE_PAD_SPECIFIERS
;
4265 syntaxError(pattern
,pos
,parseError
);
4269 pos
+= padEscape
.length();
4270 padChar
= pattern
.char32At(pos
);
4271 pos
+= U16_LENGTH(padChar
);
4273 } else if (pattern
.compare(pos
, minus
.length(), minus
) == 0) {
4274 affix
->append(kQuote
); // Encode minus
4275 affix
->append(kPatternMinus
);
4276 pos
+= minus
.length();
4278 } else if (pattern
.compare(pos
, plus
.length(), plus
) == 0) {
4279 affix
->append(kQuote
); // Encode plus
4280 affix
->append(kPatternPlus
);
4281 pos
+= plus
.length();
4284 // Unquoted, non-special characters fall through to here, as
4285 // well as other code which needs to append something to the
4288 pos
+= U16_LENGTH(ch
);
4290 case 3: // Prefix subpart, in quote
4291 case 4: // Suffix subpart, in quote
4292 // A quote within quotes indicates either the closing
4293 // quote or two quotes, which is a quote literal. That is,
4294 // we have the second quote in 'do' or 'don''t'.
4297 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
4298 affix
->append(kQuote
); // Encode quote
4299 // Fall through to append(ch)
4301 subpart
-= 2; // close quote
4306 pos
+= U16_LENGTH(ch
);
4311 if (sub0Limit
== 0) {
4312 sub0Limit
= pattern
.length();
4315 if (sub2Limit
== 0) {
4316 sub2Limit
= pattern
.length();
4319 /* Handle patterns with no '0' pattern character. These patterns
4320 * are legal, but must be recodified to make sense. "##.###" ->
4321 * "#0.###". ".###" -> ".0##".
4323 * We allow patterns of the form "####" to produce a zeroDigitCount
4324 * of zero (got that?); although this seems like it might make it
4325 * possible for format() to produce empty strings, format() checks
4326 * for this condition and outputs a zero digit in this situation.
4327 * Having a zeroDigitCount of zero yields a minimum integer digits
4328 * of zero, which allows proper round-trip patterns. We don't want
4329 * "#" to become "#0" when toPattern() is called (even though that's
4330 * what it really is, semantically).
4332 if (zeroDigitCount
== 0 && sigDigitCount
== 0 &&
4333 digitLeftCount
> 0 && decimalPos
>= 0) {
4334 // Handle "###.###" and "###." and ".###"
4337 ++n
; // Handle ".###"
4338 digitRightCount
= digitLeftCount
- n
;
4339 digitLeftCount
= n
- 1;
4343 // Do syntax checking on the digits, decimal points, and quotes.
4344 if ((decimalPos
< 0 && digitRightCount
> 0 && sigDigitCount
== 0) ||
4346 (sigDigitCount
> 0 ||
4347 decimalPos
< digitLeftCount
||
4348 decimalPos
> (digitLeftCount
+ zeroDigitCount
))) ||
4349 groupingCount
== 0 || groupingCount2
== 0 ||
4350 (sigDigitCount
> 0 && zeroDigitCount
> 0) ||
4352 { // subpart > 2 == unmatched quote
4353 debug("Syntax error")
4354 status
= U_PATTERN_SYNTAX_ERROR
;
4355 syntaxError(pattern
,pos
,parseError
);
4359 // Make sure pad is at legal position before or after affix.
4361 if (padPos
== start
) {
4362 padPos
= kPadBeforePrefix
;
4363 } else if (padPos
+2 == sub0Start
) {
4364 padPos
= kPadAfterPrefix
;
4365 } else if (padPos
== sub0Limit
) {
4366 padPos
= kPadBeforeSuffix
;
4367 } else if (padPos
+2 == sub2Limit
) {
4368 padPos
= kPadAfterSuffix
;
4370 // Illegal pad position
4371 debug("Illegal pad position")
4372 status
= U_ILLEGAL_PAD_POSITION
;
4373 syntaxError(pattern
,pos
,parseError
);
4379 delete fPosPrefixPattern
;
4380 delete fPosSuffixPattern
;
4381 delete fNegPrefixPattern
;
4382 delete fNegSuffixPattern
;
4383 fPosPrefixPattern
= new UnicodeString(prefix
);
4385 if (fPosPrefixPattern
== 0) {
4386 status
= U_MEMORY_ALLOCATION_ERROR
;
4389 fPosSuffixPattern
= new UnicodeString(suffix
);
4391 if (fPosSuffixPattern
== 0) {
4392 status
= U_MEMORY_ALLOCATION_ERROR
;
4393 delete fPosPrefixPattern
;
4396 fNegPrefixPattern
= 0;
4397 fNegSuffixPattern
= 0;
4399 fUseExponentialNotation
= (expDigits
>= 0);
4400 if (fUseExponentialNotation
) {
4401 fMinExponentDigits
= expDigits
;
4403 fExponentSignAlwaysShown
= expSignAlways
;
4404 int32_t digitTotalCount
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
4405 // The effectiveDecimalPos is the position the decimal is at or
4406 // would be at if there is no decimal. Note that if
4407 // decimalPos<0, then digitTotalCount == digitLeftCount +
4409 int32_t effectiveDecimalPos
= decimalPos
>= 0 ? decimalPos
: digitTotalCount
;
4410 UBool isSigDig
= (sigDigitCount
> 0);
4411 setSignificantDigitsUsed(isSigDig
);
4413 setMinimumSignificantDigits(sigDigitCount
);
4414 setMaximumSignificantDigits(sigDigitCount
+ digitRightCount
);
4416 int32_t minInt
= effectiveDecimalPos
- digitLeftCount
;
4417 setMinimumIntegerDigits(minInt
);
4418 setMaximumIntegerDigits(fUseExponentialNotation
4419 ? digitLeftCount
+ getMinimumIntegerDigits()
4420 : kDoubleIntegerDigits
);
4421 setMaximumFractionDigits(decimalPos
>= 0
4422 ? (digitTotalCount
- decimalPos
) : 0);
4423 setMinimumFractionDigits(decimalPos
>= 0
4424 ? (digitLeftCount
+ zeroDigitCount
- decimalPos
) : 0);
4426 setGroupingUsed(groupingCount
> 0);
4427 fGroupingSize
= (groupingCount
> 0) ? groupingCount
: 0;
4428 fGroupingSize2
= (groupingCount2
> 0 && groupingCount2
!= groupingCount
)
4429 ? groupingCount2
: 0;
4430 setMultiplier(multiplier
);
4431 setDecimalSeparatorAlwaysShown(decimalPos
== 0
4432 || decimalPos
== digitTotalCount
);
4434 fPadPosition
= (EPadPosition
) padPos
;
4435 // To compute the format width, first set up sub0Limit -
4436 // sub0Start. Add in prefix/suffix length later.
4438 // fFormatWidth = prefix.length() + suffix.length() +
4439 // sub0Limit - sub0Start;
4440 fFormatWidth
= sub0Limit
- sub0Start
;
4445 if (roundingPos
>= 0) {
4446 roundingInc
.setDecimalAt(effectiveDecimalPos
- roundingPos
);
4447 if (fRoundingIncrement
!= NULL
) {
4448 *fRoundingIncrement
= roundingInc
;
4450 fRoundingIncrement
= new DigitList(roundingInc
);
4452 if (fRoundingIncrement
== NULL
) {
4453 status
= U_MEMORY_ALLOCATION_ERROR
;
4454 delete fPosPrefixPattern
;
4455 delete fPosSuffixPattern
;
4459 fRoundingMode
= kRoundHalfEven
;
4461 setRoundingIncrement(0.0);
4464 fNegPrefixPattern
= new UnicodeString(prefix
);
4466 if (fNegPrefixPattern
== 0) {
4467 status
= U_MEMORY_ALLOCATION_ERROR
;
4470 fNegSuffixPattern
= new UnicodeString(suffix
);
4472 if (fNegSuffixPattern
== 0) {
4473 delete fNegPrefixPattern
;
4474 status
= U_MEMORY_ALLOCATION_ERROR
;
4480 if (pattern
.length() == 0) {
4481 delete fNegPrefixPattern
;
4482 delete fNegSuffixPattern
;
4483 fNegPrefixPattern
= NULL
;
4484 fNegSuffixPattern
= NULL
;
4485 if (fPosPrefixPattern
!= NULL
) {
4486 fPosPrefixPattern
->remove();
4488 fPosPrefixPattern
= new UnicodeString();
4490 if (fPosPrefixPattern
== 0) {
4491 status
= U_MEMORY_ALLOCATION_ERROR
;
4495 if (fPosSuffixPattern
!= NULL
) {
4496 fPosSuffixPattern
->remove();
4498 fPosSuffixPattern
= new UnicodeString();
4500 if (fPosSuffixPattern
== 0) {
4501 delete fPosPrefixPattern
;
4502 status
= U_MEMORY_ALLOCATION_ERROR
;
4507 setMinimumIntegerDigits(0);
4508 setMaximumIntegerDigits(kDoubleIntegerDigits
);
4509 setMinimumFractionDigits(0);
4510 setMaximumFractionDigits(kDoubleFractionDigits
);
4512 fUseExponentialNotation
= FALSE
;
4513 fCurrencySignCount
= 0;
4514 setGroupingUsed(FALSE
);
4518 setDecimalSeparatorAlwaysShown(FALSE
);
4520 setRoundingIncrement(0.0);
4523 // If there was no negative pattern, or if the negative pattern is
4524 // identical to the positive pattern, then prepend the minus sign to the
4525 // positive pattern to form the negative pattern.
4526 if (fNegPrefixPattern
== NULL
||
4527 (*fNegPrefixPattern
== *fPosPrefixPattern
4528 && *fNegSuffixPattern
== *fPosSuffixPattern
)) {
4529 _copy_us_ptr(&fNegSuffixPattern
, fPosSuffixPattern
);
4530 if (fNegPrefixPattern
== NULL
) {
4531 fNegPrefixPattern
= new UnicodeString();
4533 if (fNegPrefixPattern
== 0) {
4534 status
= U_MEMORY_ALLOCATION_ERROR
;
4538 fNegPrefixPattern
->remove();
4540 fNegPrefixPattern
->append(kQuote
).append(kPatternMinus
)
4541 .append(*fPosPrefixPattern
);
4545 s
.append("\"").append(pattern
).append("\"->");
4550 fFormatPattern
= pattern
;
4555 DecimalFormat::expandAffixAdjustWidth(const UnicodeString
* pluralCount
) {
4556 expandAffixes(pluralCount
);
4557 if (fFormatWidth
> 0) {
4558 // Finish computing format width (see above)
4559 // TODO: how to handle fFormatWidth,
4560 // need to save in f(Plural)AffixesForCurrecy?
4561 fFormatWidth
+= fPositivePrefix
.length() + fPositiveSuffix
.length();
4567 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
4569 UParseError
& parseError
,
4572 // do the following re-set first. since they change private data by
4573 // apply pattern again.
4574 if (pattern
.indexOf(kCurrencySign
) != -1) {
4575 if (fCurrencyPluralInfo
== NULL
) {
4576 // initialize currencyPluralInfo if needed
4577 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
4579 if (fAffixPatternsForCurrency
== NULL
) {
4580 setupCurrencyAffixPatterns(status
);
4582 if (pattern
.indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
4583 // only setup the affixes of the current pattern.
4584 setupCurrencyAffixes(pattern
, TRUE
, FALSE
, status
);
4587 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
4588 expandAffixAdjustWidth(NULL
);
4593 DecimalFormat::applyPatternInternally(const UnicodeString
& pluralCount
,
4594 const UnicodeString
& pattern
,
4596 UParseError
& parseError
,
4597 UErrorCode
& status
) {
4598 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
4599 expandAffixAdjustWidth(&pluralCount
);
4604 * Sets the maximum number of digits allowed in the integer portion of a
4605 * number. This override limits the integer digit count to 309.
4606 * @see NumberFormat#setMaximumIntegerDigits
4608 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
4609 NumberFormat::setMaximumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
4613 * Sets the minimum number of digits allowed in the integer portion of a
4614 * number. This override limits the integer digit count to 309.
4615 * @see NumberFormat#setMinimumIntegerDigits
4617 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
4618 NumberFormat::setMinimumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
4622 * Sets the maximum number of digits allowed in the fraction portion of a
4623 * number. This override limits the fraction digit count to 340.
4624 * @see NumberFormat#setMaximumFractionDigits
4626 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
4627 NumberFormat::setMaximumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
4631 * Sets the minimum number of digits allowed in the fraction portion of a
4632 * number. This override limits the fraction digit count to 340.
4633 * @see NumberFormat#setMinimumFractionDigits
4635 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
4636 NumberFormat::setMinimumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
4639 int32_t DecimalFormat::getMinimumSignificantDigits() const {
4640 return fMinSignificantDigits
;
4643 int32_t DecimalFormat::getMaximumSignificantDigits() const {
4644 return fMaxSignificantDigits
;
4647 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
4651 // pin max sig dig to >= min
4652 int32_t max
= _max(fMaxSignificantDigits
, min
);
4653 fMinSignificantDigits
= min
;
4654 fMaxSignificantDigits
= max
;
4657 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
4661 // pin min sig dig to 1..max
4662 U_ASSERT(fMinSignificantDigits
>= 1);
4663 int32_t min
= _min(fMinSignificantDigits
, max
);
4664 fMinSignificantDigits
= min
;
4665 fMaxSignificantDigits
= max
;
4668 UBool
DecimalFormat::areSignificantDigitsUsed() const {
4669 return fUseSignificantDigits
;
4672 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
4673 fUseSignificantDigits
= useSignificantDigits
;
4676 void DecimalFormat::setCurrencyInternally(const UChar
* theCurrency
,
4678 // If we are a currency format, then modify our affixes to
4679 // encode the currency symbol for the given currency in our
4680 // locale, and adjust the decimal digits and rounding for the
4683 // Note: The code is ordered so that this object is *not changed*
4684 // until we are sure we are going to succeed.
4686 // NULL or empty currency is *legal* and indicates no currency.
4687 UBool isCurr
= (theCurrency
&& *theCurrency
);
4689 double rounding
= 0.0;
4691 if (fCurrencySignCount
> fgCurrencySignCountZero
&& isCurr
) {
4692 rounding
= ucurr_getRoundingIncrement(theCurrency
, &ec
);
4693 frac
= ucurr_getDefaultFractionDigits(theCurrency
, &ec
);
4696 NumberFormat::setCurrency(theCurrency
, ec
);
4697 if (U_FAILURE(ec
)) return;
4699 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
4700 // NULL or empty currency is *legal* and indicates no currency.
4702 setRoundingIncrement(rounding
);
4703 setMinimumFractionDigits(frac
);
4704 setMaximumFractionDigits(frac
);
4706 expandAffixes(NULL
);
4710 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
4711 // set the currency before compute affixes to get the right currency names
4712 NumberFormat::setCurrency(theCurrency
, ec
);
4713 if (fFormatPattern
.indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
4714 UnicodeString savedPtn
= fFormatPattern
;
4715 setupCurrencyAffixes(fFormatPattern
, TRUE
, TRUE
, ec
);
4716 UParseError parseErr
;
4717 applyPattern(savedPtn
, FALSE
, parseErr
, ec
);
4719 // set the currency after apply pattern to get the correct rounding/fraction
4720 setCurrencyInternally(theCurrency
, ec
);
4723 // Deprecated variant with no UErrorCode parameter
4724 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
4725 UErrorCode ec
= U_ZERO_ERROR
;
4726 setCurrency(theCurrency
, ec
);
4729 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
4730 if (fSymbols
== NULL
) {
4731 ec
= U_MEMORY_ALLOCATION_ERROR
;
4735 const UChar
* c
= getCurrency();
4737 const UnicodeString
&intl
=
4738 fSymbols
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
4739 c
= intl
.getBuffer(); // ok for intl to go out of scope
4741 u_strncpy(result
, c
, 3);
4746 * Return the number of fraction digits to display, or the total
4747 * number of digits for significant digit formats and exponential
4751 DecimalFormat::precision() const {
4752 if (areSignificantDigitsUsed()) {
4753 return getMaximumSignificantDigits();
4754 } else if (fUseExponentialNotation
) {
4755 return getMinimumIntegerDigits() + getMaximumFractionDigits();
4757 return getMaximumFractionDigits();
4762 // TODO: template algorithm
4764 DecimalFormat::initHashForAffix(UErrorCode
& status
) {
4765 if ( U_FAILURE(status
) ) {
4769 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
4770 status
= U_MEMORY_ALLOCATION_ERROR
;
4773 if ( U_FAILURE(status
) ) {
4777 hTable
->setValueComparator(decimfmtAffixValueComparator
);
4782 DecimalFormat::initHashForAffixPattern(UErrorCode
& status
) {
4783 if ( U_FAILURE(status
) ) {
4787 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
4788 status
= U_MEMORY_ALLOCATION_ERROR
;
4791 if ( U_FAILURE(status
) ) {
4795 hTable
->setValueComparator(decimfmtAffixPatternValueComparator
);
4800 DecimalFormat::deleteHashForAffix(Hashtable
*& table
)
4802 if ( table
== NULL
) {
4806 const UHashElement
* element
= NULL
;
4807 while ( (element
= table
->nextElement(pos
)) != NULL
) {
4808 const UHashTok valueTok
= element
->value
;
4809 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
4819 DecimalFormat::deleteHashForAffixPattern()
4821 if ( fAffixPatternsForCurrency
== NULL
) {
4825 const UHashElement
* element
= NULL
;
4826 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
4827 const UHashTok valueTok
= element
->value
;
4828 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
4831 delete fAffixPatternsForCurrency
;
4832 fAffixPatternsForCurrency
= NULL
;
4837 DecimalFormat::copyHashForAffixPattern(const Hashtable
* source
,
4839 UErrorCode
& status
) {
4840 if ( U_FAILURE(status
) ) {
4844 const UHashElement
* element
= NULL
;
4846 while ( (element
= source
->nextElement(pos
)) != NULL
) {
4847 const UHashTok keyTok
= element
->key
;
4848 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
4849 const UHashTok valueTok
= element
->value
;
4850 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
4851 AffixPatternsForCurrency
* copy
= new AffixPatternsForCurrency(
4852 value
->negPrefixPatternForCurrency
,
4853 value
->negSuffixPatternForCurrency
,
4854 value
->posPrefixPatternForCurrency
,
4855 value
->posSuffixPatternForCurrency
,
4856 value
->patternType
);
4857 target
->put(UnicodeString(*key
), copy
, status
);
4858 if ( U_FAILURE(status
) ) {
4868 DecimalFormat::copyHashForAffix(const Hashtable
* source
,
4870 UErrorCode
& status
) {
4871 if ( U_FAILURE(status
) ) {
4875 const UHashElement
* element
= NULL
;
4877 while ( (element
= source
->nextElement(pos
)) != NULL
) {
4878 const UHashTok keyTok
= element
->key
;
4879 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
4881 const UHashTok valueTok
= element
->value
;
4882 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
4883 AffixesForCurrency
* copy
= new AffixesForCurrency(
4884 value
->negPrefixForCurrency
,
4885 value
->negSuffixForCurrency
,
4886 value
->posPrefixForCurrency
,
4887 value
->posSuffixForCurrency
);
4888 target
->put(UnicodeString(*key
), copy
, status
);
4889 if ( U_FAILURE(status
) ) {
4898 #endif /* #if !UCONFIG_NO_FORMATTING */