2 *******************************************************************************
3 * Copyright (C) 1997-2015, 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"
73 #include "plurrule_impl.h"
74 #include "decimalformatpattern.h"
75 #include "fmtableimp.h"
78 * On certain platforms, round is a macro defined in math.h
79 * This undefine is to avoid conflict between the macro and
80 * the function defined below.
91 static void _debugout(const char *f
, int l
, const UnicodeString
& s
) {
93 s
.extract((int32_t) 0, s
.length(), buf
, "utf-8");
94 printf("%s:%d: %s\n", f
,l
, buf
);
96 #define debugout(x) _debugout(__FILE__,__LINE__,x)
97 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
98 static const UnicodeString
dbg_null("<NULL>","");
99 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
107 /* == Fastpath calculation. ==
109 #if UCONFIG_FORMAT_FASTPATHS_49
110 inline DecimalFormatInternal
& internalData(uint8_t *reserved
) {
111 return *reinterpret_cast<DecimalFormatInternal
*>(reserved
);
113 inline const DecimalFormatInternal
& internalData(const uint8_t *reserved
) {
114 return *reinterpret_cast<const DecimalFormatInternal
*>(reserved
);
119 /* For currency parsing purose,
120 * Need to remember all prefix patterns and suffix patterns of
121 * every currency format pattern,
122 * including the pattern of default currecny style
123 * and plural currency style. And the patterns are set through applyPattern.
125 struct AffixPatternsForCurrency
: public UMemory
{
126 // negative prefix pattern
127 UnicodeString negPrefixPatternForCurrency
;
128 // negative suffix pattern
129 UnicodeString negSuffixPatternForCurrency
;
130 // positive prefix pattern
131 UnicodeString posPrefixPatternForCurrency
;
132 // positive suffix pattern
133 UnicodeString posSuffixPatternForCurrency
;
136 AffixPatternsForCurrency(const UnicodeString
& negPrefix
,
137 const UnicodeString
& negSuffix
,
138 const UnicodeString
& posPrefix
,
139 const UnicodeString
& posSuffix
,
141 negPrefixPatternForCurrency
= negPrefix
;
142 negSuffixPatternForCurrency
= negSuffix
;
143 posPrefixPatternForCurrency
= posPrefix
;
144 posSuffixPatternForCurrency
= posSuffix
;
149 debugout( UnicodeString("AffixPatternsForCurrency( -=\"") +
150 negPrefixPatternForCurrency
+ (UnicodeString
)"\"/\"" +
151 negSuffixPatternForCurrency
+ (UnicodeString
)"\" +=\"" +
152 posPrefixPatternForCurrency
+ (UnicodeString
)"\"/\"" +
153 posSuffixPatternForCurrency
+ (UnicodeString
)"\" )");
158 /* affix for currency formatting when the currency sign in the pattern
159 * equals to 3, such as the pattern contains 3 currency sign or
160 * the formatter style is currency plural format style.
162 struct AffixesForCurrency
: public UMemory
{
164 UnicodeString negPrefixForCurrency
;
166 UnicodeString negSuffixForCurrency
;
168 UnicodeString posPrefixForCurrency
;
170 UnicodeString posSuffixForCurrency
;
174 AffixesForCurrency(const UnicodeString
& negPrefix
,
175 const UnicodeString
& negSuffix
,
176 const UnicodeString
& posPrefix
,
177 const UnicodeString
& posSuffix
) {
178 negPrefixForCurrency
= negPrefix
;
179 negSuffixForCurrency
= negSuffix
;
180 posPrefixForCurrency
= posPrefix
;
181 posSuffixForCurrency
= posSuffix
;
185 debugout( UnicodeString("AffixesForCurrency( -=\"") +
186 negPrefixForCurrency
+ (UnicodeString
)"\"/\"" +
187 negSuffixForCurrency
+ (UnicodeString
)"\" +=\"" +
188 posPrefixForCurrency
+ (UnicodeString
)"\"/\"" +
189 posSuffixForCurrency
+ (UnicodeString
)"\" )");
199 static UBool U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
);
204 static UBool U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
);
208 U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
) {
209 const AffixesForCurrency
* affix_1
=
210 (AffixesForCurrency
*)val1
.pointer
;
211 const AffixesForCurrency
* affix_2
=
212 (AffixesForCurrency
*)val2
.pointer
;
213 return affix_1
->negPrefixForCurrency
== affix_2
->negPrefixForCurrency
&&
214 affix_1
->negSuffixForCurrency
== affix_2
->negSuffixForCurrency
&&
215 affix_1
->posPrefixForCurrency
== affix_2
->posPrefixForCurrency
&&
216 affix_1
->posSuffixForCurrency
== affix_2
->posSuffixForCurrency
;
221 U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
) {
222 const AffixPatternsForCurrency
* affix_1
=
223 (AffixPatternsForCurrency
*)val1
.pointer
;
224 const AffixPatternsForCurrency
* affix_2
=
225 (AffixPatternsForCurrency
*)val2
.pointer
;
226 return affix_1
->negPrefixPatternForCurrency
==
227 affix_2
->negPrefixPatternForCurrency
&&
228 affix_1
->negSuffixPatternForCurrency
==
229 affix_2
->negSuffixPatternForCurrency
&&
230 affix_1
->posPrefixPatternForCurrency
==
231 affix_2
->posPrefixPatternForCurrency
&&
232 affix_1
->posSuffixPatternForCurrency
==
233 affix_2
->posSuffixPatternForCurrency
&&
234 affix_1
->patternType
== affix_2
->patternType
;
242 // *****************************************************************************
243 // class DecimalFormat
244 // *****************************************************************************
246 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat
)
248 // Constants for characters used in programmatic (unlocalized) patterns.
249 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
250 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
251 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
252 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
253 #define kPatternPerMill ((UChar)0x2030)
254 #define kPatternPercent ((UChar)0x0025) /*'%'*/
255 #define kPatternDigit ((UChar)0x0023) /*'#'*/
256 #define kPatternSeparator ((UChar)0x003B) /*';'*/
257 #define kPatternExponent ((UChar)0x0045) /*'E'*/
258 #define kPatternPlus ((UChar)0x002B) /*'+'*/
259 #define kPatternMinus ((UChar)0x002D) /*'-'*/
260 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
261 #define kQuote ((UChar)0x0027) /*'\''*/
263 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
264 * is used in patterns and substitued with either the currency symbol,
265 * or if it is doubled, with the international currency symbol. If the
266 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
267 * replaced with the monetary decimal separator.
269 #define kCurrencySign ((UChar)0x00A4)
270 #define kDefaultPad ((UChar)0x0020) /* */
272 const int32_t DecimalFormat::kDoubleIntegerDigits
= 309;
273 const int32_t DecimalFormat::kDoubleFractionDigits
= 340;
275 const int32_t DecimalFormat::kMaxScientificIntegerDigits
= 8;
278 * These are the tags we expect to see in normal resource bundle files associated
281 const char DecimalFormat::fgNumberPatterns
[]="NumberPatterns"; // Deprecated - not used
282 static const char fgNumberElements
[]="NumberElements";
283 static const char fgLatn
[]="latn";
284 static const char fgPatterns
[]="patterns";
285 static const char fgDecimalFormat
[]="decimalFormat";
286 static const char fgCurrencyFormat
[]="currencyFormat";
288 static const UChar fgTripleCurrencySign
[] = {0xA4, 0xA4, 0xA4, 0};
290 inline int32_t _min(int32_t a
, int32_t b
) { return (a
<b
) ? a
: b
; }
291 inline int32_t _max(int32_t a
, int32_t b
) { return (a
<b
) ? b
: a
; }
293 static void copyString(const UnicodeString
& src
, UBool isBogus
, UnicodeString
*& dest
, UErrorCode
&status
) {
294 if (U_FAILURE(status
)) {
304 dest
= new UnicodeString(src
);
306 status
= U_MEMORY_ALLOCATION_ERROR
;
314 //------------------------------------------------------------------------------
315 // Constructs a DecimalFormat instance in the default locale.
317 DecimalFormat::DecimalFormat(UErrorCode
& status
) {
319 UParseError parseError
;
320 construct(status
, parseError
);
323 //------------------------------------------------------------------------------
324 // Constructs a DecimalFormat instance with the specified number format
325 // pattern in the default locale.
327 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
328 UErrorCode
& status
) {
330 UParseError parseError
;
331 construct(status
, parseError
, &pattern
);
334 //------------------------------------------------------------------------------
335 // Constructs a DecimalFormat instance with the specified number format
336 // pattern and the number format symbols in the default locale. The
337 // created instance owns the symbols.
339 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
340 DecimalFormatSymbols
* symbolsToAdopt
,
341 UErrorCode
& status
) {
343 UParseError parseError
;
344 if (symbolsToAdopt
== NULL
)
345 status
= U_ILLEGAL_ARGUMENT_ERROR
;
346 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
349 DecimalFormat::DecimalFormat( const UnicodeString
& pattern
,
350 DecimalFormatSymbols
* symbolsToAdopt
,
351 UParseError
& parseErr
,
352 UErrorCode
& status
) {
354 if (symbolsToAdopt
== NULL
)
355 status
= U_ILLEGAL_ARGUMENT_ERROR
;
356 construct(status
,parseErr
, &pattern
, symbolsToAdopt
);
359 //------------------------------------------------------------------------------
360 // Constructs a DecimalFormat instance with the specified number format
361 // pattern and the number format symbols in the default locale. The
362 // created instance owns the clone of the symbols.
364 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
365 const DecimalFormatSymbols
& symbols
,
366 UErrorCode
& status
) {
368 UParseError parseError
;
369 construct(status
, parseError
, &pattern
, new DecimalFormatSymbols(symbols
));
372 //------------------------------------------------------------------------------
373 // Constructs a DecimalFormat instance with the specified number format
374 // pattern, the number format symbols, and the number format style.
375 // The created instance owns the clone of the symbols.
377 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
378 DecimalFormatSymbols
* symbolsToAdopt
,
379 UNumberFormatStyle style
,
380 UErrorCode
& status
) {
383 UParseError parseError
;
384 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
387 //-----------------------------------------------------------------------------
388 // Common DecimalFormat initialization.
389 // Put all fields of an uninitialized object into a known state.
390 // Common code, shared by all constructors.
391 // Can not fail. Leave the object in good enough shape that the destructor
392 // or assignment operator can run successfully.
394 DecimalFormat::init() {
395 fPosPrefixPattern
= 0;
396 fPosSuffixPattern
= 0;
397 fNegPrefixPattern
= 0;
398 fNegSuffixPattern
= 0;
404 fDecimalSeparatorAlwaysShown
= FALSE
;
406 fUseSignificantDigits
= FALSE
;
407 fMinSignificantDigits
= 1;
408 fMaxSignificantDigits
= 6;
409 fUseExponentialNotation
= FALSE
;
410 fMinExponentDigits
= 0;
411 fExponentSignAlwaysShown
= FALSE
;
413 fRoundingIncrement
= 0;
414 fRoundingMode
= kRoundHalfEven
;
417 fPadPosition
= kPadBeforePrefix
;
418 fStyle
= UNUM_DECIMAL
;
419 fCurrencySignCount
= fgCurrencySignCountZero
;
420 fAffixPatternsForCurrency
= NULL
;
421 fAffixesForCurrency
= NULL
;
422 fPluralAffixesForCurrency
= NULL
;
423 fCurrencyPluralInfo
= NULL
;
424 fCurrencyUsage
= UCURR_USAGE_STANDARD
;
425 #if UCONFIG_HAVE_PARSEALLINPUT
426 fParseAllInput
= UNUM_MAYBE
;
429 #if UCONFIG_FORMAT_FASTPATHS_49
430 DecimalFormatInternal
&data
= internalData(fReserved
);
431 data
.fFastFormatStatus
=kFastpathUNKNOWN
; // don't try to calculate the fastpath until later.
432 data
.fFastParseStatus
=kFastpathUNKNOWN
; // don't try to calculate the fastpath until later.
437 //------------------------------------------------------------------------------
438 // Constructs a DecimalFormat instance with the specified number format
439 // pattern and the number format symbols in the desired locale. The
440 // created instance owns the symbols.
443 DecimalFormat::construct(UErrorCode
& status
,
444 UParseError
& parseErr
,
445 const UnicodeString
* pattern
,
446 DecimalFormatSymbols
* symbolsToAdopt
)
448 fSymbols
= symbolsToAdopt
; // Do this BEFORE aborting on status failure!!!
449 fRoundingIncrement
= NULL
;
450 fRoundingMode
= kRoundHalfEven
;
451 fPad
= kPatternPadEscape
;
452 fPadPosition
= kPadBeforePrefix
;
453 if (U_FAILURE(status
))
456 fPosPrefixPattern
= fPosSuffixPattern
= NULL
;
457 fNegPrefixPattern
= fNegSuffixPattern
= NULL
;
461 fDecimalSeparatorAlwaysShown
= FALSE
;
462 fUseExponentialNotation
= FALSE
;
463 fMinExponentDigits
= 0;
465 if (fSymbols
== NULL
)
467 fSymbols
= new DecimalFormatSymbols(Locale::getDefault(), status
);
469 status
= U_MEMORY_ALLOCATION_ERROR
;
473 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
474 if (U_FAILURE(status
)) {
477 UErrorCode nsStatus
= U_ZERO_ERROR
;
478 NumberingSystem
*ns
= NumberingSystem::createInstance(nsStatus
);
479 if (U_FAILURE(nsStatus
)) {
485 // Uses the default locale's number format pattern if there isn't
490 UResourceBundle
*top
= ures_open(NULL
, Locale::getDefault().getName(), &status
);
492 UResourceBundle
*resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, NULL
, &status
);
493 resource
= ures_getByKeyWithFallback(resource
, ns
->getName(), resource
, &status
);
494 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
495 const UChar
*resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
496 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(fgLatn
,ns
->getName())) {
497 status
= U_ZERO_ERROR
;
498 resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, resource
, &status
);
499 resource
= ures_getByKeyWithFallback(resource
, fgLatn
, resource
, &status
);
500 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
501 resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
503 str
.setTo(TRUE
, resStr
, len
);
505 ures_close(resource
);
511 if (U_FAILURE(status
))
516 if (pattern
->indexOf((UChar
)kCurrencySign
) >= 0) {
517 // If it looks like we are going to use a currency pattern
518 // then do the time consuming lookup.
519 setCurrencyForSymbols();
521 setCurrencyInternally(NULL
, status
);
524 const UnicodeString
* patternUsed
;
525 UnicodeString currencyPluralPatternForOther
;
527 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
528 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
529 if (U_FAILURE(status
)) {
533 // the pattern used in format is not fixed until formatting,
534 // in which, the number is known and
535 // will be used to pick the right pattern based on plural count.
536 // Here, set the pattern as the pattern of plural count == "other".
537 // For most locale, the patterns are probably the same for all
538 // plural count. If not, the right pattern need to be re-applied
540 fCurrencyPluralInfo
->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther
);
541 patternUsed
= ¤cyPluralPatternForOther
;
543 setCurrencyForSymbols();
546 patternUsed
= pattern
;
549 if (patternUsed
->indexOf(kCurrencySign
) != -1) {
550 // initialize for currency, not only for plural format,
551 // but also for mix parsing
552 if (fCurrencyPluralInfo
== NULL
) {
553 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
554 if (U_FAILURE(status
)) {
558 // need it for mix parsing
559 setupCurrencyAffixPatterns(status
);
560 // expanded affixes for plural names
561 if (patternUsed
->indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
562 setupCurrencyAffixes(*patternUsed
, TRUE
, TRUE
, status
);
566 applyPatternWithoutExpandAffix(*patternUsed
,FALSE
, parseErr
, status
);
569 if (fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
570 expandAffixAdjustWidth(NULL
);
573 // If it was a currency format, apply the appropriate rounding by
574 // resetting the currency. NOTE: this copies fCurrency on top of itself.
575 if (fCurrencySignCount
!= fgCurrencySignCountZero
) {
576 setCurrencyInternally(getCurrency(), status
);
578 #if UCONFIG_FORMAT_FASTPATHS_49
579 DecimalFormatInternal
&data
= internalData(fReserved
);
580 data
.fFastFormatStatus
= kFastpathNO
; // allow it to be calculated
581 data
.fFastParseStatus
= kFastpathNO
; // allow it to be calculated
588 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode
& status
) {
589 if (U_FAILURE(status
)) {
592 UParseError parseErr
;
593 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
594 if (U_FAILURE(status
)) {
598 NumberingSystem
*ns
= NumberingSystem::createInstance(fSymbols
->getLocale(),status
);
599 if (U_FAILURE(status
)) {
603 // Save the default currency patterns of this locale.
604 // Here, chose onlyApplyPatternWithoutExpandAffix without
605 // expanding the affix patterns into affixes.
606 UnicodeString currencyPattern
;
607 UErrorCode error
= U_ZERO_ERROR
;
609 UResourceBundle
*resource
= ures_open(NULL
, fSymbols
->getLocale().getName(), &error
);
610 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, fgNumberElements
, NULL
, &error
);
611 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &error
);
612 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
614 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
615 if ( error
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(ns
->getName(),fgLatn
)) {
616 error
= U_ZERO_ERROR
;
617 resource
= ures_getByKeyWithFallback(numElements
, fgLatn
, resource
, &error
);
618 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
619 patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
621 ures_close(numElements
);
622 ures_close(resource
);
625 if (U_SUCCESS(error
)) {
626 applyPatternWithoutExpandAffix(UnicodeString(patResStr
, patLen
), false,
628 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
634 fAffixPatternsForCurrency
->put(UNICODE_STRING("default", 7), affixPtn
, status
);
637 // save the unique currency plural patterns of this locale.
638 Hashtable
* pluralPtn
= fCurrencyPluralInfo
->fPluralCountToCurrencyUnitPattern
;
639 const UHashElement
* element
= NULL
;
640 int32_t pos
= UHASH_FIRST
;
641 Hashtable pluralPatternSet
;
642 while ((element
= pluralPtn
->nextElement(pos
)) != NULL
) {
643 const UHashTok valueTok
= element
->value
;
644 const UnicodeString
* value
= (UnicodeString
*)valueTok
.pointer
;
645 const UHashTok keyTok
= element
->key
;
646 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
647 if (pluralPatternSet
.geti(*value
) != 1) {
648 pluralPatternSet
.puti(*value
, 1, status
);
649 applyPatternWithoutExpandAffix(*value
, false, parseErr
, status
);
650 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
656 fAffixPatternsForCurrency
->put(*key
, affixPtn
, status
);
663 DecimalFormat::setupCurrencyAffixes(const UnicodeString
& pattern
,
664 UBool setupForCurrentPattern
,
665 UBool setupForPluralPattern
,
666 UErrorCode
& status
) {
667 if (U_FAILURE(status
)) {
670 UParseError parseErr
;
671 if (setupForCurrentPattern
) {
672 if (fAffixesForCurrency
) {
673 deleteHashForAffix(fAffixesForCurrency
);
675 fAffixesForCurrency
= initHashForAffix(status
);
676 if (U_SUCCESS(status
)) {
677 applyPatternWithoutExpandAffix(pattern
, false, parseErr
, status
);
678 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
679 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
680 if (U_SUCCESS(status
)) {
681 const UnicodeString
* pluralCount
;
682 while ((pluralCount
= keywords
->snext(status
)) != NULL
) {
683 if ( U_SUCCESS(status
) ) {
684 expandAffixAdjustWidth(pluralCount
);
685 AffixesForCurrency
* affix
= new AffixesForCurrency(
686 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
687 fAffixesForCurrency
->put(*pluralCount
, affix
, status
);
695 if (U_FAILURE(status
)) {
699 if (setupForPluralPattern
) {
700 if (fPluralAffixesForCurrency
) {
701 deleteHashForAffix(fPluralAffixesForCurrency
);
703 fPluralAffixesForCurrency
= initHashForAffix(status
);
704 if (U_SUCCESS(status
)) {
705 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
706 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
707 if (U_SUCCESS(status
)) {
708 const UnicodeString
* pluralCount
;
709 while ((pluralCount
= keywords
->snext(status
)) != NULL
) {
710 if ( U_SUCCESS(status
) ) {
712 fCurrencyPluralInfo
->getCurrencyPluralPattern(*pluralCount
, ptn
);
713 applyPatternInternally(*pluralCount
, ptn
, false, parseErr
, status
);
714 AffixesForCurrency
* affix
= new AffixesForCurrency(
715 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
716 fPluralAffixesForCurrency
->put(*pluralCount
, affix
, status
);
726 //------------------------------------------------------------------------------
728 DecimalFormat::~DecimalFormat()
730 delete fPosPrefixPattern
;
731 delete fPosSuffixPattern
;
732 delete fNegPrefixPattern
;
733 delete fNegSuffixPattern
;
734 delete fCurrencyChoice
;
737 delete fRoundingIncrement
;
738 deleteHashForAffixPattern();
739 deleteHashForAffix(fAffixesForCurrency
);
740 deleteHashForAffix(fPluralAffixesForCurrency
);
741 delete fCurrencyPluralInfo
;
744 //------------------------------------------------------------------------------
747 DecimalFormat::DecimalFormat(const DecimalFormat
&source
) :
748 NumberFormat(source
) {
753 //------------------------------------------------------------------------------
754 // assignment operator
757 static void _copy_ptr(T
** pdest
, const T
* source
) {
758 if (source
== NULL
) {
761 } else if (*pdest
== NULL
) {
762 *pdest
= new T(*source
);
769 static void _clone_ptr(T
** pdest
, const T
* source
) {
771 if (source
== NULL
) {
774 *pdest
= static_cast<T
*>(source
->clone());
779 DecimalFormat::operator=(const DecimalFormat
& rhs
)
782 UErrorCode status
= U_ZERO_ERROR
;
783 NumberFormat::operator=(rhs
);
784 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
785 fPositivePrefix
= rhs
.fPositivePrefix
;
786 fPositiveSuffix
= rhs
.fPositiveSuffix
;
787 fNegativePrefix
= rhs
.fNegativePrefix
;
788 fNegativeSuffix
= rhs
.fNegativeSuffix
;
789 _copy_ptr(&fPosPrefixPattern
, rhs
.fPosPrefixPattern
);
790 _copy_ptr(&fPosSuffixPattern
, rhs
.fPosSuffixPattern
);
791 _copy_ptr(&fNegPrefixPattern
, rhs
.fNegPrefixPattern
);
792 _copy_ptr(&fNegSuffixPattern
, rhs
.fNegSuffixPattern
);
793 _clone_ptr(&fCurrencyChoice
, rhs
.fCurrencyChoice
);
794 setRoundingIncrement(rhs
.getRoundingIncrement());
795 fRoundingMode
= rhs
.fRoundingMode
;
796 setMultiplier(rhs
.getMultiplier());
797 fGroupingSize
= rhs
.fGroupingSize
;
798 fGroupingSize2
= rhs
.fGroupingSize2
;
799 fDecimalSeparatorAlwaysShown
= rhs
.fDecimalSeparatorAlwaysShown
;
800 _copy_ptr(&fSymbols
, rhs
.fSymbols
);
801 fUseExponentialNotation
= rhs
.fUseExponentialNotation
;
802 fExponentSignAlwaysShown
= rhs
.fExponentSignAlwaysShown
;
803 fBoolFlags
= rhs
.fBoolFlags
;
804 /*Bertrand A. D. Update 98.03.17*/
805 fCurrencySignCount
= rhs
.fCurrencySignCount
;
807 fMinExponentDigits
= rhs
.fMinExponentDigits
;
810 fFormatWidth
= rhs
.fFormatWidth
;
812 fPadPosition
= rhs
.fPadPosition
;
814 fMinSignificantDigits
= rhs
.fMinSignificantDigits
;
815 fMaxSignificantDigits
= rhs
.fMaxSignificantDigits
;
816 fUseSignificantDigits
= rhs
.fUseSignificantDigits
;
817 fFormatPattern
= rhs
.fFormatPattern
;
818 fCurrencyUsage
= rhs
.fCurrencyUsage
;
820 _clone_ptr(&fCurrencyPluralInfo
, rhs
.fCurrencyPluralInfo
);
821 deleteHashForAffixPattern();
822 if (rhs
.fAffixPatternsForCurrency
) {
823 UErrorCode status
= U_ZERO_ERROR
;
824 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
825 copyHashForAffixPattern(rhs
.fAffixPatternsForCurrency
,
826 fAffixPatternsForCurrency
, status
);
828 deleteHashForAffix(fAffixesForCurrency
);
829 if (rhs
.fAffixesForCurrency
) {
830 UErrorCode status
= U_ZERO_ERROR
;
831 fAffixesForCurrency
= initHashForAffixPattern(status
);
832 copyHashForAffix(rhs
.fAffixesForCurrency
, fAffixesForCurrency
, status
);
834 deleteHashForAffix(fPluralAffixesForCurrency
);
835 if (rhs
.fPluralAffixesForCurrency
) {
836 UErrorCode status
= U_ZERO_ERROR
;
837 fPluralAffixesForCurrency
= initHashForAffixPattern(status
);
838 copyHashForAffix(rhs
.fPluralAffixesForCurrency
, fPluralAffixesForCurrency
, status
);
840 #if UCONFIG_FORMAT_FASTPATHS_49
841 DecimalFormatInternal
&data
= internalData(fReserved
);
842 const DecimalFormatInternal
&rhsData
= internalData(rhs
.fReserved
);
849 //------------------------------------------------------------------------------
852 DecimalFormat::operator==(const Format
& that
) const
857 // NumberFormat::operator== guarantees this cast is safe
858 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
861 // This code makes it easy to determine why two format objects that should
864 if (!NumberFormat::operator==(that
)) {
865 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
866 debug("NumberFormat::!=");
868 if (!((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
869 fPositivePrefix
== other
->fPositivePrefix
)
870 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
871 *fPosPrefixPattern
== *other
->fPosPrefixPattern
))) {
872 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
873 debug("Pos Prefix !=");
875 if (!((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
876 fPositiveSuffix
== other
->fPositiveSuffix
)
877 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
878 *fPosSuffixPattern
== *other
->fPosSuffixPattern
))) {
879 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
880 debug("Pos Suffix !=");
882 if (!((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
883 fNegativePrefix
== other
->fNegativePrefix
)
884 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
885 *fNegPrefixPattern
== *other
->fNegPrefixPattern
))) {
886 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
887 debug("Neg Prefix ");
888 if (fNegPrefixPattern
== NULL
) {
890 debugout(fNegativePrefix
);
893 debugout(*fNegPrefixPattern
);
896 if (other
->fNegPrefixPattern
== NULL
) {
898 debugout(other
->fNegativePrefix
);
901 debugout(*other
->fNegPrefixPattern
);
904 if (!((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
905 fNegativeSuffix
== other
->fNegativeSuffix
)
906 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
907 *fNegSuffixPattern
== *other
->fNegSuffixPattern
))) {
908 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
909 debug("Neg Suffix ");
910 if (fNegSuffixPattern
== NULL
) {
912 debugout(fNegativeSuffix
);
915 debugout(*fNegSuffixPattern
);
918 if (other
->fNegSuffixPattern
== NULL
) {
920 debugout(other
->fNegativeSuffix
);
923 debugout(*other
->fNegSuffixPattern
);
926 if (!((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
927 || (fRoundingIncrement
!= NULL
&&
928 other
->fRoundingIncrement
!= NULL
&&
929 *fRoundingIncrement
== *other
->fRoundingIncrement
))) {
930 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
931 debug("Rounding Increment !=");
933 if (fRoundingMode
!= other
->fRoundingMode
) {
934 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
935 printf("Rounding Mode %d != %d", (int)fRoundingMode
, (int)other
->fRoundingMode
);
937 if (getMultiplier() != other
->getMultiplier()) {
938 if (first
) { printf("[ "); first
= FALSE
; }
939 printf("Multiplier %ld != %ld", getMultiplier(), other
->getMultiplier());
941 if (fGroupingSize
!= other
->fGroupingSize
) {
942 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
943 printf("Grouping Size %ld != %ld", fGroupingSize
, other
->fGroupingSize
);
945 if (fGroupingSize2
!= other
->fGroupingSize2
) {
946 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
947 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2
, other
->fGroupingSize2
);
949 if (fDecimalSeparatorAlwaysShown
!= other
->fDecimalSeparatorAlwaysShown
) {
950 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
951 printf("fDecimalSeparatorAlwaysShown %d != %d", fDecimalSeparatorAlwaysShown
, other
->fDecimalSeparatorAlwaysShown
);
953 if (fUseExponentialNotation
!= other
->fUseExponentialNotation
) {
954 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
955 debug("fUseExponentialNotation !=");
957 if (fUseExponentialNotation
&&
958 fMinExponentDigits
!= other
->fMinExponentDigits
) {
959 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
960 debug("fMinExponentDigits !=");
962 if (fUseExponentialNotation
&&
963 fExponentSignAlwaysShown
!= other
->fExponentSignAlwaysShown
) {
964 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
965 debug("fExponentSignAlwaysShown !=");
967 if (fBoolFlags
.getAll() != other
->fBoolFlags
.getAll()) {
968 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
969 debug("fBoolFlags !=");
971 if (*fSymbols
!= *(other
->fSymbols
)) {
972 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
975 // TODO Add debug stuff for significant digits here
976 if (fUseSignificantDigits
!= other
->fUseSignificantDigits
) {
977 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
978 debug("fUseSignificantDigits !=");
980 if (fUseSignificantDigits
&&
981 fMinSignificantDigits
!= other
->fMinSignificantDigits
) {
982 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
983 debug("fMinSignificantDigits !=");
985 if (fUseSignificantDigits
&&
986 fMaxSignificantDigits
!= other
->fMaxSignificantDigits
) {
987 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
988 debug("fMaxSignificantDigits !=");
990 if (fFormatWidth
!= other
->fFormatWidth
) {
991 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
992 debug("fFormatWidth !=");
994 if (fPad
!= other
->fPad
) {
995 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
998 if (fPadPosition
!= other
->fPadPosition
) {
999 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
1000 debug("fPadPosition !=");
1002 if (fStyle
== UNUM_CURRENCY_PLURAL
&&
1003 fStyle
!= other
->fStyle
)
1004 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
1007 if (fStyle
== UNUM_CURRENCY_PLURAL
&&
1008 fFormatPattern
!= other
->fFormatPattern
) {
1009 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
1010 debug("fFormatPattern !=");
1013 if (!first
) { printf(" ]"); }
1014 if (fCurrencySignCount
!= other
->fCurrencySignCount
) {
1015 debug("fCurrencySignCount !=");
1017 if (fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
) {
1018 debug("fCurrencyPluralInfo == ");
1019 if (fCurrencyPluralInfo
== NULL
) {
1020 debug("fCurrencyPluralInfo == NULL");
1023 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
1024 *fCurrencyPluralInfo
!= *(other
->fCurrencyPluralInfo
)) {
1025 debug("fCurrencyPluralInfo !=");
1027 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
== NULL
||
1028 fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
!= NULL
) {
1029 debug("fCurrencyPluralInfo one NULL, the other not");
1031 if (fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
== NULL
) {
1032 debug("fCurrencyPluralInfo == ");
1038 NumberFormat::operator==(that
) &&
1040 ((fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) ?
1041 (fAffixPatternsForCurrency
->equals(*other
->fAffixPatternsForCurrency
)) :
1042 (((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
1043 fPositivePrefix
== other
->fPositivePrefix
)
1044 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
1045 *fPosPrefixPattern
== *other
->fPosPrefixPattern
)) &&
1046 ((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
1047 fPositiveSuffix
== other
->fPositiveSuffix
)
1048 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
1049 *fPosSuffixPattern
== *other
->fPosSuffixPattern
)) &&
1050 ((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
1051 fNegativePrefix
== other
->fNegativePrefix
)
1052 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
1053 *fNegPrefixPattern
== *other
->fNegPrefixPattern
)) &&
1054 ((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
1055 fNegativeSuffix
== other
->fNegativeSuffix
)
1056 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
1057 *fNegSuffixPattern
== *other
->fNegSuffixPattern
)))) &&
1059 ((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
1060 || (fRoundingIncrement
!= NULL
&&
1061 other
->fRoundingIncrement
!= NULL
&&
1062 *fRoundingIncrement
== *other
->fRoundingIncrement
)) &&
1064 fRoundingMode
== other
->fRoundingMode
&&
1065 getMultiplier() == other
->getMultiplier() &&
1066 fGroupingSize
== other
->fGroupingSize
&&
1067 fGroupingSize2
== other
->fGroupingSize2
&&
1068 fDecimalSeparatorAlwaysShown
== other
->fDecimalSeparatorAlwaysShown
&&
1069 fUseExponentialNotation
== other
->fUseExponentialNotation
&&
1071 (!fUseExponentialNotation
||
1072 (fMinExponentDigits
== other
->fMinExponentDigits
&& fExponentSignAlwaysShown
== other
->fExponentSignAlwaysShown
)) &&
1074 fBoolFlags
.getAll() == other
->fBoolFlags
.getAll() &&
1075 *fSymbols
== *(other
->fSymbols
) &&
1076 fUseSignificantDigits
== other
->fUseSignificantDigits
&&
1078 (!fUseSignificantDigits
||
1079 (fMinSignificantDigits
== other
->fMinSignificantDigits
&& fMaxSignificantDigits
== other
->fMaxSignificantDigits
)) &&
1081 fFormatWidth
== other
->fFormatWidth
&&
1082 fPad
== other
->fPad
&&
1083 fPadPosition
== other
->fPadPosition
&&
1085 (fStyle
!= UNUM_CURRENCY_PLURAL
||
1086 (fStyle
== other
->fStyle
&& fFormatPattern
== other
->fFormatPattern
)) &&
1088 fCurrencySignCount
== other
->fCurrencySignCount
&&
1090 ((fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
&&
1091 fCurrencyPluralInfo
== NULL
) ||
1092 (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
1093 *fCurrencyPluralInfo
== *(other
->fCurrencyPluralInfo
))) &&
1095 fCurrencyUsage
== other
->fCurrencyUsage
1097 // depending on other settings we may also need to compare
1098 // fCurrencyChoice (mostly deprecated?),
1099 // fAffixesForCurrency & fPluralAffixesForCurrency (only relevant in some cases)
1103 //------------------------------------------------------------------------------
1106 DecimalFormat::clone() const
1108 return new DecimalFormat(*this);
1113 DecimalFormat::getFixedDecimal(double number
, UErrorCode
&status
) const {
1114 FixedDecimal result
;
1116 if (U_FAILURE(status
)) {
1120 if (uprv_isNaN(number
) || uprv_isPositiveInfinity(fabs(number
))) {
1121 // For NaN and Infinity the state of the formatter is ignored.
1122 result
.init(number
);
1126 if (fMultiplier
== NULL
&& fScale
== 0 && fRoundingIncrement
== 0 && areSignificantDigitsUsed() == FALSE
&&
1127 result
.quickInit(number
) && result
.visibleDecimalDigitCount
<= getMaximumFractionDigits()) {
1128 // Fast Path. Construction of an exact FixedDecimal directly from the double, without passing
1129 // through a DigitList, was successful, and the formatter is doing nothing tricky with rounding.
1130 // printf("getFixedDecimal(%g): taking fast path.\n", number);
1131 result
.adjustForMinFractionDigits(getMinimumFractionDigits());
1133 // Slow path. Create a DigitList, and have this formatter round it according to the
1134 // requirements of the format, and fill the fixedDecimal from that.
1137 result
= getFixedDecimal(digits
, status
);
1143 DecimalFormat::getFixedDecimal(const Formattable
&number
, UErrorCode
&status
) const {
1144 if (U_FAILURE(status
)) {
1145 return FixedDecimal();
1147 if (!number
.isNumeric()) {
1148 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1149 return FixedDecimal();
1152 DigitList
*dl
= number
.getDigitList();
1154 DigitList
clonedDL(*dl
);
1155 return getFixedDecimal(clonedDL
, status
);
1158 Formattable::Type type
= number
.getType();
1159 if (type
== Formattable::kDouble
|| type
== Formattable::kLong
) {
1160 return getFixedDecimal(number
.getDouble(status
), status
);
1163 if (type
== Formattable::kInt64
&& number
.getInt64() <= MAX_INT64_IN_DOUBLE
&&
1164 number
.getInt64() >= -MAX_INT64_IN_DOUBLE
) {
1165 return getFixedDecimal(number
.getDouble(status
), status
);
1168 // The only case left is type==int64_t, with a value with more digits than a double can represent.
1169 // Any formattable originating as a big decimal will have had a pre-existing digit list.
1170 // Any originating as a double or int32 will have been handled as a double.
1172 U_ASSERT(type
== Formattable::kInt64
);
1174 digits
.set(number
.getInt64());
1175 return getFixedDecimal(digits
, status
);
1179 // Create a fixed decimal from a DigitList.
1180 // The digit list may be modified.
1181 // Internal function only.
1183 DecimalFormat::getFixedDecimal(DigitList
&number
, UErrorCode
&status
) const {
1184 // Round the number according to the requirements of this Format.
1185 FixedDecimal result
;
1186 _round(number
, number
, result
.isNegative
, status
);
1188 // The int64_t fields in FixedDecimal can easily overflow.
1189 // In deciding what to discard in this event, consider that fixedDecimal
1190 // is being used only with PluralRules, and those rules mostly look at least significant
1191 // few digits of the integer part, and whether the fraction part is zero or not.
1193 // So, in case of overflow when filling in the fields of the FixedDecimal object,
1194 // for the integer part, discard the most significant digits.
1195 // for the fraction part, discard the least significant digits,
1196 // don't truncate the fraction value to zero.
1197 // For simplicity, the int64_t fields are limited to 18 decimal digits, even
1198 // though they could hold most (but not all) 19 digit values.
1201 int32_t di
= number
.getDecimalAt()-18; // Take at most 18 digits.
1205 result
.intValue
= 0;
1206 for (; di
<number
.getDecimalAt(); di
++) {
1207 result
.intValue
= result
.intValue
* 10 + (number
.getDigit(di
) & 0x0f);
1209 if (result
.intValue
== 0 && number
.getDecimalAt()-18 > 0) {
1210 // The number is something like 100000000000000000000000.
1211 // More than 18 digits integer digits, but the least significant 18 are all zero.
1212 // We don't want to return zero as the int part, but want to keep zeros
1213 // for several of the least significant digits.
1214 result
.intValue
= 100000000000000000LL;
1218 result
.decimalDigits
= result
.decimalDigitsWithoutTrailingZeros
= result
.visibleDecimalDigitCount
= 0;
1219 for (di
= number
.getDecimalAt(); di
< number
.getCount(); di
++) {
1220 result
.visibleDecimalDigitCount
++;
1221 if (result
.decimalDigits
< 100000000000000000LL) {
1222 // 9223372036854775807 Largest 64 bit signed integer
1223 int32_t digitVal
= number
.getDigit(di
) & 0x0f; // getDigit() returns a char, '0'-'9'.
1224 result
.decimalDigits
= result
.decimalDigits
* 10 + digitVal
;
1226 result
.decimalDigitsWithoutTrailingZeros
= result
.decimalDigits
;
1231 result
.hasIntegerValue
= (result
.decimalDigits
== 0);
1233 // Trailing fraction zeros. The format specification may require more trailing
1234 // zeros than the numeric value. Add any such on now.
1236 int32_t minFractionDigits
;
1237 if (areSignificantDigitsUsed()) {
1238 minFractionDigits
= getMinimumSignificantDigits() - number
.getDecimalAt();
1239 if (minFractionDigits
< 0) {
1240 minFractionDigits
= 0;
1243 minFractionDigits
= getMinimumFractionDigits();
1245 result
.adjustForMinFractionDigits(minFractionDigits
);
1251 //------------------------------------------------------------------------------
1254 DecimalFormat::format(int32_t number
,
1255 UnicodeString
& appendTo
,
1256 FieldPosition
& fieldPosition
) const
1258 return format((int64_t)number
, appendTo
, fieldPosition
);
1262 DecimalFormat::format(int32_t number
,
1263 UnicodeString
& appendTo
,
1264 FieldPosition
& fieldPosition
,
1265 UErrorCode
& status
) const
1267 return format((int64_t)number
, appendTo
, fieldPosition
, status
);
1271 DecimalFormat::format(int32_t number
,
1272 UnicodeString
& appendTo
,
1273 FieldPositionIterator
* posIter
,
1274 UErrorCode
& status
) const
1276 return format((int64_t)number
, appendTo
, posIter
, status
);
1280 #if UCONFIG_FORMAT_FASTPATHS_49
1281 void DecimalFormat::handleChanged() {
1282 DecimalFormatInternal
&data
= internalData(fReserved
);
1284 if(data
.fFastFormatStatus
== kFastpathUNKNOWN
|| data
.fFastParseStatus
== kFastpathUNKNOWN
) {
1285 return; // still constructing. Wait.
1288 data
.fFastParseStatus
= data
.fFastFormatStatus
= kFastpathNO
;
1290 #if UCONFIG_HAVE_PARSEALLINPUT
1291 if(fParseAllInput
== UNUM_NO
) {
1292 debug("No Parse fastpath: fParseAllInput==UNUM_NO");
1295 if (fFormatWidth
!=0) {
1296 debug("No Parse fastpath: fFormatWidth");
1297 } else if(fPositivePrefix
.length()>0) {
1298 debug("No Parse fastpath: positive prefix");
1299 } else if(fPositiveSuffix
.length()>0) {
1300 debug("No Parse fastpath: positive suffix");
1301 } else if(fNegativePrefix
.length()>1
1302 || ((fNegativePrefix
.length()==1) && (fNegativePrefix
.charAt(0)!=0x002D))) {
1303 debug("No Parse fastpath: negative prefix that isn't '-'");
1304 } else if(fNegativeSuffix
.length()>0) {
1305 debug("No Parse fastpath: negative suffix");
1307 data
.fFastParseStatus
= kFastpathYES
;
1308 debug("parse fastpath: YES");
1311 if(fUseExponentialNotation
) {
1312 debug("No format fastpath: fUseExponentialNotation");
1313 } else if(fFormatWidth
!=0) {
1314 debug("No format fastpath: fFormatWidth!=0");
1315 } else if(fMinSignificantDigits
!=1) {
1316 debug("No format fastpath: fMinSignificantDigits!=1");
1317 } else if(fMultiplier
!=NULL
) {
1318 debug("No format fastpath: fMultiplier!=NULL");
1319 } else if(fScale
!=0) {
1320 debug("No format fastpath: fScale!=0");
1321 } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0)) {
1322 debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)");
1323 } else if(fDecimalSeparatorAlwaysShown
) {
1324 debug("No format fastpath: fDecimalSeparatorAlwaysShown");
1325 } else if(getMinimumFractionDigits()>0) {
1326 debug("No format fastpath: fMinFractionDigits>0");
1327 } else if(fCurrencySignCount
!= fgCurrencySignCountZero
) {
1328 debug("No format fastpath: fCurrencySignCount != fgCurrencySignCountZero");
1329 } else if(fRoundingIncrement
!=0) {
1330 debug("No format fastpath: fRoundingIncrement!=0");
1331 } else if (fGroupingSize
!=0 && isGroupingUsed()) {
1332 debug("Maybe format fastpath: fGroupingSize!=0 and grouping is used");
1334 printf("groupingsize=%d\n", fGroupingSize
);
1337 if (getMinimumIntegerDigits() <= fGroupingSize
) {
1338 data
.fFastFormatStatus
= kFastpathMAYBE
;
1340 } else if(fGroupingSize2
!=0 && isGroupingUsed()) {
1341 debug("No format fastpath: fGroupingSize2!=0");
1343 data
.fFastFormatStatus
= kFastpathYES
;
1344 debug("format:kFastpathYES!");
1350 //------------------------------------------------------------------------------
1353 DecimalFormat::format(int64_t number
,
1354 UnicodeString
& appendTo
,
1355 FieldPosition
& fieldPosition
) const
1357 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
1358 FieldPositionOnlyHandler
handler(fieldPosition
);
1359 return _format(number
, appendTo
, handler
, status
);
1363 DecimalFormat::format(int64_t number
,
1364 UnicodeString
& appendTo
,
1365 FieldPosition
& fieldPosition
,
1366 UErrorCode
& status
) const
1368 FieldPositionOnlyHandler
handler(fieldPosition
);
1369 return _format(number
, appendTo
, handler
, status
);
1373 DecimalFormat::format(int64_t number
,
1374 UnicodeString
& appendTo
,
1375 FieldPositionIterator
* posIter
,
1376 UErrorCode
& status
) const
1378 FieldPositionIteratorHandler
handler(posIter
, status
);
1379 return _format(number
, appendTo
, handler
, status
);
1383 DecimalFormat::_format(int64_t number
,
1384 UnicodeString
& appendTo
,
1385 FieldPositionHandler
& handler
,
1386 UErrorCode
&status
) const
1388 // Bottleneck function for formatting int64_t
1389 if (U_FAILURE(status
)) {
1393 #if UCONFIG_FORMAT_FASTPATHS_49
1394 // const UnicodeString *posPrefix = fPosPrefixPattern;
1395 // const UnicodeString *posSuffix = fPosSuffixPattern;
1396 // const UnicodeString *negSuffix = fNegSuffixPattern;
1398 const DecimalFormatInternal
&data
= internalData(fReserved
);
1402 printf("fastpath? [%d]\n", number
);
1405 if( data
.fFastFormatStatus
==kFastpathYES
||
1406 data
.fFastFormatStatus
==kFastpathMAYBE
) {
1407 int32_t noGroupingThreshold
= 0;
1409 #define kZero 0x0030
1410 const int32_t MAX_IDX
= MAX_DIGITS
+2;
1411 UChar outputStr
[MAX_IDX
];
1412 int32_t destIdx
= MAX_IDX
;
1413 outputStr
[--destIdx
] = 0; // term
1415 if (data
.fFastFormatStatus
==kFastpathMAYBE
) {
1416 noGroupingThreshold
= destIdx
- fGroupingSize
;
1420 // Negative numbers are slightly larger than positive
1421 // output the first digit (or the leading zero)
1422 outputStr
[--destIdx
] = (-(n
% 10) + kZero
);
1425 // get any remaining digits
1427 if (destIdx
== noGroupingThreshold
) {
1430 outputStr
[--destIdx
] = (n
% 10) + kZero
;
1434 // Slide the number to the start of the output str
1435 U_ASSERT(destIdx
>= 0);
1436 int32_t length
= MAX_IDX
- destIdx
-1;
1437 /*int32_t prefixLen = */ appendAffix(appendTo
, static_cast<double>(number
), handler
, number
<0, TRUE
);
1439 // This will be at least 0 even if it was set to a negative number.
1440 int32_t maxIntDig
= getMaximumIntegerDigits();
1441 int32_t destlength
= length
<=maxIntDig
?length
:maxIntDig
; // dest length pinned to max int digits
1443 if(length
>maxIntDig
&& fBoolFlags
.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
)) {
1444 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1447 int32_t minDigits
= getMinimumIntegerDigits();
1449 // We always want at least one digit, even if it is just a 0.
1450 int32_t prependZero
= (minDigits
< 1 ? 1 : minDigits
) - destlength
;
1453 printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d skip=%d\n", prependZero
, length
, getMinimumIntegerDigits(), maxIntDig
, destlength
, length
-destlength
);
1455 int32_t intBegin
= appendTo
.length();
1457 while((prependZero
--)>0) {
1458 appendTo
.append((UChar
)0x0030); // '0'
1461 appendTo
.append(outputStr
+destIdx
+
1462 (length
-destlength
), // skip any leading digits
1464 handler
.addAttribute(kIntegerField
, intBegin
, appendTo
.length());
1466 /*int32_t suffixLen =*/ appendAffix(appendTo
, static_cast<double>(number
), handler
, number
<0, FALSE
);
1468 //outputStr[length]=0;
1471 printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr
+destIdx
, length
, MAX_IDX
, number
);
1481 // Else the slow way - via DigitList
1484 return _format(digits
, appendTo
, handler
, status
);
1487 //------------------------------------------------------------------------------
1490 DecimalFormat::format( double number
,
1491 UnicodeString
& appendTo
,
1492 FieldPosition
& fieldPosition
) const
1494 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
1495 FieldPositionOnlyHandler
handler(fieldPosition
);
1496 return _format(number
, appendTo
, handler
, status
);
1500 DecimalFormat::format( double number
,
1501 UnicodeString
& appendTo
,
1502 FieldPosition
& fieldPosition
,
1503 UErrorCode
& status
) const
1505 FieldPositionOnlyHandler
handler(fieldPosition
);
1506 return _format(number
, appendTo
, handler
, status
);
1510 DecimalFormat::format( double number
,
1511 UnicodeString
& appendTo
,
1512 FieldPositionIterator
* posIter
,
1513 UErrorCode
& status
) const
1515 FieldPositionIteratorHandler
handler(posIter
, status
);
1516 return _format(number
, appendTo
, handler
, status
);
1520 DecimalFormat::_format( double number
,
1521 UnicodeString
& appendTo
,
1522 FieldPositionHandler
& handler
,
1523 UErrorCode
&status
) const
1525 if (U_FAILURE(status
)) {
1528 // Special case for NaN, sets the begin and end index to be the
1529 // the string length of localized name of NaN.
1530 // TODO: let NaNs go through DigitList.
1531 if (uprv_isNaN(number
))
1533 int begin
= appendTo
.length();
1534 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1536 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1538 addPadding(appendTo
, handler
, 0, 0);
1544 _format(digits
, appendTo
, handler
, status
);
1545 // No way to return status from here.
1549 //------------------------------------------------------------------------------
1553 DecimalFormat::format(const StringPiece
&number
,
1554 UnicodeString
&toAppendTo
,
1555 FieldPositionIterator
*posIter
,
1556 UErrorCode
&status
) const
1558 #if UCONFIG_FORMAT_FASTPATHS_49
1559 // don't bother if the int64 path is not optimized
1560 int32_t len
= number
.length();
1562 if(len
>0&&len
<10) { /* 10 or more digits may not be an int64 */
1563 const char *data
= number
.data();
1570 if(data
[start
]=='+') {
1572 } else if(data
[start
]=='-') {
1577 int32_t place
= 1; /* 1, 10, ... */
1578 for(int32_t i
=len
-1;i
>=start
;i
--) {
1579 if(data
[i
]>='0'&&data
[i
]<='9') {
1580 num
+=place
*(int64_t)(data
[i
]-'0');
1590 num
= -num
;// add minus bit
1592 // format as int64_t
1593 return format(num
, toAppendTo
, posIter
, status
);
1595 // else fall through
1600 dnum
.set(number
, status
);
1601 if (U_FAILURE(status
)) {
1604 FieldPositionIteratorHandler
handler(posIter
, status
);
1605 _format(dnum
, toAppendTo
, handler
, status
);
1611 DecimalFormat::format(const DigitList
&number
,
1612 UnicodeString
&appendTo
,
1613 FieldPositionIterator
*posIter
,
1614 UErrorCode
&status
) const {
1615 FieldPositionIteratorHandler
handler(posIter
, status
);
1616 _format(number
, appendTo
, handler
, status
);
1623 DecimalFormat::format(const DigitList
&number
,
1624 UnicodeString
& appendTo
,
1626 UErrorCode
&status
) const {
1627 FieldPositionOnlyHandler
handler(pos
);
1628 _format(number
, appendTo
, handler
, status
);
1633 DecimalFormat::_round(const DigitList
&number
, DigitList
&adjustedNum
, UBool
& isNegative
, UErrorCode
&status
) const {
1634 if (U_FAILURE(status
)) {
1638 // note: number and adjustedNum may refer to the same DigitList, in cases where a copy
1639 // is not needed by the caller.
1641 adjustedNum
= number
;
1643 if (number
.isNaN()) {
1647 // Do this BEFORE checking to see if value is infinite or negative! Sets the
1648 // begin and end index to be length of the string composed of
1649 // localized name of Infinite and the positive/negative localized
1652 adjustedNum
.setRoundingMode(fRoundingMode
);
1653 if (fMultiplier
!= NULL
) {
1654 adjustedNum
.mult(*fMultiplier
, status
);
1655 if (U_FAILURE(status
)) {
1662 ten
.set((int32_t)10);
1664 for (int32_t i
= fScale
; i
> 0 ; i
--) {
1665 adjustedNum
.mult(ten
, status
);
1666 if (U_FAILURE(status
)) {
1671 for (int32_t i
= fScale
; i
< 0 ; i
++) {
1672 adjustedNum
.div(ten
, status
);
1673 if (U_FAILURE(status
)) {
1681 * Note: sign is important for zero as well as non-zero numbers.
1682 * Proper detection of -0.0 is needed to deal with the
1683 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
1685 isNegative
= !adjustedNum
.isPositive();
1687 // Apply rounding after multiplier
1689 adjustedNum
.fContext
.status
&= ~DEC_Inexact
;
1690 if (fRoundingIncrement
!= NULL
) {
1691 adjustedNum
.div(*fRoundingIncrement
, status
);
1692 adjustedNum
.toIntegralValue();
1693 adjustedNum
.mult(*fRoundingIncrement
, status
);
1695 if (U_FAILURE(status
)) {
1699 if (fRoundingMode
== kRoundUnnecessary
&& (adjustedNum
.fContext
.status
& DEC_Inexact
)) {
1700 status
= U_FORMAT_INEXACT_ERROR
;
1704 if (adjustedNum
.isInfinite()) {
1708 if (fUseExponentialNotation
|| areSignificantDigitsUsed()) {
1709 int32_t sigDigits
= precision();
1710 if (sigDigits
> 0) {
1711 adjustedNum
.round(sigDigits
);
1712 // Travis Keep (21/2/2014): Calling round on a digitList does not necessarily
1713 // preserve the sign of that digit list. Preserving the sign is especially
1714 // important when formatting -0.0 for instance. Not preserving the sign seems
1715 // like a bug because I cannot think of any case where the sign would actually
1716 // have to change when rounding. For now, we preserve the sign by setting the
1717 // positive attribute directly.
1718 adjustedNum
.setPositive(!isNegative
);
1721 // Fixed point format. Round to a set number of fraction digits.
1722 int32_t numFractionDigits
= precision();
1723 adjustedNum
.roundFixedPoint(numFractionDigits
);
1725 if (fRoundingMode
== kRoundUnnecessary
&& (adjustedNum
.fContext
.status
& DEC_Inexact
)) {
1726 status
= U_FORMAT_INEXACT_ERROR
;
1733 DecimalFormat::_format(const DigitList
&number
,
1734 UnicodeString
& appendTo
,
1735 FieldPositionHandler
& handler
,
1736 UErrorCode
&status
) const
1738 if (U_FAILURE(status
)) {
1742 // Special case for NaN, sets the begin and end index to be the
1743 // the string length of localized name of NaN.
1746 int begin
= appendTo
.length();
1747 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1749 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1751 addPadding(appendTo
, handler
, 0, 0);
1755 DigitList adjustedNum
;
1757 _round(number
, adjustedNum
, isNegative
, status
);
1758 if (U_FAILURE(status
)) {
1762 // Special case for INFINITE,
1763 if (adjustedNum
.isInfinite()) {
1764 int32_t prefixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, TRUE
);
1766 int begin
= appendTo
.length();
1767 appendTo
+= getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1769 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1771 int32_t suffixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, FALSE
);
1773 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1776 return subformat(appendTo
, handler
, adjustedNum
, FALSE
, status
);
1780 * Return true if a grouping separator belongs at the given
1781 * position, based on whether grouping is in use and the values of
1782 * the primary and secondary grouping interval.
1783 * @param pos the number of integer digits to the right of
1784 * the current position. Zero indicates the position after the
1785 * rightmost integer digit.
1786 * @return true if a grouping character belongs at the current
1789 UBool
DecimalFormat::isGroupingPosition(int32_t pos
) const {
1790 UBool result
= FALSE
;
1791 if (isGroupingUsed() && (pos
> 0) && (fGroupingSize
> 0)) {
1792 if ((fGroupingSize2
> 0) && (pos
> fGroupingSize
)) {
1793 result
= ((pos
- fGroupingSize
) % fGroupingSize2
) == 0;
1795 result
= pos
% fGroupingSize
== 0;
1801 //------------------------------------------------------------------------------
1804 * Complete the formatting of a finite number. On entry, the DigitList must
1805 * be filled in with the correct digits.
1808 DecimalFormat::subformat(UnicodeString
& appendTo
,
1809 FieldPositionHandler
& handler
,
1812 UErrorCode
& status
) const
1815 // DigitList returns digits as '0' thru '9', so we will need to
1816 // always need to subtract the character 0 to get the numeric value to use for indexing.
1818 UChar32 localizedDigits
[10];
1819 localizedDigits
[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1820 localizedDigits
[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol
).char32At(0);
1821 localizedDigits
[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol
).char32At(0);
1822 localizedDigits
[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol
).char32At(0);
1823 localizedDigits
[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol
).char32At(0);
1824 localizedDigits
[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol
).char32At(0);
1825 localizedDigits
[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol
).char32At(0);
1826 localizedDigits
[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol
).char32At(0);
1827 localizedDigits
[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol
).char32At(0);
1828 localizedDigits
[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol
).char32At(0);
1830 const UnicodeString
*grouping
;
1831 if(fCurrencySignCount
== fgCurrencySignCountZero
) {
1832 grouping
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1834 grouping
= &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
1836 const UnicodeString
*decimal
;
1837 if(fCurrencySignCount
== fgCurrencySignCountZero
) {
1838 decimal
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1840 decimal
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1842 UBool useSigDig
= areSignificantDigitsUsed();
1843 int32_t maxIntDig
= getMaximumIntegerDigits();
1844 int32_t minIntDig
= getMinimumIntegerDigits();
1846 // Appends the prefix.
1847 double doubleValue
= digits
.getDouble();
1848 int32_t prefixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), TRUE
);
1850 if (fUseExponentialNotation
)
1852 int currentLength
= appendTo
.length();
1853 int intBegin
= currentLength
;
1857 int32_t minFracDig
= 0;
1859 maxIntDig
= minIntDig
= 1;
1860 minFracDig
= getMinimumSignificantDigits() - 1;
1862 minFracDig
= getMinimumFractionDigits();
1863 if (maxIntDig
> kMaxScientificIntegerDigits
) {
1865 if (maxIntDig
< minIntDig
) {
1866 maxIntDig
= minIntDig
;
1869 if (maxIntDig
> minIntDig
) {
1874 // Minimum integer digits are handled in exponential format by
1875 // adjusting the exponent. For example, 0.01234 with 3 minimum
1876 // integer digits is "123.4E-4".
1878 // Maximum integer digits are interpreted as indicating the
1879 // repeating range. This is useful for engineering notation, in
1880 // which the exponent is restricted to a multiple of 3. For
1881 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1882 // If maximum integer digits are defined and are larger than
1883 // minimum integer digits, then minimum integer digits are
1885 digits
.reduce(); // Removes trailing zero digits.
1886 int32_t exponent
= digits
.getDecimalAt();
1887 if (maxIntDig
> 1 && maxIntDig
!= minIntDig
) {
1888 // A exponent increment is defined; adjust to it.
1889 exponent
= (exponent
> 0) ? (exponent
- 1) / maxIntDig
1890 : (exponent
/ maxIntDig
) - 1;
1891 exponent
*= maxIntDig
;
1893 // No exponent increment is defined; use minimum integer digits.
1894 // If none is specified, as in "#E0", generate 1 integer digit.
1895 exponent
-= (minIntDig
> 0 || minFracDig
> 0)
1899 // We now output a minimum number of digits, and more if there
1900 // are more digits, up to the maximum number of digits. We
1901 // place the decimal point after the "integer" digits, which
1902 // are the first (decimalAt - exponent) digits.
1903 int32_t minimumDigits
= minIntDig
+ minFracDig
;
1904 // The number of integer digits is handled specially if the number
1905 // is zero, since then there may be no digits.
1906 int32_t integerDigits
= digits
.isZero() ? minIntDig
:
1907 digits
.getDecimalAt() - exponent
;
1908 int32_t totalDigits
= digits
.getCount();
1909 if (minimumDigits
> totalDigits
)
1910 totalDigits
= minimumDigits
;
1911 if (integerDigits
> totalDigits
)
1912 totalDigits
= integerDigits
;
1914 // totalDigits records total number of digits needs to be processed
1916 for (i
=0; i
<totalDigits
; ++i
)
1918 if (i
== integerDigits
)
1920 intEnd
= appendTo
.length();
1921 handler
.addAttribute(kIntegerField
, intBegin
, intEnd
);
1923 appendTo
+= *decimal
;
1925 fracBegin
= appendTo
.length();
1926 handler
.addAttribute(kDecimalSeparatorField
, fracBegin
- 1, fracBegin
);
1928 // Restores the digit character or pads the buffer with zeros.
1929 UChar32 c
= (UChar32
)((i
< digits
.getCount()) ?
1930 localizedDigits
[digits
.getDigitValue(i
)] :
1931 localizedDigits
[0]);
1935 currentLength
= appendTo
.length();
1938 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1940 if (fracBegin
> 0) {
1941 handler
.addAttribute(kFractionField
, fracBegin
, currentLength
);
1944 // The exponent is output using the pattern-specified minimum
1945 // exponent digits. There is no maximum limit to the exponent
1946 // digits, since truncating the exponent would appendTo in an
1947 // unacceptable inaccuracy.
1948 appendTo
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1950 handler
.addAttribute(kExponentSymbolField
, currentLength
, appendTo
.length());
1951 currentLength
= appendTo
.length();
1953 // For zero values, we force the exponent to zero. We
1954 // must do this here, and not earlier, because the value
1955 // is used to determine integer digit count above.
1956 if (digits
.isZero())
1960 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1961 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1962 } else if (fExponentSignAlwaysShown
) {
1963 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1964 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1967 currentLength
= appendTo
.length();
1969 DigitList expDigits
;
1970 expDigits
.set(exponent
);
1972 int expDig
= fMinExponentDigits
;
1973 if (fUseExponentialNotation
&& expDig
< 1) {
1976 for (i
=expDigits
.getDecimalAt(); i
<expDig
; ++i
)
1977 appendTo
+= (localizedDigits
[0]);
1979 for (i
=0; i
<expDigits
.getDecimalAt(); ++i
)
1981 UChar32 c
= (UChar32
)((i
< expDigits
.getCount()) ?
1982 localizedDigits
[expDigits
.getDigitValue(i
)] :
1983 localizedDigits
[0]);
1987 handler
.addAttribute(kExponentField
, currentLength
, appendTo
.length());
1989 else // Not using exponential notation
1991 int currentLength
= appendTo
.length();
1992 int intBegin
= currentLength
;
1994 int32_t sigCount
= 0;
1995 int32_t minSigDig
= getMinimumSignificantDigits();
1996 int32_t maxSigDig
= getMaximumSignificantDigits();
1999 maxSigDig
= INT32_MAX
;
2002 // Output the integer portion. Here 'count' is the total
2003 // number of integer digits we will display, including both
2004 // leading zeros required to satisfy getMinimumIntegerDigits,
2005 // and actual digits present in the number.
2006 int32_t count
= useSigDig
?
2007 _max(1, digits
.getDecimalAt()) : minIntDig
;
2008 if (digits
.getDecimalAt() > 0 && count
< digits
.getDecimalAt()) {
2009 count
= digits
.getDecimalAt();
2012 // Handle the case where getMaximumIntegerDigits() is smaller
2013 // than the real number of integer digits. If this is so, we
2014 // output the least significant max integer digits. For example,
2015 // the value 1997 printed with 2 max integer digits is just "97".
2017 int32_t digitIndex
= 0; // Index into digitList.fDigits[]
2018 if (count
> maxIntDig
&& maxIntDig
>= 0) {
2020 digitIndex
= digits
.getDecimalAt() - count
;
2021 if(fBoolFlags
.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
)) {
2022 status
= U_ILLEGAL_ARGUMENT_ERROR
;
2026 int32_t sizeBeforeIntegerPart
= appendTo
.length();
2029 for (i
=count
-1; i
>=0; --i
)
2031 if (i
< digits
.getDecimalAt() && digitIndex
< digits
.getCount() &&
2032 sigCount
< maxSigDig
) {
2033 // Output a real digit
2034 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
2039 // Output a zero (leading or trailing)
2040 appendTo
+= localizedDigits
[0];
2046 // Output grouping separator if necessary.
2047 if (isGroupingPosition(i
)) {
2048 currentLength
= appendTo
.length();
2049 appendTo
.append(*grouping
);
2050 handler
.addAttribute(kGroupingSeparatorField
, currentLength
, appendTo
.length());
2054 // This handles the special case of formatting 0. For zero only, we count the
2055 // zero to the left of the decimal point as one signficant digit. Ordinarily we
2056 // do not count any leading 0's as significant. If the number we are formatting
2057 // is not zero, then either sigCount or digits.getCount() will be non-zero.
2058 if (sigCount
== 0 && digits
.getCount() == 0) {
2062 // TODO(dlf): this looks like it was a bug, we marked the int field as ending
2063 // before the zero was generated.
2064 // Record field information for caller.
2065 // if (fieldPosition.getField() == NumberFormat::kIntegerField)
2066 // fieldPosition.setEndIndex(appendTo.length());
2068 // Determine whether or not there are any printable fractional
2069 // digits. If we've used up the digits we know there aren't.
2070 UBool fractionPresent
= (!isInteger
&& digitIndex
< digits
.getCount()) ||
2071 (useSigDig
? (sigCount
< minSigDig
) : (getMinimumFractionDigits() > 0));
2073 // If there is no fraction present, and we haven't printed any
2074 // integer digits, then print a zero. Otherwise we won't print
2075 // _any_ digits, and we won't be able to parse this string.
2076 if (!fractionPresent
&& appendTo
.length() == sizeBeforeIntegerPart
)
2077 appendTo
+= localizedDigits
[0];
2079 currentLength
= appendTo
.length();
2080 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
2082 // Output the decimal separator if we always do so.
2083 if (fDecimalSeparatorAlwaysShown
|| fractionPresent
) {
2084 appendTo
+= *decimal
;
2085 handler
.addAttribute(kDecimalSeparatorField
, currentLength
, appendTo
.length());
2086 currentLength
= appendTo
.length();
2089 int fracBegin
= currentLength
;
2091 count
= useSigDig
? INT32_MAX
: getMaximumFractionDigits();
2092 if (useSigDig
&& (sigCount
== maxSigDig
||
2093 (sigCount
>= minSigDig
&& digitIndex
== digits
.getCount()))) {
2097 for (i
=0; i
< count
; ++i
) {
2098 // Here is where we escape from the loop. We escape
2099 // if we've output the maximum fraction digits
2100 // (specified in the for expression above). We also
2101 // stop when we've output the minimum digits and
2102 // either: we have an integer, so there is no
2103 // fractional stuff to display, or we're out of
2104 // significant digits.
2105 if (!useSigDig
&& i
>= getMinimumFractionDigits() &&
2106 (isInteger
|| digitIndex
>= digits
.getCount())) {
2110 // Output leading fractional zeros. These are zeros
2111 // that come after the decimal but before any
2112 // significant digits. These are only output if
2113 // abs(number being formatted) < 1.0.
2114 if (-1-i
> (digits
.getDecimalAt()-1)) {
2115 appendTo
+= localizedDigits
[0];
2119 // Output a digit, if we have any precision left, or a
2120 // zero if we don't. We don't want to output noise digits.
2121 if (!isInteger
&& digitIndex
< digits
.getCount()) {
2122 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
2124 appendTo
+= localizedDigits
[0];
2127 // If we reach the maximum number of significant
2128 // digits, or if we output all the real digits and
2129 // reach the minimum, then we are done.
2132 (sigCount
== maxSigDig
||
2133 (digitIndex
== digits
.getCount() && sigCount
>= minSigDig
))) {
2138 handler
.addAttribute(kFractionField
, fracBegin
, appendTo
.length());
2141 int32_t suffixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), FALSE
);
2143 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
2148 * Inserts the character fPad as needed to expand result to fFormatWidth.
2149 * @param result the string to be padded
2151 void DecimalFormat::addPadding(UnicodeString
& appendTo
,
2152 FieldPositionHandler
& handler
,
2154 int32_t suffixLen
) const
2156 if (fFormatWidth
> 0) {
2157 int32_t len
= fFormatWidth
- appendTo
.length();
2159 UnicodeString padding
;
2160 for (int32_t i
=0; i
<len
; ++i
) {
2163 switch (fPadPosition
) {
2164 case kPadAfterPrefix
:
2165 appendTo
.insert(prefixLen
, padding
);
2167 case kPadBeforePrefix
:
2168 appendTo
.insert(0, padding
);
2170 case kPadBeforeSuffix
:
2171 appendTo
.insert(appendTo
.length() - suffixLen
, padding
);
2173 case kPadAfterSuffix
:
2174 appendTo
+= padding
;
2177 if (fPadPosition
== kPadBeforePrefix
|| fPadPosition
== kPadAfterPrefix
) {
2178 handler
.shiftLast(len
);
2184 //------------------------------------------------------------------------------
2187 DecimalFormat::parse(const UnicodeString
& text
,
2188 Formattable
& result
,
2189 ParsePosition
& parsePosition
) const {
2190 parse(text
, result
, parsePosition
, NULL
);
2193 CurrencyAmount
* DecimalFormat::parseCurrency(const UnicodeString
& text
,
2194 ParsePosition
& pos
) const {
2195 Formattable parseResult
;
2196 int32_t start
= pos
.getIndex();
2197 UChar curbuf
[4] = {};
2198 parse(text
, parseResult
, pos
, curbuf
);
2199 if (pos
.getIndex() != start
) {
2200 UErrorCode ec
= U_ZERO_ERROR
;
2201 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curbuf
, ec
), ec
);
2202 if (U_FAILURE(ec
)) {
2203 pos
.setIndex(start
); // indicate failure
2205 return currAmt
.orphan();
2212 * Parses the given text as a number, optionally providing a currency amount.
2213 * @param text the string to parse
2214 * @param result output parameter for the numeric result.
2215 * @param parsePosition input-output position; on input, the
2216 * position within text to match; must have 0 <= pos.getIndex() <
2217 * text.length(); on output, the position after the last matched
2218 * character. If the parse fails, the position in unchanged upon
2220 * @param currency if non-NULL, it should point to a 4-UChar buffer.
2221 * In this case the text is parsed as a currency format, and the
2222 * ISO 4217 code for the parsed currency is put into the buffer.
2223 * Otherwise the text is parsed as a non-currency format.
2225 void DecimalFormat::parse(const UnicodeString
& text
,
2226 Formattable
& result
,
2227 ParsePosition
& parsePosition
,
2228 UChar
* currency
) const {
2229 int32_t startIdx
, backup
;
2230 int32_t i
= startIdx
= backup
= parsePosition
.getIndex();
2232 // clear any old contents in the result. In particular, clears any DigitList
2233 // that it may be holding.
2235 if (currency
!= NULL
) {
2236 for (int32_t ci
=0; ci
<4; ci
++) {
2241 // Handle NaN as a special case:
2243 // Skip padding characters, if around prefix
2244 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforePrefix
||
2245 fPadPosition
== kPadAfterPrefix
)) {
2246 i
= skipPadding(text
, i
);
2250 // skip any leading whitespace
2251 i
= backup
= skipUWhiteSpace(text
, i
);
2254 // If the text is composed of the representation of NaN, returns NaN.length
2255 const UnicodeString
*nan
= &getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
2256 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
2257 ? 0 : nan
->length());
2260 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforeSuffix
||
2261 fPadPosition
== kPadAfterSuffix
)) {
2262 i
= skipPadding(text
, i
);
2264 parsePosition
.setIndex(i
);
2265 result
.setDouble(uprv_getNaN());
2269 // NaN parse failed; start over
2271 parsePosition
.setIndex(i
);
2273 // status is used to record whether a number is infinite.
2274 UBool status
[fgStatusLength
];
2276 DigitList
*digits
= result
.getInternalDigitList(); // get one from the stack buffer
2277 if (digits
== NULL
) {
2278 return; // no way to report error from here.
2281 if (fCurrencySignCount
!= fgCurrencySignCountZero
) {
2282 if (!parseForCurrency(text
, parsePosition
, *digits
,
2283 status
, currency
)) {
2288 fNegPrefixPattern
, fNegSuffixPattern
,
2289 fPosPrefixPattern
, fPosSuffixPattern
,
2290 FALSE
, UCURR_SYMBOL_NAME
,
2291 parsePosition
, *digits
, status
, currency
)) {
2292 debug("!subparse(...) - rewind");
2293 parsePosition
.setIndex(startIdx
);
2299 if (status
[fgStatusInfinite
]) {
2300 double inf
= uprv_getInfinity();
2301 result
.setDouble(digits
->isPositive() ? inf
: -inf
);
2302 // TODO: set the dl to infinity, and let it fall into the code below.
2307 if (fMultiplier
!= NULL
) {
2308 UErrorCode ec
= U_ZERO_ERROR
;
2309 digits
->div(*fMultiplier
, ec
);
2314 ten
.set((int32_t)10);
2316 for (int32_t i
= fScale
; i
> 0; i
--) {
2317 UErrorCode ec
= U_ZERO_ERROR
;
2318 digits
->div(ten
,ec
);
2321 for (int32_t i
= fScale
; i
< 0; i
++) {
2322 UErrorCode ec
= U_ZERO_ERROR
;
2323 digits
->mult(ten
,ec
);
2328 // Negative zero special case:
2329 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
2330 // if not parsing integerOnly, leave as -0, which a double can represent.
2331 if (digits
->isZero() && !digits
->isPositive() && isParseIntegerOnly()) {
2332 digits
->setPositive(TRUE
);
2334 result
.adoptDigitList(digits
);
2341 DecimalFormat::parseForCurrency(const UnicodeString
& text
,
2342 ParsePosition
& parsePosition
,
2345 UChar
* currency
) const {
2346 int origPos
= parsePosition
.getIndex();
2347 int maxPosIndex
= origPos
;
2348 int maxErrorPos
= -1;
2349 // First, parse against current pattern.
2350 // Since current pattern could be set by applyPattern(),
2351 // it could be an arbitrary pattern, and it may not be the one
2352 // defined in current locale.
2353 UBool tmpStatus
[fgStatusLength
];
2354 ParsePosition
tmpPos(origPos
);
2355 DigitList tmpDigitList
;
2357 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
2358 found
= subparse(text
,
2359 fNegPrefixPattern
, fNegSuffixPattern
,
2360 fPosPrefixPattern
, fPosSuffixPattern
,
2361 TRUE
, UCURR_LONG_NAME
,
2362 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
2364 found
= subparse(text
,
2365 fNegPrefixPattern
, fNegSuffixPattern
,
2366 fPosPrefixPattern
, fPosSuffixPattern
,
2367 TRUE
, UCURR_SYMBOL_NAME
,
2368 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
2371 if (tmpPos
.getIndex() > maxPosIndex
) {
2372 maxPosIndex
= tmpPos
.getIndex();
2373 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
2374 status
[i
] = tmpStatus
[i
];
2376 digits
= tmpDigitList
;
2379 maxErrorPos
= tmpPos
.getErrorIndex();
2381 // Then, parse against affix patterns.
2382 // Those are currency patterns and currency plural patterns.
2383 int32_t pos
= UHASH_FIRST
;
2384 const UHashElement
* element
= NULL
;
2385 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
2386 const UHashTok valueTok
= element
->value
;
2387 const AffixPatternsForCurrency
* affixPtn
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
2388 UBool tmpStatus
[fgStatusLength
];
2389 ParsePosition
tmpPos(origPos
);
2390 DigitList tmpDigitList
;
2393 debug("trying affix for currency..");
2397 UBool result
= subparse(text
,
2398 &affixPtn
->negPrefixPatternForCurrency
,
2399 &affixPtn
->negSuffixPatternForCurrency
,
2400 &affixPtn
->posPrefixPatternForCurrency
,
2401 &affixPtn
->posSuffixPatternForCurrency
,
2402 TRUE
, affixPtn
->patternType
,
2403 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
2406 if (tmpPos
.getIndex() > maxPosIndex
) {
2407 maxPosIndex
= tmpPos
.getIndex();
2408 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
2409 status
[i
] = tmpStatus
[i
];
2411 digits
= tmpDigitList
;
2414 maxErrorPos
= (tmpPos
.getErrorIndex() > maxErrorPos
) ?
2415 tmpPos
.getErrorIndex() : maxErrorPos
;
2418 // Finally, parse against simple affix to find the match.
2419 // For example, in TestMonster suite,
2420 // if the to-be-parsed text is "-\u00A40,00".
2421 // complexAffixCompare will not find match,
2422 // since there is no ISO code matches "\u00A4",
2423 // and the parse stops at "\u00A4".
2424 // We will just use simple affix comparison (look for exact match)
2427 // TODO: We should parse against simple affix first when
2428 // output currency is not requested. After the complex currency
2429 // parsing implementation was introduced, the default currency
2430 // instance parsing slowed down because of the new code flow.
2431 // I filed #10312 - Yoshito
2432 UBool tmpStatus_2
[fgStatusLength
];
2433 ParsePosition
tmpPos_2(origPos
);
2434 DigitList tmpDigitList_2
;
2436 // Disable complex currency parsing and try it again.
2437 UBool result
= subparse(text
,
2438 &fNegativePrefix
, &fNegativeSuffix
,
2439 &fPositivePrefix
, &fPositiveSuffix
,
2440 FALSE
/* disable complex currency parsing */, UCURR_SYMBOL_NAME
,
2441 tmpPos_2
, tmpDigitList_2
, tmpStatus_2
,
2444 if (tmpPos_2
.getIndex() > maxPosIndex
) {
2445 maxPosIndex
= tmpPos_2
.getIndex();
2446 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
2447 status
[i
] = tmpStatus_2
[i
];
2449 digits
= tmpDigitList_2
;
2453 maxErrorPos
= (tmpPos_2
.getErrorIndex() > maxErrorPos
) ?
2454 tmpPos_2
.getErrorIndex() : maxErrorPos
;
2458 //parsePosition.setIndex(origPos);
2459 parsePosition
.setErrorIndex(maxErrorPos
);
2461 parsePosition
.setIndex(maxPosIndex
);
2462 parsePosition
.setErrorIndex(-1);
2469 * Parse the given text into a number. The text is parsed beginning at
2470 * parsePosition, until an unparseable character is seen.
2471 * @param text the string to parse.
2472 * @param negPrefix negative prefix.
2473 * @param negSuffix negative suffix.
2474 * @param posPrefix positive prefix.
2475 * @param posSuffix positive suffix.
2476 * @param complexCurrencyParsing whether it is complex currency parsing or not.
2477 * @param type the currency type to parse against, LONG_NAME only or not.
2478 * @param parsePosition The position at which to being parsing. Upon
2479 * return, the first unparsed character.
2480 * @param digits the DigitList to set to the parsed value.
2481 * @param status output param containing boolean status flags indicating
2482 * whether the value was infinite and whether it was positive.
2483 * @param currency return value for parsed currency, for generic
2484 * currency parsing mode, or NULL for normal parsing. In generic
2485 * currency parsing mode, any currency is parsed, not just the
2486 * currency that this formatter is set to.
2488 UBool
DecimalFormat::subparse(const UnicodeString
& text
,
2489 const UnicodeString
* negPrefix
,
2490 const UnicodeString
* negSuffix
,
2491 const UnicodeString
* posPrefix
,
2492 const UnicodeString
* posSuffix
,
2493 UBool complexCurrencyParsing
,
2495 ParsePosition
& parsePosition
,
2496 DigitList
& digits
, UBool
* status
,
2497 UChar
* currency
) const
2499 // The parsing process builds up the number as char string, in the neutral format that
2500 // will be acceptable to the decNumber library, then at the end passes that string
2501 // off for conversion to a decNumber.
2502 UErrorCode err
= U_ZERO_ERROR
;
2503 CharString parsedNum
;
2506 int32_t position
= parsePosition
.getIndex();
2507 int32_t oldStart
= position
;
2508 int32_t textLength
= text
.length(); // One less pointer to follow
2509 UBool strictParse
= !isLenient();
2510 UChar32 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
2511 const UnicodeString
*groupingString
= &getConstSymbol(fCurrencySignCount
== fgCurrencySignCountZero
?
2512 DecimalFormatSymbols::kGroupingSeparatorSymbol
: DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
2513 UChar32 groupingChar
= groupingString
->char32At(0);
2514 int32_t groupingStringLength
= groupingString
->length();
2515 int32_t groupingCharLength
= U16_LENGTH(groupingChar
);
2516 UBool groupingUsed
= isGroupingUsed();
2519 UnicodeString
s(dbgbuf
,0,300);;
2520 s
.append((UnicodeString
)"PARSE \"").append(text
.tempSubString(position
)).append((UnicodeString
)"\" " );
2521 #define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("<empty>")); } else { s.append(*x); } s.append(UnicodeString(" ")); } else { s.append(UnicodeString(#x "=NULL ")); }
2527 printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.length=%d negPrefLen=%d\n", currencyParsing
, fFormatWidth
, (isParseIntegerOnly())?'Y':'N', text
.length(), negPrefix
!=NULL
?negPrefix
->length():-1);
2530 UBool fastParseOk
= false; /* TRUE iff fast parse is OK */
2531 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
2532 const DecimalFormatInternal
&data
= internalData(fReserved
);
2533 if((data
.fFastParseStatus
==kFastpathYES
) &&
2534 fCurrencySignCount
== fgCurrencySignCountZero
&&
2535 // (negPrefix!=NULL&&negPrefix->isEmpty()) ||
2538 (posPrefix
==NULL
||posPrefix
->isEmpty()) &&
2539 (posSuffix
==NULL
||posSuffix
->isEmpty()) &&
2540 // (negPrefix==NULL||negPrefix->isEmpty()) &&
2541 // (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
2542 TRUE
) { // optimized path
2544 int l
=text
.length();
2546 UChar32 ch
= text
.char32At(j
);
2547 const UnicodeString
*decimalString
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
2548 UChar32 decimalChar
= 0;
2549 UBool intOnly
= FALSE
;
2550 UChar32 lookForGroup
= (groupingUsed
&&intOnly
&&strictParse
)?groupingChar
:0;
2552 int32_t decimalCount
= decimalString
->countChar32(0,3);
2553 if(isParseIntegerOnly()) {
2554 decimalChar
= 0; // not allowed
2555 intOnly
= TRUE
; // Don't look for decimals.
2556 } else if(decimalCount
==1) {
2557 decimalChar
= decimalString
->char32At(0); // Look for this decimal
2558 } else if(decimalCount
==0) {
2559 decimalChar
=0; // NO decimal set
2561 j
=l
+1;//Set counter to end of line, so that we break. Unknown decimal situation.
2565 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
2566 decimalChar
, groupingChar
, ch
,
2568 (strictParse
)?'y':'n');
2570 if(ch
==0x002D) { // '-'
2571 j
=l
+1;//=break - negative number.
2574 parsedNum.append('-',err);
2576 if(j<l) ch = text.char32At(j);
2579 parsedNum
.append('+',err
);
2582 int32_t digit
= ch
- zero
;
2583 if(digit
>=0 && digit
<= 9) {
2584 parsedNum
.append((char)(digit
+ '0'), err
);
2585 if((digitCount
>0) || digit
!=0 || j
==(l
-1)) {
2588 } else if(ch
== 0) { // break out
2591 } else if(ch
== decimalChar
) {
2592 parsedNum
.append((char)('.'), err
);
2593 decimalChar
=0; // no more decimals.
2594 // fastParseHadDecimal=TRUE;
2595 } else if(ch
== lookForGroup
) {
2596 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
2597 } else if(intOnly
&& (lookForGroup
!=0) && !u_isdigit(ch
)) {
2598 // parsing integer only and can fall through
2600 digitCount
=-1; // fail - fall through to slow parse
2604 ch
= text
.char32At(j
); // for next
2607 ((j
==l
)||intOnly
) // end OR only parsing integer
2608 && (digitCount
>0)) { // and have at least one digit
2610 printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j
, parsedNum
.data(), digitCount
, fGroupingSize
, fGroupingSize2
);
2612 fastParseOk
=true; // Fast parse OK!
2616 /* for testing, try it the slow way. also */
2620 parsePosition
.setIndex(position
=j
);
2621 status
[fgStatusInfinite
]=false;
2624 // was not OK. reset, retry
2626 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j
, l
, digitCount
);
2632 printf("Could not fastpath parse. ");
2633 printf("fFormatWidth=%d ", fFormatWidth
);
2634 printf("text.length()=%d ", text
.length());
2635 printf("posPrefix=%p posSuffix=%p ", posPrefix
, posSuffix
);
2642 #if UCONFIG_HAVE_PARSEALLINPUT
2643 && fParseAllInput
!=UNUM_YES
2647 // Match padding before prefix
2648 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforePrefix
) {
2649 position
= skipPadding(text
, position
);
2652 // Match positive and negative prefixes; prefer longest match.
2653 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, posPrefix
, complexCurrencyParsing
, type
, currency
);
2654 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, negPrefix
, complexCurrencyParsing
, type
, currency
);
2655 if (posMatch
>= 0 && negMatch
>= 0) {
2656 if (posMatch
> negMatch
) {
2658 } else if (negMatch
> posMatch
) {
2662 if (posMatch
>= 0) {
2663 position
+= posMatch
;
2664 parsedNum
.append('+', err
);
2665 } else if (negMatch
>= 0) {
2666 position
+= negMatch
;
2667 parsedNum
.append('-', err
);
2668 } else if (strictParse
){
2669 parsePosition
.setErrorIndex(position
);
2672 // Temporary set positive. This might be changed after checking suffix
2673 parsedNum
.append('+', err
);
2676 // Match padding before prefix
2677 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterPrefix
) {
2678 position
= skipPadding(text
, position
);
2681 if (! strictParse
) {
2682 position
= skipUWhiteSpace(text
, position
);
2685 // process digits or Inf, find decimal position
2686 const UnicodeString
*inf
= &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
2687 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
2688 ? 0 : inf
->length());
2689 position
+= infLen
; // infLen is non-zero when it does equal to infinity
2690 status
[fgStatusInfinite
] = infLen
!= 0;
2693 parsedNum
.append("Infinity", err
);
2695 // We now have a string of digits, possibly with grouping symbols,
2696 // and decimal points. We want to process these into a DigitList.
2697 // We don't want to put a bunch of leading zeros into the DigitList
2698 // though, so we keep track of the location of the decimal point,
2699 // put only significant digits into the DigitList, and adjust the
2700 // exponent as needed.
2703 UBool strictFail
= FALSE
; // did we exit with a strict parse failure?
2704 int32_t lastGroup
= -1; // where did we last see a grouping separator?
2705 int32_t digitStart
= position
;
2706 int32_t gs2
= fGroupingSize2
== 0 ? fGroupingSize
: fGroupingSize2
;
2708 const UnicodeString
*decimalString
;
2709 if (fCurrencySignCount
!= fgCurrencySignCountZero
) {
2710 decimalString
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
2712 decimalString
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
2714 UChar32 decimalChar
= decimalString
->char32At(0);
2715 int32_t decimalStringLength
= decimalString
->length();
2716 int32_t decimalCharLength
= U16_LENGTH(decimalChar
);
2718 UBool sawDecimal
= FALSE
;
2719 UChar32 sawDecimalChar
= 0xFFFF;
2720 UBool sawGrouping
= FALSE
;
2721 UChar32 sawGroupingChar
= 0xFFFF;
2722 UBool sawDigit
= FALSE
;
2723 int32_t backup
= -1;
2726 // equivalent grouping and decimal support
2727 const UnicodeSet
*decimalSet
= NULL
;
2728 const UnicodeSet
*groupingSet
= NULL
;
2730 if (decimalCharLength
== decimalStringLength
) {
2731 decimalSet
= DecimalFormatStaticSets::getSimilarDecimals(decimalChar
, strictParse
);
2734 if (groupingCharLength
== groupingStringLength
) {
2736 groupingSet
= fStaticSets
->fStrictDefaultGroupingSeparators
;
2738 groupingSet
= fStaticSets
->fDefaultGroupingSeparators
;
2742 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
2743 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
2744 // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
2746 // We have to track digitCount ourselves, because digits.fCount will
2747 // pin when the maximum allowable digits is reached.
2748 int32_t digitCount
= 0;
2749 int32_t integerDigitCount
= 0;
2751 for (; position
< textLength
; )
2753 UChar32 ch
= text
.char32At(position
);
2755 /* We recognize all digit ranges, not only the Latin digit range
2756 * '0'..'9'. We do so by using the Character.digit() method,
2757 * which converts a valid Unicode digit to the range 0..9.
2759 * The character 'ch' may be a digit. If so, place its value
2760 * from 0 to 9 in 'digit'. First try using the locale digit,
2761 * which may or MAY NOT be a standard Unicode digit range. If
2762 * this fails, try using the standard Unicode digit ranges by
2763 * calling Character.digit(). If this also fails, digit will
2764 * have a value outside the range 0..9.
2767 if (digit
< 0 || digit
> 9)
2769 digit
= u_charDigitValue(ch
);
2772 // As a last resort, look through the localized digits if the zero digit
2773 // is not a "standard" Unicode digit.
2774 if ( (digit
< 0 || digit
> 9) && u_charDigitValue(zero
) != 0) {
2776 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is:
2777 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits.
2778 if ( zero
!=0x3007 || ch
!=0x96F6 ) {
2779 for (digit
= 1 ; digit
< 10 ; digit
++ ) {
2780 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)(DecimalFormatSymbols::kOneDigitSymbol
+digit
-1)).char32At(0) == ch
) {
2787 if (digit
>= 0 && digit
<= 9)
2789 if (strictParse
&& backup
!= -1) {
2790 // comma followed by digit, so group before comma is a
2791 // secondary group. If there was a group separator
2792 // before that, the group must == the secondary group
2793 // length, else it can be <= the the secondary group
2795 if ((lastGroup
!= -1 && backup
- lastGroup
- 1 != gs2
) ||
2796 (lastGroup
== -1 && position
- digitStart
- 1 > gs2
)) {
2804 // Cancel out backup setting (see grouping handler below)
2808 // Note: this will append leading zeros
2809 parsedNum
.append((char)(digit
+ '0'), err
);
2811 // count any digit that's not a leading zero
2812 if (digit
> 0 || digitCount
> 0 || sawDecimal
) {
2815 // count any integer digit that's not a leading zero
2817 integerDigitCount
+= 1;
2821 position
+= U16_LENGTH(ch
);
2823 else if (groupingStringLength
> 0 &&
2824 matchGrouping(groupingChar
, sawGrouping
, sawGroupingChar
, groupingSet
,
2825 decimalChar
, decimalSet
,
2826 ch
) && groupingUsed
)
2833 if ( (!sawDigit
&& groupingSet
!=NULL
&& u_isWhitespace(ch
)) || backup
!= -1 ) {
2834 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for
2835 // backward compatibility) as long as it is not one of the breaking whitespace characters
2836 // that is only treated as a group separator because of the equivalence set. If we get
2837 // here it is because the leading sep was such a breaking space, or there were multiple
2838 // group separators in a row. Note that the DecimalFormat documentation says
2839 // "During parsing, grouping separators are ignored" and that was for strict parsing,
2840 // so we may need to further revisit this strictParse restriction to ensure compatibility.
2841 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F.
2842 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP).
2848 // Ignore grouping characters, if we are using them, but require
2849 // that they be followed by a digit. Otherwise we backup and
2852 position
+= groupingStringLength
;
2854 // Once we see a grouping character, we only accept that grouping character from then on.
2857 else if (matchDecimal(decimalChar
,sawDecimal
,sawDecimalChar
, decimalSet
, ch
))
2861 (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1)) {
2867 // If we're only parsing integers, or if we ALREADY saw the
2868 // decimal, then don't parse this one.
2869 if (isParseIntegerOnly() || sawDecimal
) {
2873 parsedNum
.append('.', err
);
2874 position
+= decimalStringLength
;
2876 // Once we see a decimal character, we only accept that decimal character from then on.
2878 // decimalSet is considered to consist of (ch,ch)
2882 if(!fBoolFlags
.contains(UNUM_PARSE_NO_EXPONENT
) || // don't parse if this is set unless..
2883 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
2884 const UnicodeString
*tmp
;
2885 tmp
= &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
2887 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
2889 // Parse sign, if present
2890 int32_t pos
= position
+ tmp
->length();
2891 char exponentSign
= '+';
2893 if (pos
< textLength
)
2895 tmp
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2896 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2898 pos
+= tmp
->length();
2901 tmp
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2902 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2905 pos
+= tmp
->length();
2910 UBool sawExponentDigit
= FALSE
;
2911 while (pos
< textLength
) {
2912 ch
= text
[(int32_t)pos
];
2915 if (digit
< 0 || digit
> 9) {
2916 digit
= u_charDigitValue(ch
);
2918 if (0 <= digit
&& digit
<= 9) {
2919 if (!sawExponentDigit
) {
2920 parsedNum
.append('E', err
);
2921 parsedNum
.append(exponentSign
, err
);
2922 sawExponentDigit
= TRUE
;
2925 parsedNum
.append((char)(digit
+ '0'), err
);
2931 if (sawExponentDigit
) {
2932 position
= pos
; // Advance past the exponent
2935 break; // Whether we fail or succeed, we exit this loop
2939 } else { // not parsing exponent
2945 // if we didn't see a decimal and it is required, check to see if the pattern had one
2946 if(!sawDecimal
&& isDecimalPatternMatchRequired())
2948 if(fFormatPattern
.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol
) != 0)
2950 parsePosition
.setIndex(oldStart
);
2951 parsePosition
.setErrorIndex(position
);
2952 debug("decimal point match required fail!");
2962 if (strictParse
&& !sawDecimal
) {
2963 if (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1) {
2969 // only set with strictParse and a grouping separator error
2971 parsePosition
.setIndex(oldStart
);
2972 parsePosition
.setErrorIndex(position
);
2973 debug("strictFail!");
2977 // If there was no decimal point we have an integer
2979 // If none of the text string was recognized. For example, parse
2980 // "x" with pattern "#0.00" (return index and error index both 0)
2981 // parse "$" with pattern "$#0.00". (return index 0 and error index
2983 if (!sawDigit
&& digitCount
== 0) {
2985 debug("none of text rec");
2986 printf("position=%d\n",position
);
2988 parsePosition
.setIndex(oldStart
);
2989 parsePosition
.setErrorIndex(oldStart
);
2994 // Match padding before suffix
2995 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforeSuffix
) {
2996 position
= skipPadding(text
, position
);
2999 int32_t posSuffixMatch
= -1, negSuffixMatch
= -1;
3001 // Match positive and negative suffixes; prefer longest match.
3002 if (posMatch
>= 0 || (!strictParse
&& negMatch
< 0)) {
3003 posSuffixMatch
= compareAffix(text
, position
, FALSE
, FALSE
, posSuffix
, complexCurrencyParsing
, type
, currency
);
3005 if (negMatch
>= 0) {
3006 negSuffixMatch
= compareAffix(text
, position
, TRUE
, FALSE
, negSuffix
, complexCurrencyParsing
, type
, currency
);
3008 if (posSuffixMatch
>= 0 && negSuffixMatch
>= 0) {
3009 if (posSuffixMatch
> negSuffixMatch
) {
3010 negSuffixMatch
= -1;
3011 } else if (negSuffixMatch
> posSuffixMatch
) {
3012 posSuffixMatch
= -1;
3016 // Fail if neither or both
3017 if (strictParse
&& ((posSuffixMatch
>= 0) == (negSuffixMatch
>= 0))) {
3018 parsePosition
.setErrorIndex(position
);
3019 debug("neither or both");
3023 position
+= (posSuffixMatch
>= 0 ? posSuffixMatch
: (negSuffixMatch
>= 0 ? negSuffixMatch
: 0));
3025 // Match padding before suffix
3026 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterSuffix
) {
3027 position
= skipPadding(text
, position
);
3030 parsePosition
.setIndex(position
);
3032 parsedNum
.data()[0] = (posSuffixMatch
>= 0 || (!strictParse
&& negMatch
< 0 && negSuffixMatch
< 0)) ? '+' : '-';
3034 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position
, parsedNum
.data(), parsePosition
.getIndex(),oldStart
,u_errorName(err
));
3036 } /* end SLOW parse */
3037 if(parsePosition
.getIndex() == oldStart
)
3040 printf(" PP didnt move, err\n");
3042 parsePosition
.setErrorIndex(position
);
3045 #if UCONFIG_HAVE_PARSEALLINPUT
3046 else if (fParseAllInput
==UNUM_YES
&&parsePosition
.getIndex()!=textLength
)
3049 printf(" PP didnt consume all (UNUM_YES), err\n");
3051 parsePosition
.setErrorIndex(position
);
3055 // uint32_t bits = (fastParseOk?kFastpathOk:0) |
3056 // (fastParseHadDecimal?0:kNoDecimal);
3057 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
3058 digits
.set(parsedNum
.toStringPiece(),
3063 if (U_FAILURE(err
)) {
3065 printf(" err setting %s\n", u_errorName(err
));
3067 parsePosition
.setErrorIndex(position
);
3071 // check if we missed a required decimal point
3072 if(fastParseOk
&& isDecimalPatternMatchRequired())
3074 if(fFormatPattern
.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol
) != 0)
3076 parsePosition
.setIndex(oldStart
);
3077 parsePosition
.setErrorIndex(position
);
3078 debug("decimal point match required fail!");
3088 * Starting at position, advance past a run of pad characters, if any.
3089 * Return the index of the first character after position that is not a pad
3090 * character. Result is >= position.
3092 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
3093 int32_t padLen
= U16_LENGTH(fPad
);
3094 while (position
< text
.length() &&
3095 text
.char32At(position
) == fPad
) {
3102 * Return the length matched by the given affix, or -1 if none.
3103 * Runs of white space in the affix, match runs of white space in
3104 * the input. Pattern white space and input white space are
3105 * determined differently; see code.
3106 * @param text input text
3107 * @param pos offset into input at which to begin matching
3110 * @param affixPat affix pattern used for currency affix comparison.
3111 * @param complexCurrencyParsing whether it is currency parsing or not
3112 * @param type the currency type to parse against, LONG_NAME only or not.
3113 * @param currency return value for parsed currency, for generic
3114 * currency parsing mode, or null for normal parsing. In generic
3115 * currency parsing mode, any currency is parsed, not just the
3116 * currency that this formatter is set to.
3117 * @return length of input that matches, or -1 if match failure
3119 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
3123 const UnicodeString
* affixPat
,
3124 UBool complexCurrencyParsing
,
3126 UChar
* currency
) const
3128 const UnicodeString
*patternToCompare
;
3129 if (fCurrencyChoice
!= NULL
|| currency
!= NULL
||
3130 (fCurrencySignCount
!= fgCurrencySignCountZero
&& complexCurrencyParsing
)) {
3132 if (affixPat
!= NULL
) {
3133 return compareComplexAffix(*affixPat
, text
, pos
, type
, currency
);
3139 patternToCompare
= &fNegativePrefix
;
3142 patternToCompare
= &fNegativeSuffix
;
3147 patternToCompare
= &fPositivePrefix
;
3150 patternToCompare
= &fPositiveSuffix
;
3153 return compareSimpleAffix(*patternToCompare
, text
, pos
, isLenient());
3156 UBool
DecimalFormat::equalWithSignCompatibility(UChar32 lhs
, UChar32 rhs
) const {
3160 U_ASSERT(fStaticSets
!= NULL
); // should already be loaded
3161 const UnicodeSet
*minusSigns
= fStaticSets
->fMinusSigns
;
3162 const UnicodeSet
*plusSigns
= fStaticSets
->fPlusSigns
;
3163 return (minusSigns
->contains(lhs
) && minusSigns
->contains(rhs
)) ||
3164 (plusSigns
->contains(lhs
) && plusSigns
->contains(rhs
));
3167 // check for LRM 0x200E, RLM 0x200F, ALM 0x061C
3168 #define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C)
3170 #define TRIM_BUFLEN 32
3171 UnicodeString
& DecimalFormat::trimMarksFromAffix(const UnicodeString
& affix
, UnicodeString
& trimmedAffix
) {
3172 UChar trimBuf
[TRIM_BUFLEN
];
3173 int32_t affixLen
= affix
.length();
3174 int32_t affixPos
, trimLen
= 0;
3176 for (affixPos
= 0; affixPos
< affixLen
; affixPos
++) {
3177 UChar c
= affix
.charAt(affixPos
);
3178 if (!IS_BIDI_MARK(c
)) {
3179 if (trimLen
< TRIM_BUFLEN
) {
3180 trimBuf
[trimLen
++] = c
;
3187 return (trimLen
> 0)? trimmedAffix
.setTo(trimBuf
, trimLen
): trimmedAffix
.setTo(affix
);
3191 * Return the length matched by the given affix, or -1 if none.
3192 * Runs of white space in the affix, match runs of white space in
3193 * the input. Pattern white space and input white space are
3194 * determined differently; see code.
3195 * @param affix pattern string, taken as a literal
3196 * @param input input text
3197 * @param pos offset into input at which to begin matching
3198 * @return length of input that matches, or -1 if match failure
3200 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
3201 const UnicodeString
& input
,
3203 UBool lenient
) const {
3204 int32_t start
= pos
;
3205 UnicodeString trimmedAffix
;
3206 // For more efficiency we should keep lazily-created trimmed affixes around in
3207 // instance variables instead of trimming each time they are used (the next step)
3208 trimMarksFromAffix(affix
, trimmedAffix
);
3209 UChar32 affixChar
= trimmedAffix
.char32At(0);
3210 int32_t affixLength
= trimmedAffix
.length();
3211 int32_t inputLength
= input
.length();
3212 int32_t affixCharLength
= U16_LENGTH(affixChar
);
3213 UnicodeSet
*affixSet
;
3214 UErrorCode status
= U_ZERO_ERROR
;
3216 U_ASSERT(fStaticSets
!= NULL
); // should already be loaded
3218 if (U_FAILURE(status
)) {
3222 affixSet
= fStaticSets
->fStrictDashEquivalents
;
3224 // If the trimmedAffix is exactly one character long and that character
3225 // is in the dash set and the very next input character is also
3226 // in the dash set, return a match.
3227 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
3228 UChar32 ic
= input
.char32At(pos
);
3229 if (affixSet
->contains(ic
)) {
3230 pos
+= U16_LENGTH(ic
);
3231 pos
= skipBidiMarks(input
, pos
); // skip any trailing bidi marks
3236 for (int32_t i
= 0; i
< affixLength
; ) {
3237 UChar32 c
= trimmedAffix
.char32At(i
);
3238 int32_t len
= U16_LENGTH(c
);
3239 if (PatternProps::isWhiteSpace(c
)) {
3240 // We may have a pattern like: \u200F \u0020
3241 // and input text like: \u200F \u0020
3242 // Note that U+200F and U+0020 are Pattern_White_Space but only
3243 // U+0020 is UWhiteSpace. So we have to first do a direct
3244 // match of the run of Pattern_White_Space in the pattern,
3245 // then match any extra characters.
3246 UBool literalMatch
= FALSE
;
3247 while (pos
< inputLength
) {
3248 UChar32 ic
= input
.char32At(pos
);
3250 literalMatch
= TRUE
;
3253 if (i
== affixLength
) {
3256 c
= trimmedAffix
.char32At(i
);
3257 len
= U16_LENGTH(c
);
3258 if (!PatternProps::isWhiteSpace(c
)) {
3261 } else if (IS_BIDI_MARK(ic
)) {
3262 pos
++; // just skip over this input text
3268 // Advance over run in pattern
3269 i
= skipPatternWhiteSpace(trimmedAffix
, i
);
3271 // Advance over run in input text
3272 // Must see at least one white space char in input,
3273 // unless we've already matched some characters literally.
3275 pos
= skipUWhiteSpace(input
, pos
);
3276 if (pos
== s
&& !literalMatch
) {
3280 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
3281 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
3282 // is also in the trimmedAffix.
3283 i
= skipUWhiteSpace(trimmedAffix
, i
);
3285 UBool match
= FALSE
;
3286 while (pos
< inputLength
) {
3287 UChar32 ic
= input
.char32At(pos
);
3288 if (!match
&& ic
== c
) {
3292 } else if (IS_BIDI_MARK(ic
)) {
3293 pos
++; // just skip over this input text
3304 UBool match
= FALSE
;
3306 affixSet
= fStaticSets
->fDashEquivalents
;
3308 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
3309 pos
= skipUWhiteSpaceAndMarks(input
, pos
);
3310 UChar32 ic
= input
.char32At(pos
);
3312 if (affixSet
->contains(ic
)) {
3313 pos
+= U16_LENGTH(ic
);
3314 pos
= skipBidiMarks(input
, pos
);
3319 for (int32_t i
= 0; i
< affixLength
; )
3321 //i = skipRuleWhiteSpace(trimmedAffix, i);
3322 i
= skipUWhiteSpace(trimmedAffix
, i
);
3323 pos
= skipUWhiteSpaceAndMarks(input
, pos
);
3325 if (i
>= affixLength
|| pos
>= inputLength
) {
3329 UChar32 c
= trimmedAffix
.char32At(i
);
3330 UChar32 ic
= input
.char32At(pos
);
3332 if (!equalWithSignCompatibility(ic
, c
)) {
3338 pos
+= U16_LENGTH(ic
);
3339 pos
= skipBidiMarks(input
, pos
);
3342 if (affixLength
> 0 && ! match
) {
3350 * Skip over a run of zero or more Pattern_White_Space characters at
3353 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
3354 const UChar
* s
= text
.getBuffer();
3355 return (int32_t)(PatternProps::skipWhiteSpace(s
+ pos
, text
.length() - pos
) - s
);
3359 * Skip over a run of zero or more isUWhiteSpace() characters at pos
3362 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
3363 while (pos
< text
.length()) {
3364 UChar32 c
= text
.char32At(pos
);
3365 if (!u_isUWhiteSpace(c
)) {
3368 pos
+= U16_LENGTH(c
);
3374 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos
3377 int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString
& text
, int32_t pos
) {
3378 while (pos
< text
.length()) {
3379 UChar32 c
= text
.char32At(pos
);
3380 if (!u_isUWhiteSpace(c
) && !IS_BIDI_MARK(c
)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM
3383 pos
+= U16_LENGTH(c
);
3389 * Skip over a run of zero or more bidi marks at pos in text.
3391 int32_t DecimalFormat::skipBidiMarks(const UnicodeString
& text
, int32_t pos
) {
3392 while (pos
< text
.length()) {
3393 UChar c
= text
.charAt(pos
);
3394 if (!IS_BIDI_MARK(c
)) {
3403 * Return the length matched by the given affix, or -1 if none.
3404 * @param affixPat pattern string
3405 * @param input input text
3406 * @param pos offset into input at which to begin matching
3407 * @param type the currency type to parse against, LONG_NAME only or not.
3408 * @param currency return value for parsed currency, for generic
3409 * currency parsing mode, or null for normal parsing. In generic
3410 * currency parsing mode, any currency is parsed, not just the
3411 * currency that this formatter is set to.
3412 * @return length of input that matches, or -1 if match failure
3414 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
3415 const UnicodeString
& text
,
3418 UChar
* currency
) const
3420 int32_t start
= pos
;
3421 U_ASSERT(currency
!= NULL
||
3422 (fCurrencyChoice
!= NULL
&& *getCurrency() != 0) ||
3423 fCurrencySignCount
!= fgCurrencySignCountZero
);
3426 i
<affixPat
.length() && pos
>= 0; ) {
3427 UChar32 c
= affixPat
.char32At(i
);
3431 U_ASSERT(i
<= affixPat
.length());
3432 c
= affixPat
.char32At(i
);
3435 const UnicodeString
* affix
= NULL
;
3438 case kCurrencySign
: {
3439 // since the currency names in choice format is saved
3440 // the same way as other currency names,
3441 // do not need to do currency choice parsing here.
3442 // the general currency parsing parse against all names,
3443 // including names in choice format.
3444 UBool intl
= i
<affixPat
.length() &&
3445 affixPat
.char32At(i
) == kCurrencySign
;
3449 UBool plural
= i
<affixPat
.length() &&
3450 affixPat
.char32At(i
) == kCurrencySign
;
3455 // Parse generic currency -- anything for which we
3456 // have a display name, or any 3-letter ISO code.
3457 // Try to parse display name for our locale; first
3458 // determine our locale.
3459 const char* loc
= fCurrencyPluralInfo
->getLocale().getName();
3460 ParsePosition
ppos(pos
);
3462 UErrorCode ec
= U_ZERO_ERROR
;
3463 // Delegate parse of display name => ISO code to Currency
3464 uprv_parseCurrency(loc
, text
, ppos
, type
, curr
, ec
);
3466 // If parse succeeds, populate currency[0]
3467 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
3469 u_strcpy(currency
, curr
);
3471 // The formatter is currency-style but the client has not requested
3472 // the value of the parsed currency. In this case, if that value does
3473 // not match the formatter's current value, then the parse fails.
3474 UChar effectiveCurr
[4];
3475 getEffectiveCurrency(effectiveCurr
, ec
);
3476 if ( U_FAILURE(ec
) || u_strncmp(curr
,effectiveCurr
,4) != 0 ) {
3481 pos
= ppos
.getIndex();
3482 } else if (!isLenient()){
3487 case kPatternPercent
:
3488 affix
= &getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3490 case kPatternPerMill
:
3491 affix
= &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3494 affix
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3497 affix
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3500 // fall through to affix!=0 test, which will fail
3504 if (affix
!= NULL
) {
3505 pos
= match(text
, pos
, *affix
);
3510 pos
= match(text
, pos
, c
);
3511 if (PatternProps::isWhiteSpace(c
)) {
3512 i
= skipPatternWhiteSpace(affixPat
, i
);
3519 * Match a single character at text[pos] and return the index of the
3520 * next character upon success. Return -1 on failure. If
3521 * ch is a Pattern_White_Space then match a run of white space in text.
3523 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
3524 if (PatternProps::isWhiteSpace(ch
)) {
3525 // Advance over run of white space in input text
3526 // Must see at least one white space char in input
3528 pos
= skipPatternWhiteSpace(text
, pos
);
3534 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
3535 (pos
+ U16_LENGTH(ch
)) : -1;
3539 * Match a string at text[pos] and return the index of the next
3540 * character upon success. Return -1 on failure. Match a run of
3541 * white space in str with a run of white space in text.
3543 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
3544 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
3545 UChar32 ch
= str
.char32At(i
);
3546 i
+= U16_LENGTH(ch
);
3547 if (PatternProps::isWhiteSpace(ch
)) {
3548 i
= skipPatternWhiteSpace(str
, i
);
3550 pos
= match(text
, pos
, ch
);
3555 UBool
DecimalFormat::matchSymbol(const UnicodeString
&text
, int32_t position
, int32_t length
, const UnicodeString
&symbol
,
3556 UnicodeSet
*sset
, UChar32 schar
)
3559 return sset
->contains(schar
);
3562 return text
.compare(position
, length
, symbol
) == 0;
3565 UBool
DecimalFormat::matchDecimal(UChar32 symbolChar
,
3566 UBool sawDecimal
, UChar32 sawDecimalChar
,
3567 const UnicodeSet
*sset
, UChar32 schar
) {
3569 return schar
==sawDecimalChar
;
3570 } else if(schar
==symbolChar
) {
3572 } else if(sset
!=NULL
) {
3573 return sset
->contains(schar
);
3579 UBool
DecimalFormat::matchGrouping(UChar32 groupingChar
,
3580 UBool sawGrouping
, UChar32 sawGroupingChar
,
3581 const UnicodeSet
*sset
,
3582 UChar32
/*decimalChar*/, const UnicodeSet
*decimalSet
,
3585 return schar
==sawGroupingChar
; // previously found
3586 } else if(schar
==groupingChar
) {
3587 return TRUE
; // char from symbols
3588 } else if(sset
!=NULL
) {
3589 return sset
->contains(schar
) && // in groupingSet but...
3590 ((decimalSet
==NULL
) || !decimalSet
->contains(schar
)); // Exclude decimalSet from groupingSet
3598 //------------------------------------------------------------------------------
3599 // Gets the pointer to the localized decimal format symbols
3601 const DecimalFormatSymbols
*
3602 DecimalFormat::getDecimalFormatSymbols() const
3607 //------------------------------------------------------------------------------
3608 // De-owning the current localized symbols and adopt the new symbols.
3611 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
3613 if (symbolsToAdopt
== NULL
) {
3614 return; // do not allow caller to set fSymbols to NULL
3617 UBool sameSymbols
= FALSE
;
3618 if (fSymbols
!= NULL
) {
3619 sameSymbols
= (UBool
)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) ==
3620 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) &&
3621 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) ==
3622 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
3626 fSymbols
= symbolsToAdopt
;
3628 // If the currency symbols are the same, there is no need to recalculate.
3629 setCurrencyForSymbols();
3631 expandAffixes(NULL
);
3632 #if UCONFIG_FORMAT_FASTPATHS_49
3636 //------------------------------------------------------------------------------
3637 // Setting the symbols is equlivalent to adopting a newly created localized
3641 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
3643 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
3644 #if UCONFIG_FORMAT_FASTPATHS_49
3650 const CurrencyPluralInfo
*
3651 DecimalFormat::getCurrencyPluralInfo(void) const
3653 return fCurrencyPluralInfo
;
3658 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo
* toAdopt
)
3660 if (toAdopt
!= NULL
) {
3661 delete fCurrencyPluralInfo
;
3662 fCurrencyPluralInfo
= toAdopt
;
3663 // re-set currency affix patterns and currency affixes.
3664 if (fCurrencySignCount
!= fgCurrencySignCountZero
) {
3665 UErrorCode status
= U_ZERO_ERROR
;
3666 if (fAffixPatternsForCurrency
) {
3667 deleteHashForAffixPattern();
3669 setupCurrencyAffixPatterns(status
);
3670 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
3671 // only setup the affixes of the plural pattern.
3672 setupCurrencyAffixes(fFormatPattern
, FALSE
, TRUE
, status
);
3676 #if UCONFIG_FORMAT_FASTPATHS_49
3682 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo
& info
)
3684 adoptCurrencyPluralInfo(info
.clone());
3685 #if UCONFIG_FORMAT_FASTPATHS_49
3692 * Update the currency object to match the symbols. This method
3693 * is used only when the caller has passed in a symbols object
3694 * that may not be the default object for its locale.
3697 DecimalFormat::setCurrencyForSymbols() {
3699 Update the affix strings accroding to symbols in order to keep
3700 the affix strings up to date.
3704 // With the introduction of the Currency object, the currency
3705 // symbols in the DFS object are ignored. For backward
3706 // compatibility, we check any explicitly set DFS object. If it
3707 // is a default symbols object for its locale, we change the
3708 // currency object to one for that locale. If it is custom,
3709 // we set the currency to null.
3710 UErrorCode ec
= U_ZERO_ERROR
;
3711 const UChar
* c
= NULL
;
3712 const char* loc
= fSymbols
->getLocale().getName();
3713 UChar intlCurrencySymbol
[4];
3714 ucurr_forLocale(loc
, intlCurrencySymbol
, 4, &ec
);
3715 UnicodeString currencySymbol
;
3717 uprv_getStaticCurrencyName(intlCurrencySymbol
, loc
, currencySymbol
, ec
);
3719 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) == currencySymbol
3720 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) == UnicodeString(intlCurrencySymbol
))
3722 // Trap an error in mapping locale to currency. If we can't
3723 // map, then don't fail and set the currency to "".
3724 c
= intlCurrencySymbol
;
3726 ec
= U_ZERO_ERROR
; // reset local error code!
3727 setCurrencyInternally(c
, ec
);
3728 #if UCONFIG_FORMAT_FASTPATHS_49
3734 //------------------------------------------------------------------------------
3735 // Gets the positive prefix of the number pattern.
3738 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
3740 result
= fPositivePrefix
;
3744 //------------------------------------------------------------------------------
3745 // Sets the positive prefix of the number pattern.
3748 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
3750 fPositivePrefix
= newValue
;
3751 delete fPosPrefixPattern
;
3752 fPosPrefixPattern
= 0;
3753 #if UCONFIG_FORMAT_FASTPATHS_49
3758 //------------------------------------------------------------------------------
3759 // Gets the negative prefix of the number pattern.
3762 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
3764 result
= fNegativePrefix
;
3768 //------------------------------------------------------------------------------
3769 // Gets the negative prefix of the number pattern.
3772 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
3774 fNegativePrefix
= newValue
;
3775 delete fNegPrefixPattern
;
3776 fNegPrefixPattern
= 0;
3777 #if UCONFIG_FORMAT_FASTPATHS_49
3782 //------------------------------------------------------------------------------
3783 // Gets the positive suffix of the number pattern.
3786 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
3788 result
= fPositiveSuffix
;
3792 //------------------------------------------------------------------------------
3793 // Sets the positive suffix of the number pattern.
3796 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
3798 fPositiveSuffix
= newValue
;
3799 delete fPosSuffixPattern
;
3800 fPosSuffixPattern
= 0;
3801 #if UCONFIG_FORMAT_FASTPATHS_49
3806 //------------------------------------------------------------------------------
3807 // Gets the negative suffix of the number pattern.
3810 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
3812 result
= fNegativeSuffix
;
3816 //------------------------------------------------------------------------------
3817 // Sets the negative suffix of the number pattern.
3820 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
3822 fNegativeSuffix
= newValue
;
3823 delete fNegSuffixPattern
;
3824 fNegSuffixPattern
= 0;
3825 #if UCONFIG_FORMAT_FASTPATHS_49
3830 //------------------------------------------------------------------------------
3831 // Gets the multiplier of the number pattern.
3832 // Multipliers are stored as decimal numbers (DigitLists) because that
3833 // is the most convenient for muliplying or dividing the numbers to be formatted.
3834 // A NULL multiplier implies one, and the scaling operations are skipped.
3837 DecimalFormat::getMultiplier() const
3839 if (fMultiplier
== NULL
) {
3842 return fMultiplier
->getLong();
3846 //------------------------------------------------------------------------------
3847 // Sets the multiplier of the number pattern.
3849 DecimalFormat::setMultiplier(int32_t newValue
)
3851 // if (newValue == 0) {
3852 // throw new IllegalArgumentException("Bad multiplier: " + newValue);
3854 if (newValue
== 0) {
3855 newValue
= 1; // one being the benign default value for a multiplier.
3857 if (newValue
== 1) {
3861 if (fMultiplier
== NULL
) {
3862 fMultiplier
= new DigitList
;
3864 if (fMultiplier
!= NULL
) {
3865 fMultiplier
->set(newValue
);
3868 #if UCONFIG_FORMAT_FASTPATHS_49
3874 * Get the rounding increment.
3875 * @return A positive rounding increment, or 0.0 if rounding
3877 * @see #setRoundingIncrement
3878 * @see #getRoundingMode
3879 * @see #setRoundingMode
3881 double DecimalFormat::getRoundingIncrement() const {
3882 if (fRoundingIncrement
== NULL
) {
3885 return fRoundingIncrement
->getDouble();
3890 * Set the rounding increment. This method also controls whether
3891 * rounding is enabled.
3892 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
3893 * Negative increments are equivalent to 0.0.
3894 * @see #getRoundingIncrement
3895 * @see #getRoundingMode
3896 * @see #setRoundingMode
3898 void DecimalFormat::setRoundingIncrement(double newValue
) {
3899 if (newValue
> 0.0) {
3900 if (fRoundingIncrement
== NULL
) {
3901 fRoundingIncrement
= new DigitList();
3903 if (fRoundingIncrement
!= NULL
) {
3904 fRoundingIncrement
->set(newValue
);
3908 // These statements are executed if newValue is less than 0.0
3909 // or fRoundingIncrement could not be created.
3910 delete fRoundingIncrement
;
3911 fRoundingIncrement
= NULL
;
3912 #if UCONFIG_FORMAT_FASTPATHS_49
3918 * Get the rounding mode.
3919 * @return A rounding mode
3920 * @see #setRoundingIncrement
3921 * @see #getRoundingIncrement
3922 * @see #setRoundingMode
3924 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
3925 return fRoundingMode
;
3929 * Set the rounding mode. This has no effect unless the rounding
3930 * increment is greater than zero.
3931 * @param roundingMode A rounding mode
3932 * @see #setRoundingIncrement
3933 * @see #getRoundingIncrement
3934 * @see #getRoundingMode
3936 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
3937 fRoundingMode
= roundingMode
;
3938 #if UCONFIG_FORMAT_FASTPATHS_49
3944 * Get the width to which the output of <code>format()</code> is padded.
3945 * @return the format width, or zero if no padding is in effect
3946 * @see #setFormatWidth
3947 * @see #getPadCharacter
3948 * @see #setPadCharacter
3949 * @see #getPadPosition
3950 * @see #setPadPosition
3952 int32_t DecimalFormat::getFormatWidth() const {
3953 return fFormatWidth
;
3957 * Set the width to which the output of <code>format()</code> is padded.
3958 * This method also controls whether padding is enabled.
3959 * @param width the width to which to pad the result of
3960 * <code>format()</code>, or zero to disable padding. A negative
3961 * width is equivalent to 0.
3962 * @see #getFormatWidth
3963 * @see #getPadCharacter
3964 * @see #setPadCharacter
3965 * @see #getPadPosition
3966 * @see #setPadPosition
3968 void DecimalFormat::setFormatWidth(int32_t width
) {
3969 fFormatWidth
= (width
> 0) ? width
: 0;
3970 #if UCONFIG_FORMAT_FASTPATHS_49
3975 UnicodeString
DecimalFormat::getPadCharacterString() const {
3976 return UnicodeString(fPad
);
3979 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
3980 if (padChar
.length() > 0) {
3981 fPad
= padChar
.char32At(0);
3986 #if UCONFIG_FORMAT_FASTPATHS_49
3992 * Get the position at which padding will take place. This is the location
3993 * at which padding will be inserted if the result of <code>format()</code>
3994 * is shorter than the format width.
3995 * @return the pad position, one of <code>kPadBeforePrefix</code>,
3996 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3997 * <code>kPadAfterSuffix</code>.
3998 * @see #setFormatWidth
3999 * @see #getFormatWidth
4000 * @see #setPadCharacter
4001 * @see #getPadCharacter
4002 * @see #setPadPosition
4003 * @see #kPadBeforePrefix
4004 * @see #kPadAfterPrefix
4005 * @see #kPadBeforeSuffix
4006 * @see #kPadAfterSuffix
4008 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
4009 return fPadPosition
;
4013 * <strong><font face=helvetica color=red>NEW</font></strong>
4014 * Set the position at which padding will take place. This is the location
4015 * at which padding will be inserted if the result of <code>format()</code>
4016 * is shorter than the format width. This has no effect unless padding is
4018 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
4019 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
4020 * <code>kPadAfterSuffix</code>.
4021 * @see #setFormatWidth
4022 * @see #getFormatWidth
4023 * @see #setPadCharacter
4024 * @see #getPadCharacter
4025 * @see #getPadPosition
4026 * @see #kPadBeforePrefix
4027 * @see #kPadAfterPrefix
4028 * @see #kPadBeforeSuffix
4029 * @see #kPadAfterSuffix
4031 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
4032 fPadPosition
= padPos
;
4033 #if UCONFIG_FORMAT_FASTPATHS_49
4039 * Return whether or not scientific notation is used.
4040 * @return TRUE if this object formats and parses scientific notation
4041 * @see #setScientificNotation
4042 * @see #getMinimumExponentDigits
4043 * @see #setMinimumExponentDigits
4044 * @see #isExponentSignAlwaysShown
4045 * @see #setExponentSignAlwaysShown
4047 UBool
DecimalFormat::isScientificNotation() const {
4048 return fUseExponentialNotation
;
4052 * Set whether or not scientific notation is used.
4053 * @param useScientific TRUE if this object formats and parses scientific
4055 * @see #isScientificNotation
4056 * @see #getMinimumExponentDigits
4057 * @see #setMinimumExponentDigits
4058 * @see #isExponentSignAlwaysShown
4059 * @see #setExponentSignAlwaysShown
4061 void DecimalFormat::setScientificNotation(UBool useScientific
) {
4062 fUseExponentialNotation
= useScientific
;
4063 #if UCONFIG_FORMAT_FASTPATHS_49
4069 * Return the minimum exponent digits that will be shown.
4070 * @return the minimum exponent digits that will be shown
4071 * @see #setScientificNotation
4072 * @see #isScientificNotation
4073 * @see #setMinimumExponentDigits
4074 * @see #isExponentSignAlwaysShown
4075 * @see #setExponentSignAlwaysShown
4077 int8_t DecimalFormat::getMinimumExponentDigits() const {
4078 return fMinExponentDigits
;
4082 * Set the minimum exponent digits that will be shown. This has no
4083 * effect unless scientific notation is in use.
4084 * @param minExpDig a value >= 1 indicating the fewest exponent digits
4085 * that will be shown. Values less than 1 will be treated as 1.
4086 * @see #setScientificNotation
4087 * @see #isScientificNotation
4088 * @see #getMinimumExponentDigits
4089 * @see #isExponentSignAlwaysShown
4090 * @see #setExponentSignAlwaysShown
4092 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
4093 fMinExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
4094 #if UCONFIG_FORMAT_FASTPATHS_49
4100 * Return whether the exponent sign is always shown.
4101 * @return TRUE if the exponent is always prefixed with either the
4102 * localized minus sign or the localized plus sign, false if only negative
4103 * exponents are prefixed with the localized minus sign.
4104 * @see #setScientificNotation
4105 * @see #isScientificNotation
4106 * @see #setMinimumExponentDigits
4107 * @see #getMinimumExponentDigits
4108 * @see #setExponentSignAlwaysShown
4110 UBool
DecimalFormat::isExponentSignAlwaysShown() const {
4111 return fExponentSignAlwaysShown
;
4115 * Set whether the exponent sign is always shown. This has no effect
4116 * unless scientific notation is in use.
4117 * @param expSignAlways TRUE if the exponent is always prefixed with either
4118 * the localized minus sign or the localized plus sign, false if only
4119 * negative exponents are prefixed with the localized minus sign.
4120 * @see #setScientificNotation
4121 * @see #isScientificNotation
4122 * @see #setMinimumExponentDigits
4123 * @see #getMinimumExponentDigits
4124 * @see #isExponentSignAlwaysShown
4126 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
4127 fExponentSignAlwaysShown
= expSignAlways
;
4128 #if UCONFIG_FORMAT_FASTPATHS_49
4133 //------------------------------------------------------------------------------
4134 // Gets the grouping size of the number pattern. For example, thousand or 10
4135 // thousand groupings.
4138 DecimalFormat::getGroupingSize() const
4140 return isGroupingUsed() ? fGroupingSize
: 0;
4143 //------------------------------------------------------------------------------
4144 // Gets the grouping size of the number pattern.
4147 DecimalFormat::setGroupingSize(int32_t newValue
)
4149 fGroupingSize
= newValue
;
4150 #if UCONFIG_FORMAT_FASTPATHS_49
4155 //------------------------------------------------------------------------------
4158 DecimalFormat::getSecondaryGroupingSize() const
4160 return fGroupingSize2
;
4163 //------------------------------------------------------------------------------
4166 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
4168 fGroupingSize2
= newValue
;
4169 #if UCONFIG_FORMAT_FASTPATHS_49
4174 //------------------------------------------------------------------------------
4175 // Checks if to show the decimal separator.
4178 DecimalFormat::isDecimalSeparatorAlwaysShown() const
4180 return fDecimalSeparatorAlwaysShown
;
4183 //------------------------------------------------------------------------------
4184 // Sets to always show the decimal separator.
4187 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
4189 fDecimalSeparatorAlwaysShown
= newValue
;
4190 #if UCONFIG_FORMAT_FASTPATHS_49
4195 //------------------------------------------------------------------------------
4196 // Checks if decimal point pattern match is required
4198 DecimalFormat::isDecimalPatternMatchRequired(void) const
4200 return fBoolFlags
.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED
);
4203 //------------------------------------------------------------------------------
4204 // Checks if decimal point pattern match is required
4207 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue
)
4209 fBoolFlags
.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED
, newValue
);
4213 //------------------------------------------------------------------------------
4214 // Emits the pattern of this DecimalFormat instance.
4217 DecimalFormat::toPattern(UnicodeString
& result
) const
4219 return toPattern(result
, FALSE
);
4222 //------------------------------------------------------------------------------
4223 // Emits the localized pattern this DecimalFormat instance.
4226 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
4228 return toPattern(result
, TRUE
);
4231 //------------------------------------------------------------------------------
4233 * Expand the affix pattern strings into the expanded affix strings. If any
4234 * affix pattern string is null, do not expand it. This method should be
4235 * called any time the symbols or the affix patterns change in order to keep
4236 * the expanded affix strings up to date.
4237 * This method also will be called before formatting if format currency
4238 * plural names, since the plural name is not a static one, it is
4239 * based on the currency plural count, the affix will be known only
4240 * after the currency plural count is know.
4241 * In which case, the parameter
4242 * 'pluralCount' will be a non-null currency plural count.
4243 * In all other cases, the 'pluralCount' is null, which means it is not needed.
4245 void DecimalFormat::expandAffixes(const UnicodeString
* pluralCount
) {
4246 FieldPositionHandler none
;
4247 if (fPosPrefixPattern
!= 0) {
4248 expandAffix(*fPosPrefixPattern
, fPositivePrefix
, 0, none
, FALSE
, pluralCount
);
4250 if (fPosSuffixPattern
!= 0) {
4251 expandAffix(*fPosSuffixPattern
, fPositiveSuffix
, 0, none
, FALSE
, pluralCount
);
4253 if (fNegPrefixPattern
!= 0) {
4254 expandAffix(*fNegPrefixPattern
, fNegativePrefix
, 0, none
, FALSE
, pluralCount
);
4256 if (fNegSuffixPattern
!= 0) {
4257 expandAffix(*fNegSuffixPattern
, fNegativeSuffix
, 0, none
, FALSE
, pluralCount
);
4261 s
.append(UnicodeString("["))
4262 .append(DEREFSTR(fPosPrefixPattern
)).append((UnicodeString
)"|").append(DEREFSTR(fPosSuffixPattern
))
4263 .append((UnicodeString
)";") .append(DEREFSTR(fNegPrefixPattern
)).append((UnicodeString
)"|").append(DEREFSTR(fNegSuffixPattern
))
4264 .append((UnicodeString
)"]->[")
4265 .append(fPositivePrefix
).append((UnicodeString
)"|").append(fPositiveSuffix
)
4266 .append((UnicodeString
)";") .append(fNegativePrefix
).append((UnicodeString
)"|").append(fNegativeSuffix
)
4267 .append((UnicodeString
)"]\n");
4273 * Expand an affix pattern into an affix string. All characters in the
4274 * pattern are literal unless prefixed by kQuote. The following characters
4275 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
4276 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
4277 * kCurrencySign + kCurrencySign), it is interpreted as an international
4278 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
4279 * currency plural long names, such as "US Dollars".
4280 * Any other character after a kQuote represents itself.
4281 * kQuote must be followed by another character; kQuote may not occur by
4282 * itself at the end of the pattern.
4284 * This method is used in two distinct ways. First, it is used to expand
4285 * the stored affix patterns into actual affixes. For this usage, doFormat
4286 * must be false. Second, it is used to expand the stored affix patterns
4287 * given a specific number (doFormat == true), for those rare cases in
4288 * which a currency format references a ChoiceFormat (e.g., en_IN display
4289 * name for INR). The number itself is taken from digitList.
4291 * When used in the first way, this method has a side effect: It sets
4292 * currencyChoice to a ChoiceFormat object, if the currency's display name
4293 * in this locale is a ChoiceFormat pattern (very rare). It only does this
4294 * if currencyChoice is null to start with.
4296 * @param pattern the non-null, fPossibly empty pattern
4297 * @param affix string to receive the expanded equivalent of pattern.
4298 * Previous contents are deleted.
4299 * @param doFormat if false, then the pattern will be expanded, and if a
4300 * currency symbol is encountered that expands to a ChoiceFormat, the
4301 * currencyChoice member variable will be initialized if it is null. If
4302 * doFormat is true, then it is assumed that the currencyChoice has been
4303 * created, and it will be used to format the value in digitList.
4304 * @param pluralCount the plural count. It is only used for currency
4305 * plural format. In which case, it is the plural
4306 * count of the currency amount. For example,
4307 * in en_US, it is the singular "one", or the plural
4308 * "other". For all other cases, it is null, and
4309 * is not being used.
4311 void DecimalFormat::expandAffix(const UnicodeString
& pattern
,
4312 UnicodeString
& affix
,
4314 FieldPositionHandler
& handler
,
4316 const UnicodeString
* pluralCount
) const {
4318 for (int i
=0; i
<pattern
.length(); ) {
4319 UChar32 c
= pattern
.char32At(i
);
4322 c
= pattern
.char32At(i
);
4324 int beginIdx
= affix
.length();
4326 case kCurrencySign
: {
4327 // As of ICU 2.2 we use the currency object, and
4328 // ignore the currency symbols in the DFS, unless
4329 // we have a null currency object. This occurs if
4330 // resurrecting a pre-2.2 object or if the user
4331 // sets a custom DFS.
4332 UBool intl
= i
<pattern
.length() &&
4333 pattern
.char32At(i
) == kCurrencySign
;
4334 UBool plural
= FALSE
;
4337 plural
= i
<pattern
.length() &&
4338 pattern
.char32At(i
) == kCurrencySign
;
4344 const UChar
* currencyUChars
= getCurrency();
4345 if (currencyUChars
[0] != 0) {
4346 UErrorCode ec
= U_ZERO_ERROR
;
4347 if (plural
&& pluralCount
!= NULL
) {
4348 // plural name is only needed when pluralCount != null,
4349 // which means when formatting currency plural names.
4350 // For other cases, pluralCount == null,
4351 // and plural names are not needed.
4353 CharString pluralCountChar
;
4354 pluralCountChar
.appendInvariantChars(*pluralCount
, ec
);
4355 UBool isChoiceFormat
;
4356 const UChar
* s
= ucurr_getPluralName(currencyUChars
,
4357 fSymbols
!= NULL
? fSymbols
->getLocale().getName() :
4358 Locale::getDefault().getName(), &isChoiceFormat
,
4359 pluralCountChar
.data(), &len
, &ec
);
4360 affix
+= UnicodeString(s
, len
);
4361 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
4363 affix
.append(currencyUChars
, -1);
4364 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
4367 UBool isChoiceFormat
;
4368 // If fSymbols is NULL, use default locale
4369 const UChar
* s
= ucurr_getName(currencyUChars
,
4370 fSymbols
!= NULL
? fSymbols
->getLocale().getName() : Locale::getDefault().getName(),
4371 UCURR_SYMBOL_NAME
, &isChoiceFormat
, &len
, &ec
);
4372 if (isChoiceFormat
) {
4373 // Two modes here: If doFormat is false, we set up
4374 // currencyChoice. If doFormat is true, we use the
4375 // previously created currencyChoice to format the
4376 // value in digitList.
4378 // If the currency is handled by a ChoiceFormat,
4379 // then we're not going to use the expanded
4380 // patterns. Instantiate the ChoiceFormat and
4382 if (fCurrencyChoice
== NULL
) {
4383 // TODO Replace double-check with proper thread-safe code
4384 ChoiceFormat
* fmt
= new ChoiceFormat(UnicodeString(s
), ec
);
4385 if (U_SUCCESS(ec
)) {
4387 if (fCurrencyChoice
== NULL
) {
4389 ((DecimalFormat
*)this)->fCurrencyChoice
= fmt
;
4396 // We could almost return null or "" here, since the
4397 // expanded affixes are almost not used at all
4398 // in this situation. However, one method --
4399 // toPattern() -- still does use the expanded
4400 // affixes, in order to set up a padding
4401 // pattern. We use the CURRENCY_SIGN as a
4403 affix
.append(kCurrencySign
);
4405 if (fCurrencyChoice
!= NULL
) {
4406 FieldPosition
pos(0); // ignored
4410 fCurrencyChoice
->format(number
, affix
, pos
);
4412 // We only arrive here if the currency choice
4413 // format in the locale data is INVALID.
4414 affix
.append(currencyUChars
, -1);
4415 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
4420 affix
+= UnicodeString(s
, len
);
4421 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
4425 affix
+= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
4427 affix
+= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
4429 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
4433 case kPatternPercent
:
4434 affix
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
4435 handler
.addAttribute(kPercentField
, beginIdx
, affix
.length());
4437 case kPatternPerMill
:
4438 affix
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
4439 handler
.addAttribute(kPermillField
, beginIdx
, affix
.length());
4442 affix
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
4443 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
4446 affix
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
4447 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
4461 * Append an affix to the given StringBuffer.
4462 * @param buf buffer to append to
4466 int32_t DecimalFormat::appendAffix(UnicodeString
& buf
, double number
,
4467 FieldPositionHandler
& handler
,
4468 UBool isNegative
, UBool isPrefix
) const {
4469 // plural format precedes choice format
4470 if (fCurrencyChoice
!= 0 &&
4471 fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
4472 const UnicodeString
* affixPat
;
4474 affixPat
= isNegative
? fNegPrefixPattern
: fPosPrefixPattern
;
4476 affixPat
= isNegative
? fNegSuffixPattern
: fPosSuffixPattern
;
4479 UnicodeString affixBuf
;
4480 expandAffix(*affixPat
, affixBuf
, number
, handler
, TRUE
, NULL
);
4481 buf
.append(affixBuf
);
4482 return affixBuf
.length();
4484 // else someone called a function that reset the pattern.
4487 const UnicodeString
* affix
;
4488 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
4489 // TODO: get an accurate count of visible fraction digits.
4490 UnicodeString pluralCount
;
4491 int32_t minFractionDigits
= this->getMinimumFractionDigits();
4492 if (minFractionDigits
> 0) {
4493 FixedDecimal
ni(number
, this->getMinimumFractionDigits());
4494 pluralCount
= fCurrencyPluralInfo
->getPluralRules()->select(ni
);
4496 pluralCount
= fCurrencyPluralInfo
->getPluralRules()->select(number
);
4498 AffixesForCurrency
* oneSet
;
4499 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
4500 oneSet
= (AffixesForCurrency
*)fPluralAffixesForCurrency
->get(pluralCount
);
4502 oneSet
= (AffixesForCurrency
*)fAffixesForCurrency
->get(pluralCount
);
4505 affix
= isNegative
? &oneSet
->negPrefixForCurrency
:
4506 &oneSet
->posPrefixForCurrency
;
4508 affix
= isNegative
? &oneSet
->negSuffixForCurrency
:
4509 &oneSet
->posSuffixForCurrency
;
4513 affix
= isNegative
? &fNegativePrefix
: &fPositivePrefix
;
4515 affix
= isNegative
? &fNegativeSuffix
: &fPositiveSuffix
;
4519 int32_t begin
= (int) buf
.length();
4523 if (handler
.isRecording()) {
4524 int32_t offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
));
4526 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
4527 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4530 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
4532 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
4533 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4536 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
4538 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
4539 handler
.addAttribute(kSignField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4542 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
4544 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
4545 handler
.addAttribute(kPercentField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4548 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
4550 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
4551 handler
.addAttribute(kPermillField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4554 return affix
->length();
4558 * Appends an affix pattern to the given StringBuffer, quoting special
4559 * characters as needed. Uses the internal affix pattern, if that exists,
4560 * or the literal affix, if the internal affix pattern is null. The
4561 * appended string will generate the same affix pattern (or literal affix)
4562 * when passed to toPattern().
4564 * @param appendTo the affix string is appended to this
4565 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
4566 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
4567 * Ignored unless affixPattern is null. If affixPattern is null, then
4568 * expAffix is appended as a literal affix.
4569 * @param localized true if the appended pattern should contain localized
4570 * pattern characters; otherwise, non-localized pattern chars are appended
4572 void DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
4573 const UnicodeString
* affixPattern
,
4574 const UnicodeString
& expAffix
,
4575 UBool localized
) const {
4576 if (affixPattern
== 0) {
4577 appendAffixPattern(appendTo
, expAffix
, localized
);
4580 for (int pos
=0; pos
<affixPattern
->length(); pos
=i
) {
4581 i
= affixPattern
->indexOf(kQuote
, pos
);
4584 affixPattern
->extractBetween(pos
, affixPattern
->length(), s
);
4585 appendAffixPattern(appendTo
, s
, localized
);
4590 affixPattern
->extractBetween(pos
, i
, s
);
4591 appendAffixPattern(appendTo
, s
, localized
);
4593 UChar32 c
= affixPattern
->char32At(++i
);
4596 appendTo
.append(c
).append(c
);
4597 // Fall through and append another kQuote below
4598 } else if (c
== kCurrencySign
&&
4599 i
<affixPattern
->length() &&
4600 affixPattern
->char32At(i
) == kCurrencySign
) {
4602 appendTo
.append(c
).append(c
);
4603 } else if (localized
) {
4605 case kPatternPercent
:
4606 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
4608 case kPatternPerMill
:
4609 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
4612 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
4615 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
4628 * Append an affix to the given StringBuffer, using quotes if
4629 * there are special characters. Single quotes themselves must be
4630 * escaped in either case.
4633 DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
4634 const UnicodeString
& affix
,
4635 UBool localized
) const {
4638 needQuote
= affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
)) >= 0
4639 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
)) >= 0
4640 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
)) >= 0
4641 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
)) >= 0
4642 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
)) >= 0
4643 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
)) >= 0
4644 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
)) >= 0
4645 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
)) >= 0
4646 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) >= 0
4647 || affix
.indexOf(kCurrencySign
) >= 0;
4650 needQuote
= affix
.indexOf(kPatternZeroDigit
) >= 0
4651 || affix
.indexOf(kPatternGroupingSeparator
) >= 0
4652 || affix
.indexOf(kPatternDecimalSeparator
) >= 0
4653 || affix
.indexOf(kPatternPercent
) >= 0
4654 || affix
.indexOf(kPatternPerMill
) >= 0
4655 || affix
.indexOf(kPatternDigit
) >= 0
4656 || affix
.indexOf(kPatternSeparator
) >= 0
4657 || affix
.indexOf(kPatternExponent
) >= 0
4658 || affix
.indexOf(kPatternPlus
) >= 0
4659 || affix
.indexOf(kPatternMinus
) >= 0
4660 || affix
.indexOf(kCurrencySign
) >= 0;
4663 appendTo
+= (UChar
)0x0027 /*'\''*/;
4664 if (affix
.indexOf((UChar
)0x0027 /*'\''*/) < 0)
4667 for (int32_t j
= 0; j
< affix
.length(); ) {
4668 UChar32 c
= affix
.char32At(j
);
4671 if (c
== 0x0027 /*'\''*/)
4676 appendTo
+= (UChar
)0x0027 /*'\''*/;
4679 //------------------------------------------------------------------------------
4682 DecimalFormat::toPattern(UnicodeString
& result
, UBool localized
) const
4684 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
4685 // the prefix or suffix pattern might not be defined yet,
4686 // so they can not be synthesized,
4687 // instead, get them directly.
4688 // but it might not be the actual pattern used in formatting.
4689 // the actual pattern used in formatting depends on the
4690 // formatted number's plural count.
4691 result
= fFormatPattern
;
4695 UChar32 zero
, sigDigit
= kPatternSignificantDigit
;
4696 UnicodeString digit
, group
;
4698 int32_t roundingDecimalPos
= 0; // Pos of decimal in roundingDigits
4699 UnicodeString roundingDigits
;
4700 int32_t padPos
= (fFormatWidth
> 0) ? fPadPosition
: -1;
4701 UnicodeString padSpec
;
4702 UBool useSigDig
= areSignificantDigitsUsed();
4705 digit
.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
4706 group
.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
4707 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
4709 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
4713 digit
.append((UChar
)kPatternDigit
);
4714 group
.append((UChar
)kPatternGroupingSeparator
);
4715 zero
= (UChar32
)kPatternZeroDigit
;
4717 if (fFormatWidth
> 0) {
4719 padSpec
.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
4722 padSpec
.append((UChar
)kPatternPadEscape
);
4724 padSpec
.append(fPad
);
4726 if (fRoundingIncrement
!= NULL
) {
4727 for(i
=0; i
<fRoundingIncrement
->getCount(); ++i
) {
4728 roundingDigits
.append(zero
+(fRoundingIncrement
->getDigitValue(i
))); // Convert to Unicode digit
4730 roundingDecimalPos
= fRoundingIncrement
->getDecimalAt();
4732 for (int32_t part
=0; part
<2; ++part
) {
4733 if (padPos
== kPadBeforePrefix
) {
4734 result
.append(padSpec
);
4736 appendAffixPattern(result
,
4737 (part
==0 ? fPosPrefixPattern
: fNegPrefixPattern
),
4738 (part
==0 ? fPositivePrefix
: fNegativePrefix
),
4740 if (padPos
== kPadAfterPrefix
&& ! padSpec
.isEmpty()) {
4741 result
.append(padSpec
);
4743 int32_t sub0Start
= result
.length();
4744 int32_t g
= isGroupingUsed() ? _max(0, fGroupingSize
) : 0;
4745 if (g
> 0 && fGroupingSize2
> 0 && fGroupingSize2
!= fGroupingSize
) {
4746 g
+= fGroupingSize2
;
4748 int32_t maxDig
= 0, minDig
= 0, maxSigDig
= 0;
4750 minDig
= getMinimumSignificantDigits();
4751 maxDig
= maxSigDig
= getMaximumSignificantDigits();
4753 minDig
= getMinimumIntegerDigits();
4754 maxDig
= getMaximumIntegerDigits();
4756 if (fUseExponentialNotation
) {
4757 if (maxDig
> kMaxScientificIntegerDigits
) {
4760 } else if (useSigDig
) {
4761 maxDig
= _max(maxDig
, g
+1);
4763 maxDig
= _max(_max(g
, getMinimumIntegerDigits()),
4764 roundingDecimalPos
) + 1;
4766 for (i
= maxDig
; i
> 0; --i
) {
4767 if (!fUseExponentialNotation
&& i
<maxDig
&&
4768 isGroupingPosition(i
)) {
4769 result
.append(group
);
4772 // #@,@### (maxSigDig == 5, minSigDig == 2)
4773 // 65 4321 (1-based pos, count from the right)
4774 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
4775 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
4776 if (maxSigDig
>= i
&& i
> (maxSigDig
- minDig
)) {
4777 result
.append(sigDigit
);
4779 result
.append(digit
);
4782 if (! roundingDigits
.isEmpty()) {
4783 int32_t pos
= roundingDecimalPos
- i
;
4784 if (pos
>= 0 && pos
< roundingDigits
.length()) {
4785 result
.append((UChar
) (roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
4790 result
.append(zero
);
4792 result
.append(digit
);
4797 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown
) {
4799 result
+= getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
4802 result
.append((UChar
)kPatternDecimalSeparator
);
4805 int32_t pos
= roundingDecimalPos
;
4806 for (i
= 0; i
< getMaximumFractionDigits(); ++i
) {
4807 if (! roundingDigits
.isEmpty() && pos
< roundingDigits
.length()) {
4809 result
.append(zero
);
4812 result
.append((UChar
)(roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
4817 if (i
<getMinimumFractionDigits()) {
4818 result
.append(zero
);
4821 result
.append(digit
);
4825 if (fUseExponentialNotation
) {
4827 result
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
4830 result
.append((UChar
)kPatternExponent
);
4832 if (fExponentSignAlwaysShown
) {
4834 result
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
4837 result
.append((UChar
)kPatternPlus
);
4840 for (i
=0; i
<fMinExponentDigits
; ++i
) {
4841 result
.append(zero
);
4844 if (! padSpec
.isEmpty() && !fUseExponentialNotation
) {
4845 int32_t add
= fFormatWidth
- result
.length() + sub0Start
4847 ? fPositivePrefix
.length() + fPositiveSuffix
.length()
4848 : fNegativePrefix
.length() + fNegativeSuffix
.length());
4850 result
.insert(sub0Start
, digit
);
4853 // Only add a grouping separator if we have at least
4854 // 2 additional characters to be added, so we don't
4855 // end up with ",###".
4856 if (add
>1 && isGroupingPosition(maxDig
)) {
4857 result
.insert(sub0Start
, group
);
4862 if (fPadPosition
== kPadBeforeSuffix
&& ! padSpec
.isEmpty()) {
4863 result
.append(padSpec
);
4866 appendAffixPattern(result
, fPosSuffixPattern
, fPositiveSuffix
, localized
);
4867 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
4868 result
.append(padSpec
);
4870 UBool isDefault
= FALSE
;
4871 if ((fNegSuffixPattern
== fPosSuffixPattern
&& // both null
4872 fNegativeSuffix
== fPositiveSuffix
)
4873 || (fNegSuffixPattern
!= 0 && fPosSuffixPattern
!= 0 &&
4874 *fNegSuffixPattern
== *fPosSuffixPattern
))
4876 if (fNegPrefixPattern
!= NULL
&& fPosPrefixPattern
!= NULL
)
4878 int32_t length
= fPosPrefixPattern
->length();
4879 isDefault
= fNegPrefixPattern
->length() == (length
+2) &&
4880 (*fNegPrefixPattern
)[(int32_t)0] == kQuote
&&
4881 (*fNegPrefixPattern
)[(int32_t)1] == kPatternMinus
&&
4882 fNegPrefixPattern
->compare(2, length
, *fPosPrefixPattern
, 0, length
) == 0;
4885 fNegPrefixPattern
== NULL
&& fPosPrefixPattern
== NULL
)
4887 int32_t length
= fPositivePrefix
.length();
4888 isDefault
= fNegativePrefix
.length() == (length
+1) &&
4889 fNegativePrefix
.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) == 0 &&
4890 fNegativePrefix
.compare(1, length
, fPositivePrefix
, 0, length
) == 0;
4894 break; // Don't output default negative subpattern
4897 result
+= getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
);
4900 result
.append((UChar
)kPatternSeparator
);
4904 appendAffixPattern(result
, fNegSuffixPattern
, fNegativeSuffix
, localized
);
4905 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
4906 result
.append(padSpec
);
4914 //------------------------------------------------------------------------------
4917 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
4919 UParseError parseError
;
4920 applyPattern(pattern
, FALSE
, parseError
, status
);
4923 //------------------------------------------------------------------------------
4926 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
4927 UParseError
& parseError
,
4930 applyPattern(pattern
, FALSE
, parseError
, status
);
4932 //------------------------------------------------------------------------------
4935 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
4937 UParseError parseError
;
4938 applyPattern(pattern
, TRUE
,parseError
,status
);
4941 //------------------------------------------------------------------------------
4944 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
4945 UParseError
& parseError
,
4948 applyPattern(pattern
, TRUE
,parseError
,status
);
4951 //------------------------------------------------------------------------------
4954 DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString
& pattern
,
4956 UParseError
& parseError
,
4959 if (U_FAILURE(status
))
4963 DecimalFormatPatternParser patternParser
;
4965 patternParser
.useSymbols(*fSymbols
);
4967 fFormatPattern
= pattern
;
4968 DecimalFormatPattern out
;
4969 patternParser
.applyPatternWithoutExpandAffix(
4974 if (U_FAILURE(status
)) {
4978 setMinimumIntegerDigits(out
.fMinimumIntegerDigits
);
4979 setMaximumIntegerDigits(out
.fMaximumIntegerDigits
);
4980 setMinimumFractionDigits(out
.fMinimumFractionDigits
);
4981 setMaximumFractionDigits(out
.fMaximumFractionDigits
);
4982 setSignificantDigitsUsed(out
.fUseSignificantDigits
);
4983 if (out
.fUseSignificantDigits
) {
4984 setMinimumSignificantDigits(out
.fMinimumSignificantDigits
);
4985 setMaximumSignificantDigits(out
.fMaximumSignificantDigits
);
4987 fUseExponentialNotation
= out
.fUseExponentialNotation
;
4988 if (out
.fUseExponentialNotation
) {
4989 fMinExponentDigits
= out
.fMinExponentDigits
;
4991 fExponentSignAlwaysShown
= out
.fExponentSignAlwaysShown
;
4992 fCurrencySignCount
= out
.fCurrencySignCount
;
4993 setGroupingUsed(out
.fGroupingUsed
);
4994 if (out
.fGroupingUsed
) {
4995 fGroupingSize
= out
.fGroupingSize
;
4996 fGroupingSize2
= out
.fGroupingSize2
;
4998 setMultiplier(out
.fMultiplier
);
4999 fDecimalSeparatorAlwaysShown
= out
.fDecimalSeparatorAlwaysShown
;
5000 fFormatWidth
= out
.fFormatWidth
;
5001 if (out
.fRoundingIncrementUsed
) {
5002 if (fRoundingIncrement
!= NULL
) {
5003 *fRoundingIncrement
= out
.fRoundingIncrement
;
5005 fRoundingIncrement
= new DigitList(out
.fRoundingIncrement
);
5007 if (fRoundingIncrement
== NULL
) {
5008 status
= U_MEMORY_ALLOCATION_ERROR
;
5013 setRoundingIncrement(0.0);
5016 switch (out
.fPadPosition
) {
5017 case DecimalFormatPattern::kPadBeforePrefix
:
5018 fPadPosition
= kPadBeforePrefix
;
5020 case DecimalFormatPattern::kPadAfterPrefix
:
5021 fPadPosition
= kPadAfterPrefix
;
5023 case DecimalFormatPattern::kPadBeforeSuffix
:
5024 fPadPosition
= kPadBeforeSuffix
;
5026 case DecimalFormatPattern::kPadAfterSuffix
:
5027 fPadPosition
= kPadAfterSuffix
;
5030 copyString(out
.fNegPrefixPattern
, out
.fNegPatternsBogus
, fNegPrefixPattern
, status
);
5031 copyString(out
.fNegSuffixPattern
, out
.fNegPatternsBogus
, fNegSuffixPattern
, status
);
5032 copyString(out
.fPosPrefixPattern
, out
.fPosPatternsBogus
, fPosPrefixPattern
, status
);
5033 copyString(out
.fPosSuffixPattern
, out
.fPosPatternsBogus
, fPosSuffixPattern
, status
);
5038 DecimalFormat::expandAffixAdjustWidth(const UnicodeString
* pluralCount
) {
5039 expandAffixes(pluralCount
);
5040 if (fFormatWidth
> 0) {
5041 // Finish computing format width (see above)
5042 // TODO: how to handle fFormatWidth,
5043 // need to save in f(Plural)AffixesForCurrecy?
5044 fFormatWidth
+= fPositivePrefix
.length() + fPositiveSuffix
.length();
5050 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
5052 UParseError
& parseError
,
5055 // do the following re-set first. since they change private data by
5056 // apply pattern again.
5057 if (pattern
.indexOf(kCurrencySign
) != -1) {
5058 if (fCurrencyPluralInfo
== NULL
) {
5059 // initialize currencyPluralInfo if needed
5060 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
5062 if (fAffixPatternsForCurrency
== NULL
) {
5063 setupCurrencyAffixPatterns(status
);
5065 if (pattern
.indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
5066 // only setup the affixes of the current pattern.
5067 setupCurrencyAffixes(pattern
, TRUE
, FALSE
, status
);
5070 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
5071 expandAffixAdjustWidth(NULL
);
5072 #if UCONFIG_FORMAT_FASTPATHS_49
5079 DecimalFormat::applyPatternInternally(const UnicodeString
& pluralCount
,
5080 const UnicodeString
& pattern
,
5082 UParseError
& parseError
,
5083 UErrorCode
& status
) {
5084 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
5085 expandAffixAdjustWidth(&pluralCount
);
5086 #if UCONFIG_FORMAT_FASTPATHS_49
5093 * Sets the maximum number of digits allowed in the integer portion of a
5095 * @see NumberFormat#setMaximumIntegerDigits
5097 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
5098 NumberFormat::setMaximumIntegerDigits(_min(newValue
, gDefaultMaxIntegerDigits
));
5099 #if UCONFIG_FORMAT_FASTPATHS_49
5105 * Sets the minimum number of digits allowed in the integer portion of a
5106 * number. This override limits the integer digit count to 309.
5107 * @see NumberFormat#setMinimumIntegerDigits
5109 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
5110 NumberFormat::setMinimumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
5111 #if UCONFIG_FORMAT_FASTPATHS_49
5117 * Sets the maximum number of digits allowed in the fraction portion of a
5118 * number. This override limits the fraction digit count to 340.
5119 * @see NumberFormat#setMaximumFractionDigits
5121 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
5122 NumberFormat::setMaximumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
5123 #if UCONFIG_FORMAT_FASTPATHS_49
5129 * Sets the minimum number of digits allowed in the fraction portion of a
5130 * number. This override limits the fraction digit count to 340.
5131 * @see NumberFormat#setMinimumFractionDigits
5133 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
5134 NumberFormat::setMinimumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
5135 #if UCONFIG_FORMAT_FASTPATHS_49
5140 int32_t DecimalFormat::getMinimumSignificantDigits() const {
5141 return fMinSignificantDigits
;
5144 int32_t DecimalFormat::getMaximumSignificantDigits() const {
5145 return fMaxSignificantDigits
;
5148 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
5152 // pin max sig dig to >= min
5153 int32_t max
= _max(fMaxSignificantDigits
, min
);
5154 fMinSignificantDigits
= min
;
5155 fMaxSignificantDigits
= max
;
5156 fUseSignificantDigits
= TRUE
;
5157 #if UCONFIG_FORMAT_FASTPATHS_49
5162 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
5166 // pin min sig dig to 1..max
5167 U_ASSERT(fMinSignificantDigits
>= 1);
5168 int32_t min
= _min(fMinSignificantDigits
, max
);
5169 fMinSignificantDigits
= min
;
5170 fMaxSignificantDigits
= max
;
5171 fUseSignificantDigits
= TRUE
;
5172 #if UCONFIG_FORMAT_FASTPATHS_49
5177 UBool
DecimalFormat::areSignificantDigitsUsed() const {
5178 return fUseSignificantDigits
;
5181 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
5182 fUseSignificantDigits
= useSignificantDigits
;
5183 #if UCONFIG_FORMAT_FASTPATHS_49
5188 void DecimalFormat::setCurrencyInternally(const UChar
* theCurrency
,
5190 // If we are a currency format, then modify our affixes to
5191 // encode the currency symbol for the given currency in our
5192 // locale, and adjust the decimal digits and rounding for the
5195 // Note: The code is ordered so that this object is *not changed*
5196 // until we are sure we are going to succeed.
5198 // NULL or empty currency is *legal* and indicates no currency.
5199 UBool isCurr
= (theCurrency
&& *theCurrency
);
5201 double rounding
= 0.0;
5203 if (fCurrencySignCount
!= fgCurrencySignCountZero
&& isCurr
) {
5204 rounding
= ucurr_getRoundingIncrementForUsage(theCurrency
, fCurrencyUsage
, &ec
);
5205 frac
= ucurr_getDefaultFractionDigitsForUsage(theCurrency
, fCurrencyUsage
, &ec
);
5208 NumberFormat::setCurrency(theCurrency
, ec
);
5209 if (U_FAILURE(ec
)) return;
5211 if (fCurrencySignCount
!= fgCurrencySignCountZero
) {
5212 // NULL or empty currency is *legal* and indicates no currency.
5214 setRoundingIncrement(rounding
);
5215 setMinimumFractionDigits(frac
);
5216 setMaximumFractionDigits(frac
);
5218 expandAffixes(NULL
);
5220 #if UCONFIG_FORMAT_FASTPATHS_49
5225 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
5226 // set the currency before compute affixes to get the right currency names
5227 NumberFormat::setCurrency(theCurrency
, ec
);
5228 if (fFormatPattern
.indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
5229 UnicodeString savedPtn
= fFormatPattern
;
5230 setupCurrencyAffixes(fFormatPattern
, TRUE
, TRUE
, ec
);
5231 UParseError parseErr
;
5232 applyPattern(savedPtn
, FALSE
, parseErr
, ec
);
5234 // set the currency after apply pattern to get the correct rounding/fraction
5235 setCurrencyInternally(theCurrency
, ec
);
5236 #if UCONFIG_FORMAT_FASTPATHS_49
5241 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext
, UErrorCode
* ec
){
5242 fCurrencyUsage
= newContext
;
5244 const UChar
* theCurrency
= getCurrency();
5246 // We set rounding/digit based on currency context
5248 double rounding
= ucurr_getRoundingIncrementForUsage(theCurrency
, fCurrencyUsage
, ec
);
5249 int32_t frac
= ucurr_getDefaultFractionDigitsForUsage(theCurrency
, fCurrencyUsage
, ec
);
5251 if (U_SUCCESS(*ec
)) {
5252 setRoundingIncrement(rounding
);
5253 setMinimumFractionDigits(frac
);
5254 setMaximumFractionDigits(frac
);
5259 UCurrencyUsage
DecimalFormat::getCurrencyUsage() const {
5260 return fCurrencyUsage
;
5263 // Deprecated variant with no UErrorCode parameter
5264 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
5265 UErrorCode ec
= U_ZERO_ERROR
;
5266 setCurrency(theCurrency
, ec
);
5267 #if UCONFIG_FORMAT_FASTPATHS_49
5272 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
5273 if (fSymbols
== NULL
) {
5274 ec
= U_MEMORY_ALLOCATION_ERROR
;
5278 const UChar
* c
= getCurrency();
5280 const UnicodeString
&intl
=
5281 fSymbols
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
5282 c
= intl
.getBuffer(); // ok for intl to go out of scope
5284 u_strncpy(result
, c
, 3);
5289 * Return the number of fraction digits to display, or the total
5290 * number of digits for significant digit formats and exponential
5294 DecimalFormat::precision() const {
5295 if (areSignificantDigitsUsed()) {
5296 return getMaximumSignificantDigits();
5297 } else if (fUseExponentialNotation
) {
5298 return getMinimumIntegerDigits() + getMaximumFractionDigits();
5300 return getMaximumFractionDigits();
5305 // TODO: template algorithm
5307 DecimalFormat::initHashForAffix(UErrorCode
& status
) {
5308 if ( U_FAILURE(status
) ) {
5312 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
5313 status
= U_MEMORY_ALLOCATION_ERROR
;
5316 if ( U_FAILURE(status
) ) {
5320 hTable
->setValueComparator(decimfmtAffixValueComparator
);
5325 DecimalFormat::initHashForAffixPattern(UErrorCode
& status
) {
5326 if ( U_FAILURE(status
) ) {
5330 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
5331 status
= U_MEMORY_ALLOCATION_ERROR
;
5334 if ( U_FAILURE(status
) ) {
5338 hTable
->setValueComparator(decimfmtAffixPatternValueComparator
);
5343 DecimalFormat::deleteHashForAffix(Hashtable
*& table
)
5345 if ( table
== NULL
) {
5348 int32_t pos
= UHASH_FIRST
;
5349 const UHashElement
* element
= NULL
;
5350 while ( (element
= table
->nextElement(pos
)) != NULL
) {
5351 const UHashTok valueTok
= element
->value
;
5352 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
5362 DecimalFormat::deleteHashForAffixPattern()
5364 if ( fAffixPatternsForCurrency
== NULL
) {
5367 int32_t pos
= UHASH_FIRST
;
5368 const UHashElement
* element
= NULL
;
5369 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
5370 const UHashTok valueTok
= element
->value
;
5371 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
5374 delete fAffixPatternsForCurrency
;
5375 fAffixPatternsForCurrency
= NULL
;
5380 DecimalFormat::copyHashForAffixPattern(const Hashtable
* source
,
5382 UErrorCode
& status
) {
5383 if ( U_FAILURE(status
) ) {
5386 int32_t pos
= UHASH_FIRST
;
5387 const UHashElement
* element
= NULL
;
5389 while ( (element
= source
->nextElement(pos
)) != NULL
) {
5390 const UHashTok keyTok
= element
->key
;
5391 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
5392 const UHashTok valueTok
= element
->value
;
5393 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
5394 AffixPatternsForCurrency
* copy
= new AffixPatternsForCurrency(
5395 value
->negPrefixPatternForCurrency
,
5396 value
->negSuffixPatternForCurrency
,
5397 value
->posPrefixPatternForCurrency
,
5398 value
->posSuffixPatternForCurrency
,
5399 value
->patternType
);
5400 target
->put(UnicodeString(*key
), copy
, status
);
5401 if ( U_FAILURE(status
) ) {
5408 // this is only overridden to call handleChanged() for fastpath purposes.
5410 DecimalFormat::setGroupingUsed(UBool newValue
) {
5411 NumberFormat::setGroupingUsed(newValue
);
5415 // this is only overridden to call handleChanged() for fastpath purposes.
5417 DecimalFormat::setParseIntegerOnly(UBool newValue
) {
5418 NumberFormat::setParseIntegerOnly(newValue
);
5422 // this is only overridden to call handleChanged() for fastpath purposes.
5423 // setContext doesn't affect the fastPath right now, but this is called for completeness
5425 DecimalFormat::setContext(UDisplayContext value
, UErrorCode
& status
) {
5426 NumberFormat::setContext(value
, status
);
5431 DecimalFormat
& DecimalFormat::setAttribute( UNumberFormatAttribute attr
,
5433 UErrorCode
&status
) {
5434 if(U_FAILURE(status
)) return *this;
5437 case UNUM_LENIENT_PARSE
:
5438 setLenient(newValue
!=0);
5441 case UNUM_PARSE_INT_ONLY
:
5442 setParseIntegerOnly(newValue
!=0);
5445 case UNUM_GROUPING_USED
:
5446 setGroupingUsed(newValue
!=0);
5449 case UNUM_DECIMAL_ALWAYS_SHOWN
:
5450 setDecimalSeparatorAlwaysShown(newValue
!=0);
5453 case UNUM_MAX_INTEGER_DIGITS
:
5454 setMaximumIntegerDigits(newValue
);
5457 case UNUM_MIN_INTEGER_DIGITS
:
5458 setMinimumIntegerDigits(newValue
);
5461 case UNUM_INTEGER_DIGITS
:
5462 setMinimumIntegerDigits(newValue
);
5463 setMaximumIntegerDigits(newValue
);
5466 case UNUM_MAX_FRACTION_DIGITS
:
5467 setMaximumFractionDigits(newValue
);
5470 case UNUM_MIN_FRACTION_DIGITS
:
5471 setMinimumFractionDigits(newValue
);
5474 case UNUM_FRACTION_DIGITS
:
5475 setMinimumFractionDigits(newValue
);
5476 setMaximumFractionDigits(newValue
);
5479 case UNUM_SIGNIFICANT_DIGITS_USED
:
5480 setSignificantDigitsUsed(newValue
!=0);
5483 case UNUM_MAX_SIGNIFICANT_DIGITS
:
5484 setMaximumSignificantDigits(newValue
);
5487 case UNUM_MIN_SIGNIFICANT_DIGITS
:
5488 setMinimumSignificantDigits(newValue
);
5491 case UNUM_MULTIPLIER
:
5492 setMultiplier(newValue
);
5495 case UNUM_GROUPING_SIZE
:
5496 setGroupingSize(newValue
);
5499 case UNUM_ROUNDING_MODE
:
5500 setRoundingMode((DecimalFormat::ERoundingMode
)newValue
);
5503 case UNUM_FORMAT_WIDTH
:
5504 setFormatWidth(newValue
);
5507 case UNUM_PADDING_POSITION
:
5508 /** The position at which padding will take place. */
5509 setPadPosition((DecimalFormat::EPadPosition
)newValue
);
5512 case UNUM_SECONDARY_GROUPING_SIZE
:
5513 setSecondaryGroupingSize(newValue
);
5516 #if UCONFIG_HAVE_PARSEALLINPUT
5517 case UNUM_PARSE_ALL_INPUT
:
5518 setParseAllInput((UNumberFormatAttributeValue
)newValue
);
5522 /* These are stored in fBoolFlags */
5523 case UNUM_PARSE_NO_EXPONENT
:
5524 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
5525 case UNUM_PARSE_DECIMAL_MARK_REQUIRED
:
5526 if(!fBoolFlags
.isValidValue(newValue
)) {
5527 status
= U_ILLEGAL_ARGUMENT_ERROR
;
5529 fBoolFlags
.set(attr
, newValue
);
5537 case UNUM_CURRENCY_USAGE
:
5538 setCurrencyUsage((UCurrencyUsage
)newValue
, &status
);
5541 status
= U_UNSUPPORTED_ERROR
;
5547 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr
,
5548 UErrorCode
&status
) const {
5549 if(U_FAILURE(status
)) return -1;
5551 case UNUM_LENIENT_PARSE
:
5554 case UNUM_PARSE_INT_ONLY
:
5555 return isParseIntegerOnly();
5557 case UNUM_GROUPING_USED
:
5558 return isGroupingUsed();
5560 case UNUM_DECIMAL_ALWAYS_SHOWN
:
5561 return isDecimalSeparatorAlwaysShown();
5563 case UNUM_MAX_INTEGER_DIGITS
:
5564 return getMaximumIntegerDigits();
5566 case UNUM_MIN_INTEGER_DIGITS
:
5567 return getMinimumIntegerDigits();
5569 case UNUM_INTEGER_DIGITS
:
5570 // TBD: what should this return?
5571 return getMinimumIntegerDigits();
5573 case UNUM_MAX_FRACTION_DIGITS
:
5574 return getMaximumFractionDigits();
5576 case UNUM_MIN_FRACTION_DIGITS
:
5577 return getMinimumFractionDigits();
5579 case UNUM_FRACTION_DIGITS
:
5580 // TBD: what should this return?
5581 return getMinimumFractionDigits();
5583 case UNUM_SIGNIFICANT_DIGITS_USED
:
5584 return areSignificantDigitsUsed();
5586 case UNUM_MAX_SIGNIFICANT_DIGITS
:
5587 return getMaximumSignificantDigits();
5589 case UNUM_MIN_SIGNIFICANT_DIGITS
:
5590 return getMinimumSignificantDigits();
5592 case UNUM_MULTIPLIER
:
5593 return getMultiplier();
5595 case UNUM_GROUPING_SIZE
:
5596 return getGroupingSize();
5598 case UNUM_ROUNDING_MODE
:
5599 return getRoundingMode();
5601 case UNUM_FORMAT_WIDTH
:
5602 return getFormatWidth();
5604 case UNUM_PADDING_POSITION
:
5605 return getPadPosition();
5607 case UNUM_SECONDARY_GROUPING_SIZE
:
5608 return getSecondaryGroupingSize();
5610 /* These are stored in fBoolFlags */
5611 case UNUM_PARSE_NO_EXPONENT
:
5612 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
5613 case UNUM_PARSE_DECIMAL_MARK_REQUIRED
:
5614 return fBoolFlags
.get(attr
);
5619 case UNUM_CURRENCY_USAGE
:
5620 return fCurrencyUsage
;
5623 status
= U_UNSUPPORTED_ERROR
;
5627 return -1; /* undefined */
5630 #if UCONFIG_HAVE_PARSEALLINPUT
5631 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value
) {
5632 fParseAllInput
= value
;
5633 #if UCONFIG_FORMAT_FASTPATHS_49
5640 DecimalFormat::copyHashForAffix(const Hashtable
* source
,
5642 UErrorCode
& status
) {
5643 if ( U_FAILURE(status
) ) {
5646 int32_t pos
= UHASH_FIRST
;
5647 const UHashElement
* element
= NULL
;
5649 while ( (element
= source
->nextElement(pos
)) != NULL
) {
5650 const UHashTok keyTok
= element
->key
;
5651 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
5653 const UHashTok valueTok
= element
->value
;
5654 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
5655 AffixesForCurrency
* copy
= new AffixesForCurrency(
5656 value
->negPrefixForCurrency
,
5657 value
->negSuffixForCurrency
,
5658 value
->posPrefixForCurrency
,
5659 value
->posSuffixForCurrency
);
5660 target
->put(UnicodeString(*key
), copy
, status
);
5661 if ( U_FAILURE(status
) ) {
5670 #endif /* #if !UCONFIG_NO_FORMATTING */