2 *******************************************************************************
3 * Copyright (C) 1997-2013, 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"
75 * On certain platforms, round is a macro defined in math.h
76 * This undefine is to avoid conflict between the macro and
77 * the function defined below.
86 /* == Fastpath calculation. ==
88 #if UCONFIG_FORMAT_FASTPATHS_49
89 inline DecimalFormatInternal
& internalData(uint8_t *reserved
) {
90 return *reinterpret_cast<DecimalFormatInternal
*>(reserved
);
92 inline const DecimalFormatInternal
& internalData(const uint8_t *reserved
) {
93 return *reinterpret_cast<const DecimalFormatInternal
*>(reserved
);
98 /* For currency parsing purose,
99 * Need to remember all prefix patterns and suffix patterns of
100 * every currency format pattern,
101 * including the pattern of default currecny style
102 * and plural currency style. And the patterns are set through applyPattern.
104 struct AffixPatternsForCurrency
: public UMemory
{
105 // negative prefix pattern
106 UnicodeString negPrefixPatternForCurrency
;
107 // negative suffix pattern
108 UnicodeString negSuffixPatternForCurrency
;
109 // positive prefix pattern
110 UnicodeString posPrefixPatternForCurrency
;
111 // positive suffix pattern
112 UnicodeString posSuffixPatternForCurrency
;
115 AffixPatternsForCurrency(const UnicodeString
& negPrefix
,
116 const UnicodeString
& negSuffix
,
117 const UnicodeString
& posPrefix
,
118 const UnicodeString
& posSuffix
,
120 negPrefixPatternForCurrency
= negPrefix
;
121 negSuffixPatternForCurrency
= negSuffix
;
122 posPrefixPatternForCurrency
= posPrefix
;
123 posSuffixPatternForCurrency
= posSuffix
;
128 /* affix for currency formatting when the currency sign in the pattern
129 * equals to 3, such as the pattern contains 3 currency sign or
130 * the formatter style is currency plural format style.
132 struct AffixesForCurrency
: public UMemory
{
134 UnicodeString negPrefixForCurrency
;
136 UnicodeString negSuffixForCurrency
;
138 UnicodeString posPrefixForCurrency
;
140 UnicodeString posSuffixForCurrency
;
144 AffixesForCurrency(const UnicodeString
& negPrefix
,
145 const UnicodeString
& negSuffix
,
146 const UnicodeString
& posPrefix
,
147 const UnicodeString
& posSuffix
) {
148 negPrefixForCurrency
= negPrefix
;
149 negSuffixForCurrency
= negSuffix
;
150 posPrefixForCurrency
= posPrefix
;
151 posSuffixForCurrency
= posSuffix
;
160 static UBool U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
);
165 static UBool U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
);
169 U_CALLCONV
decimfmtAffixValueComparator(UHashTok val1
, UHashTok val2
) {
170 const AffixesForCurrency
* affix_1
=
171 (AffixesForCurrency
*)val1
.pointer
;
172 const AffixesForCurrency
* affix_2
=
173 (AffixesForCurrency
*)val2
.pointer
;
174 return affix_1
->negPrefixForCurrency
== affix_2
->negPrefixForCurrency
&&
175 affix_1
->negSuffixForCurrency
== affix_2
->negSuffixForCurrency
&&
176 affix_1
->posPrefixForCurrency
== affix_2
->posPrefixForCurrency
&&
177 affix_1
->posSuffixForCurrency
== affix_2
->posSuffixForCurrency
;
182 U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
) {
183 const AffixPatternsForCurrency
* affix_1
=
184 (AffixPatternsForCurrency
*)val1
.pointer
;
185 const AffixPatternsForCurrency
* affix_2
=
186 (AffixPatternsForCurrency
*)val2
.pointer
;
187 return affix_1
->negPrefixPatternForCurrency
==
188 affix_2
->negPrefixPatternForCurrency
&&
189 affix_1
->negSuffixPatternForCurrency
==
190 affix_2
->negSuffixPatternForCurrency
&&
191 affix_1
->posPrefixPatternForCurrency
==
192 affix_2
->posPrefixPatternForCurrency
&&
193 affix_1
->posSuffixPatternForCurrency
==
194 affix_2
->posSuffixPatternForCurrency
&&
195 affix_1
->patternType
== affix_2
->patternType
;
202 static void _debugout(const char *f
, int l
, const UnicodeString
& s
) {
204 s
.extract((int32_t) 0, s
.length(), buf
);
205 printf("%s:%d: %s\n", f
,l
, buf
);
207 #define debugout(x) _debugout(__FILE__,__LINE__,x)
208 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
209 static const UnicodeString
dbg_null("<NULL>","");
210 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
218 // *****************************************************************************
219 // class DecimalFormat
220 // *****************************************************************************
222 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat
)
224 // Constants for characters used in programmatic (unlocalized) patterns.
225 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
226 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
227 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
228 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
229 #define kPatternPerMill ((UChar)0x2030)
230 #define kPatternPercent ((UChar)0x0025) /*'%'*/
231 #define kPatternDigit ((UChar)0x0023) /*'#'*/
232 #define kPatternSeparator ((UChar)0x003B) /*';'*/
233 #define kPatternExponent ((UChar)0x0045) /*'E'*/
234 #define kPatternPlus ((UChar)0x002B) /*'+'*/
235 #define kPatternMinus ((UChar)0x002D) /*'-'*/
236 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
237 #define kQuote ((UChar)0x0027) /*'\''*/
239 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
240 * is used in patterns and substitued with either the currency symbol,
241 * or if it is doubled, with the international currency symbol. If the
242 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
243 * replaced with the monetary decimal separator.
245 #define kCurrencySign ((UChar)0x00A4)
246 #define kDefaultPad ((UChar)0x0020) /* */
248 const int32_t DecimalFormat::kDoubleIntegerDigits
= 309;
249 const int32_t DecimalFormat::kDoubleFractionDigits
= 340;
251 const int32_t DecimalFormat::kMaxScientificIntegerDigits
= 8;
254 * These are the tags we expect to see in normal resource bundle files associated
257 const char DecimalFormat::fgNumberPatterns
[]="NumberPatterns"; // Deprecated - not used
258 static const char fgNumberElements
[]="NumberElements";
259 static const char fgLatn
[]="latn";
260 static const char fgPatterns
[]="patterns";
261 static const char fgDecimalFormat
[]="decimalFormat";
262 static const char fgCurrencyFormat
[]="currencyFormat";
263 static const UChar fgTripleCurrencySign
[] = {0xA4, 0xA4, 0xA4, 0};
265 inline int32_t _min(int32_t a
, int32_t b
) { return (a
<b
) ? a
: b
; }
266 inline int32_t _max(int32_t a
, int32_t b
) { return (a
<b
) ? b
: a
; }
268 //------------------------------------------------------------------------------
269 // Constructs a DecimalFormat instance in the default locale.
271 DecimalFormat::DecimalFormat(UErrorCode
& status
) {
273 UParseError parseError
;
274 construct(status
, parseError
);
277 //------------------------------------------------------------------------------
278 // Constructs a DecimalFormat instance with the specified number format
279 // pattern in the default locale.
281 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
282 UErrorCode
& status
) {
284 UParseError parseError
;
285 construct(status
, parseError
, &pattern
);
288 //------------------------------------------------------------------------------
289 // Constructs a DecimalFormat instance with the specified number format
290 // pattern and the number format symbols in the default locale. The
291 // created instance owns the symbols.
293 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
294 DecimalFormatSymbols
* symbolsToAdopt
,
295 UErrorCode
& status
) {
297 UParseError parseError
;
298 if (symbolsToAdopt
== NULL
)
299 status
= U_ILLEGAL_ARGUMENT_ERROR
;
300 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
303 DecimalFormat::DecimalFormat( const UnicodeString
& pattern
,
304 DecimalFormatSymbols
* symbolsToAdopt
,
305 UParseError
& parseErr
,
306 UErrorCode
& status
) {
308 if (symbolsToAdopt
== NULL
)
309 status
= U_ILLEGAL_ARGUMENT_ERROR
;
310 construct(status
,parseErr
, &pattern
, symbolsToAdopt
);
313 //------------------------------------------------------------------------------
314 // Constructs a DecimalFormat instance with the specified number format
315 // pattern and the number format symbols in the default locale. The
316 // created instance owns the clone of the symbols.
318 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
319 const DecimalFormatSymbols
& symbols
,
320 UErrorCode
& status
) {
322 UParseError parseError
;
323 construct(status
, parseError
, &pattern
, new DecimalFormatSymbols(symbols
));
326 //------------------------------------------------------------------------------
327 // Constructs a DecimalFormat instance with the specified number format
328 // pattern, the number format symbols, and the number format style.
329 // The created instance owns the clone of the symbols.
331 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
332 DecimalFormatSymbols
* symbolsToAdopt
,
333 UNumberFormatStyle style
,
334 UErrorCode
& status
) {
337 UParseError parseError
;
338 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
341 //-----------------------------------------------------------------------------
342 // Common DecimalFormat initialization.
343 // Put all fields of an uninitialized object into a known state.
344 // Common code, shared by all constructors.
346 DecimalFormat::init(UErrorCode
&status
) {
347 fPosPrefixPattern
= 0;
348 fPosSuffixPattern
= 0;
349 fNegPrefixPattern
= 0;
350 fNegSuffixPattern
= 0;
356 fDecimalSeparatorAlwaysShown
= FALSE
;
358 fUseSignificantDigits
= FALSE
;
359 fMinSignificantDigits
= 1;
360 fMaxSignificantDigits
= 6;
361 fUseExponentialNotation
= FALSE
;
362 fMinExponentDigits
= 0;
363 fExponentSignAlwaysShown
= FALSE
;
365 fRoundingIncrement
= 0;
366 fRoundingMode
= kRoundHalfEven
;
369 fPadPosition
= kPadBeforePrefix
;
370 fStyle
= UNUM_DECIMAL
;
371 fCurrencySignCount
= 0;
372 fAffixPatternsForCurrency
= NULL
;
373 fAffixesForCurrency
= NULL
;
374 fPluralAffixesForCurrency
= NULL
;
375 fCurrencyPluralInfo
= NULL
;
376 #if UCONFIG_HAVE_PARSEALLINPUT
377 fParseAllInput
= UNUM_MAYBE
;
380 #if UCONFIG_FORMAT_FASTPATHS_49
381 DecimalFormatInternal
&data
= internalData(fReserved
);
382 data
.fFastFormatStatus
=kFastpathUNKNOWN
; // don't try to calculate the fastpath until later.
383 data
.fFastParseStatus
=kFastpathUNKNOWN
; // don't try to calculate the fastpath until later.
385 // only do this once per obj.
386 DecimalFormatStaticSets::initSets(&status
);
389 //------------------------------------------------------------------------------
390 // Constructs a DecimalFormat instance with the specified number format
391 // pattern and the number format symbols in the desired locale. The
392 // created instance owns the symbols.
395 DecimalFormat::construct(UErrorCode
& status
,
396 UParseError
& parseErr
,
397 const UnicodeString
* pattern
,
398 DecimalFormatSymbols
* symbolsToAdopt
)
400 fSymbols
= symbolsToAdopt
; // Do this BEFORE aborting on status failure!!!
401 fRoundingIncrement
= NULL
;
402 fRoundingMode
= kRoundHalfEven
;
403 fPad
= kPatternPadEscape
;
404 fPadPosition
= kPadBeforePrefix
;
405 if (U_FAILURE(status
))
408 fPosPrefixPattern
= fPosSuffixPattern
= NULL
;
409 fNegPrefixPattern
= fNegSuffixPattern
= NULL
;
413 fDecimalSeparatorAlwaysShown
= FALSE
;
414 fUseExponentialNotation
= FALSE
;
415 fMinExponentDigits
= 0;
417 if (fSymbols
== NULL
)
419 fSymbols
= new DecimalFormatSymbols(Locale::getDefault(), status
);
422 status
= U_MEMORY_ALLOCATION_ERROR
;
426 UErrorCode nsStatus
= U_ZERO_ERROR
;
427 NumberingSystem
*ns
= NumberingSystem::createInstance(nsStatus
);
428 if (U_FAILURE(nsStatus
)) {
434 // Uses the default locale's number format pattern if there isn't
439 UResourceBundle
*top
= ures_open(NULL
, Locale::getDefault().getName(), &status
);
441 UResourceBundle
*resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, NULL
, &status
);
442 resource
= ures_getByKeyWithFallback(resource
, ns
->getName(), resource
, &status
);
443 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
444 const UChar
*resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
445 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(fgLatn
,ns
->getName())) {
446 status
= U_ZERO_ERROR
;
447 resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, resource
, &status
);
448 resource
= ures_getByKeyWithFallback(resource
, fgLatn
, resource
, &status
);
449 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
450 resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
452 str
.setTo(TRUE
, resStr
, len
);
454 ures_close(resource
);
460 if (U_FAILURE(status
))
465 if (pattern
->indexOf((UChar
)kCurrencySign
) >= 0) {
466 // If it looks like we are going to use a currency pattern
467 // then do the time consuming lookup.
468 setCurrencyForSymbols();
470 setCurrencyInternally(NULL
, status
);
473 const UnicodeString
* patternUsed
;
474 UnicodeString currencyPluralPatternForOther
;
476 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
477 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
478 if (U_FAILURE(status
)) {
482 // the pattern used in format is not fixed until formatting,
483 // in which, the number is known and
484 // will be used to pick the right pattern based on plural count.
485 // Here, set the pattern as the pattern of plural count == "other".
486 // For most locale, the patterns are probably the same for all
487 // plural count. If not, the right pattern need to be re-applied
489 fCurrencyPluralInfo
->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther
);
490 patternUsed
= ¤cyPluralPatternForOther
;
492 setCurrencyForSymbols();
495 patternUsed
= pattern
;
498 if (patternUsed
->indexOf(kCurrencySign
) != -1) {
499 // initialize for currency, not only for plural format,
500 // but also for mix parsing
501 if (fCurrencyPluralInfo
== NULL
) {
502 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
503 if (U_FAILURE(status
)) {
507 // need it for mix parsing
508 setupCurrencyAffixPatterns(status
);
509 // expanded affixes for plural names
510 if (patternUsed
->indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
511 setupCurrencyAffixes(*patternUsed
, TRUE
, TRUE
, status
);
515 applyPatternWithoutExpandAffix(*patternUsed
,FALSE
, parseErr
, status
);
518 if (fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
519 expandAffixAdjustWidth(NULL
);
522 // If it was a currency format, apply the appropriate rounding by
523 // resetting the currency. NOTE: this copies fCurrency on top of itself.
524 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
525 setCurrencyInternally(getCurrency(), status
);
527 #if UCONFIG_FORMAT_FASTPATHS_49
528 DecimalFormatInternal
&data
= internalData(fReserved
);
529 data
.fFastFormatStatus
= kFastpathNO
; // allow it to be calculated
530 data
.fFastParseStatus
= kFastpathNO
; // allow it to be calculated
537 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode
& status
) {
538 if (U_FAILURE(status
)) {
541 UParseError parseErr
;
542 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
543 if (U_FAILURE(status
)) {
547 NumberingSystem
*ns
= NumberingSystem::createInstance(fSymbols
->getLocale(),status
);
548 if (U_FAILURE(status
)) {
552 // Save the default currency patterns of this locale.
553 // Here, chose onlyApplyPatternWithoutExpandAffix without
554 // expanding the affix patterns into affixes.
555 UnicodeString currencyPattern
;
556 UErrorCode error
= U_ZERO_ERROR
;
558 UResourceBundle
*resource
= ures_open(NULL
, fSymbols
->getLocale().getName(), &error
);
559 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, fgNumberElements
, NULL
, &error
);
560 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &error
);
561 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
563 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
564 if ( error
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(ns
->getName(),fgLatn
)) {
565 error
= U_ZERO_ERROR
;
566 resource
= ures_getByKeyWithFallback(numElements
, fgLatn
, resource
, &error
);
567 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
568 patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
570 ures_close(numElements
);
571 ures_close(resource
);
574 if (U_SUCCESS(error
)) {
575 applyPatternWithoutExpandAffix(UnicodeString(patResStr
, patLen
), false,
577 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
583 fAffixPatternsForCurrency
->put(UNICODE_STRING("default", 7), affixPtn
, status
);
586 // save the unique currency plural patterns of this locale.
587 Hashtable
* pluralPtn
= fCurrencyPluralInfo
->fPluralCountToCurrencyUnitPattern
;
588 const UHashElement
* element
= NULL
;
590 Hashtable pluralPatternSet
;
591 while ((element
= pluralPtn
->nextElement(pos
)) != NULL
) {
592 const UHashTok valueTok
= element
->value
;
593 const UnicodeString
* value
= (UnicodeString
*)valueTok
.pointer
;
594 const UHashTok keyTok
= element
->key
;
595 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
596 if (pluralPatternSet
.geti(*value
) != 1) {
597 pluralPatternSet
.puti(*value
, 1, status
);
598 applyPatternWithoutExpandAffix(*value
, false, parseErr
, status
);
599 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
605 fAffixPatternsForCurrency
->put(*key
, affixPtn
, status
);
612 DecimalFormat::setupCurrencyAffixes(const UnicodeString
& pattern
,
613 UBool setupForCurrentPattern
,
614 UBool setupForPluralPattern
,
615 UErrorCode
& status
) {
616 if (U_FAILURE(status
)) {
619 UParseError parseErr
;
620 if (setupForCurrentPattern
) {
621 if (fAffixesForCurrency
) {
622 deleteHashForAffix(fAffixesForCurrency
);
624 fAffixesForCurrency
= initHashForAffix(status
);
625 if (U_SUCCESS(status
)) {
626 applyPatternWithoutExpandAffix(pattern
, false, parseErr
, status
);
627 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
628 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
629 if (U_SUCCESS(status
)) {
630 const UnicodeString
* pluralCount
;
631 while ((pluralCount
= keywords
->snext(status
)) != NULL
) {
632 if ( U_SUCCESS(status
) ) {
633 expandAffixAdjustWidth(pluralCount
);
634 AffixesForCurrency
* affix
= new AffixesForCurrency(
635 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
636 fAffixesForCurrency
->put(*pluralCount
, affix
, status
);
644 if (U_FAILURE(status
)) {
648 if (setupForPluralPattern
) {
649 if (fPluralAffixesForCurrency
) {
650 deleteHashForAffix(fPluralAffixesForCurrency
);
652 fPluralAffixesForCurrency
= initHashForAffix(status
);
653 if (U_SUCCESS(status
)) {
654 const PluralRules
* pluralRules
= fCurrencyPluralInfo
->getPluralRules();
655 StringEnumeration
* keywords
= pluralRules
->getKeywords(status
);
656 if (U_SUCCESS(status
)) {
657 const UnicodeString
* pluralCount
;
658 while ((pluralCount
= keywords
->snext(status
)) != NULL
) {
659 if ( U_SUCCESS(status
) ) {
661 fCurrencyPluralInfo
->getCurrencyPluralPattern(*pluralCount
, ptn
);
662 applyPatternInternally(*pluralCount
, ptn
, false, parseErr
, status
);
663 AffixesForCurrency
* affix
= new AffixesForCurrency(
664 fNegativePrefix
, fNegativeSuffix
, fPositivePrefix
, fPositiveSuffix
);
665 fPluralAffixesForCurrency
->put(*pluralCount
, affix
, status
);
675 //------------------------------------------------------------------------------
677 DecimalFormat::~DecimalFormat()
679 delete fPosPrefixPattern
;
680 delete fPosSuffixPattern
;
681 delete fNegPrefixPattern
;
682 delete fNegSuffixPattern
;
683 delete fCurrencyChoice
;
686 delete fRoundingIncrement
;
687 deleteHashForAffixPattern();
688 deleteHashForAffix(fAffixesForCurrency
);
689 deleteHashForAffix(fPluralAffixesForCurrency
);
690 delete fCurrencyPluralInfo
;
693 //------------------------------------------------------------------------------
696 DecimalFormat::DecimalFormat(const DecimalFormat
&source
) :
697 NumberFormat(source
) {
698 UErrorCode status
= U_ZERO_ERROR
;
699 init(status
); // if this fails, 'source' isn't initialized properly either.
703 //------------------------------------------------------------------------------
704 // assignment operator
707 static void _copy_ptr(T
** pdest
, const T
* source
) {
708 if (source
== NULL
) {
711 } else if (*pdest
== NULL
) {
712 *pdest
= new T(*source
);
719 static void _clone_ptr(T
** pdest
, const T
* source
) {
721 if (source
== NULL
) {
724 *pdest
= static_cast<T
*>(source
->clone());
729 DecimalFormat::operator=(const DecimalFormat
& rhs
)
732 NumberFormat::operator=(rhs
);
733 fPositivePrefix
= rhs
.fPositivePrefix
;
734 fPositiveSuffix
= rhs
.fPositiveSuffix
;
735 fNegativePrefix
= rhs
.fNegativePrefix
;
736 fNegativeSuffix
= rhs
.fNegativeSuffix
;
737 _copy_ptr(&fPosPrefixPattern
, rhs
.fPosPrefixPattern
);
738 _copy_ptr(&fPosSuffixPattern
, rhs
.fPosSuffixPattern
);
739 _copy_ptr(&fNegPrefixPattern
, rhs
.fNegPrefixPattern
);
740 _copy_ptr(&fNegSuffixPattern
, rhs
.fNegSuffixPattern
);
741 _clone_ptr(&fCurrencyChoice
, rhs
.fCurrencyChoice
);
742 setRoundingIncrement(rhs
.getRoundingIncrement());
743 fRoundingMode
= rhs
.fRoundingMode
;
744 setMultiplier(rhs
.getMultiplier());
745 fGroupingSize
= rhs
.fGroupingSize
;
746 fGroupingSize2
= rhs
.fGroupingSize2
;
747 fDecimalSeparatorAlwaysShown
= rhs
.fDecimalSeparatorAlwaysShown
;
748 _copy_ptr(&fSymbols
, rhs
.fSymbols
);
749 fUseExponentialNotation
= rhs
.fUseExponentialNotation
;
750 fExponentSignAlwaysShown
= rhs
.fExponentSignAlwaysShown
;
751 fBoolFlags
= rhs
.fBoolFlags
;
752 /*Bertrand A. D. Update 98.03.17*/
753 fCurrencySignCount
= rhs
.fCurrencySignCount
;
755 fMinExponentDigits
= rhs
.fMinExponentDigits
;
758 fFormatWidth
= rhs
.fFormatWidth
;
760 fPadPosition
= rhs
.fPadPosition
;
762 fMinSignificantDigits
= rhs
.fMinSignificantDigits
;
763 fMaxSignificantDigits
= rhs
.fMaxSignificantDigits
;
764 fUseSignificantDigits
= rhs
.fUseSignificantDigits
;
765 fFormatPattern
= rhs
.fFormatPattern
;
767 fCurrencySignCount
= rhs
.fCurrencySignCount
;
768 _clone_ptr(&fCurrencyPluralInfo
, rhs
.fCurrencyPluralInfo
);
769 deleteHashForAffixPattern();
770 if (rhs
.fAffixPatternsForCurrency
) {
771 UErrorCode status
= U_ZERO_ERROR
;
772 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
773 copyHashForAffixPattern(rhs
.fAffixPatternsForCurrency
,
774 fAffixPatternsForCurrency
, status
);
776 deleteHashForAffix(fAffixesForCurrency
);
777 if (rhs
.fAffixesForCurrency
) {
778 UErrorCode status
= U_ZERO_ERROR
;
779 fAffixesForCurrency
= initHashForAffixPattern(status
);
780 copyHashForAffix(rhs
.fAffixesForCurrency
, fAffixesForCurrency
, status
);
782 deleteHashForAffix(fPluralAffixesForCurrency
);
783 if (rhs
.fPluralAffixesForCurrency
) {
784 UErrorCode status
= U_ZERO_ERROR
;
785 fPluralAffixesForCurrency
= initHashForAffixPattern(status
);
786 copyHashForAffix(rhs
.fPluralAffixesForCurrency
, fPluralAffixesForCurrency
, status
);
789 #if UCONFIG_FORMAT_FASTPATHS_49
795 //------------------------------------------------------------------------------
798 DecimalFormat::operator==(const Format
& that
) const
803 // NumberFormat::operator== guarantees this cast is safe
804 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
807 // This code makes it easy to determine why two format objects that should
810 if (!NumberFormat::operator==(that
)) {
811 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
812 debug("NumberFormat::!=");
814 if (!((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
815 fPositivePrefix
== other
->fPositivePrefix
)
816 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
817 *fPosPrefixPattern
== *other
->fPosPrefixPattern
))) {
818 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
819 debug("Pos Prefix !=");
821 if (!((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
822 fPositiveSuffix
== other
->fPositiveSuffix
)
823 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
824 *fPosSuffixPattern
== *other
->fPosSuffixPattern
))) {
825 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
826 debug("Pos Suffix !=");
828 if (!((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
829 fNegativePrefix
== other
->fNegativePrefix
)
830 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
831 *fNegPrefixPattern
== *other
->fNegPrefixPattern
))) {
832 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
833 debug("Neg Prefix ");
834 if (fNegPrefixPattern
== NULL
) {
836 debugout(fNegativePrefix
);
839 debugout(*fNegPrefixPattern
);
842 if (other
->fNegPrefixPattern
== NULL
) {
844 debugout(other
->fNegativePrefix
);
847 debugout(*other
->fNegPrefixPattern
);
850 if (!((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
851 fNegativeSuffix
== other
->fNegativeSuffix
)
852 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
853 *fNegSuffixPattern
== *other
->fNegSuffixPattern
))) {
854 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
855 debug("Neg Suffix ");
856 if (fNegSuffixPattern
== NULL
) {
858 debugout(fNegativeSuffix
);
861 debugout(*fNegSuffixPattern
);
864 if (other
->fNegSuffixPattern
== NULL
) {
866 debugout(other
->fNegativeSuffix
);
869 debugout(*other
->fNegSuffixPattern
);
872 if (!((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
873 || (fRoundingIncrement
!= NULL
&&
874 other
->fRoundingIncrement
!= NULL
&&
875 *fRoundingIncrement
== *other
->fRoundingIncrement
))) {
876 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
877 debug("Rounding Increment !=");
879 if (getMultiplier() != other
->getMultiplier()) {
880 if (first
) { printf("[ "); first
= FALSE
; }
881 printf("Multiplier %ld != %ld", getMultiplier(), other
->getMultiplier());
883 if (fGroupingSize
!= other
->fGroupingSize
) {
884 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
885 printf("Grouping Size %ld != %ld", fGroupingSize
, other
->fGroupingSize
);
887 if (fGroupingSize2
!= other
->fGroupingSize2
) {
888 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
889 printf("Secondary Grouping Size %ld != %ld", fGroupingSize2
, other
->fGroupingSize2
);
891 if (fDecimalSeparatorAlwaysShown
!= other
->fDecimalSeparatorAlwaysShown
) {
892 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
893 printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown
, other
->fDecimalSeparatorAlwaysShown
);
895 if (fUseExponentialNotation
!= other
->fUseExponentialNotation
) {
896 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
899 if (!(!fUseExponentialNotation
||
900 fMinExponentDigits
!= other
->fMinExponentDigits
)) {
901 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
902 debug("Exp Digits !=");
904 if (*fSymbols
!= *(other
->fSymbols
)) {
905 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
908 // TODO Add debug stuff for significant digits here
909 if (fUseSignificantDigits
!= other
->fUseSignificantDigits
) {
910 debug("fUseSignificantDigits !=");
912 if (fUseSignificantDigits
&&
913 fMinSignificantDigits
!= other
->fMinSignificantDigits
) {
914 debug("fMinSignificantDigits !=");
916 if (fUseSignificantDigits
&&
917 fMaxSignificantDigits
!= other
->fMaxSignificantDigits
) {
918 debug("fMaxSignificantDigits !=");
921 if (!first
) { printf(" ]"); }
922 if (fCurrencySignCount
!= other
->fCurrencySignCount
) {
923 debug("fCurrencySignCount !=");
925 if (fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
) {
926 debug("fCurrencyPluralInfo == ");
927 if (fCurrencyPluralInfo
== NULL
) {
928 debug("fCurrencyPluralInfo == NULL");
931 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
932 *fCurrencyPluralInfo
!= *(other
->fCurrencyPluralInfo
)) {
933 debug("fCurrencyPluralInfo !=");
935 if (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
== NULL
||
936 fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
!= NULL
) {
937 debug("fCurrencyPluralInfo one NULL, the other not");
939 if (fCurrencyPluralInfo
== NULL
&& other
->fCurrencyPluralInfo
== NULL
) {
940 debug("fCurrencyPluralInfo == ");
945 return (NumberFormat::operator==(that
) &&
946 ((fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) ?
947 (fAffixPatternsForCurrency
->equals(*other
->fAffixPatternsForCurrency
)) :
948 (((fPosPrefixPattern
== other
->fPosPrefixPattern
&& // both null
949 fPositivePrefix
== other
->fPositivePrefix
)
950 || (fPosPrefixPattern
!= 0 && other
->fPosPrefixPattern
!= 0 &&
951 *fPosPrefixPattern
== *other
->fPosPrefixPattern
)) &&
952 ((fPosSuffixPattern
== other
->fPosSuffixPattern
&& // both null
953 fPositiveSuffix
== other
->fPositiveSuffix
)
954 || (fPosSuffixPattern
!= 0 && other
->fPosSuffixPattern
!= 0 &&
955 *fPosSuffixPattern
== *other
->fPosSuffixPattern
)) &&
956 ((fNegPrefixPattern
== other
->fNegPrefixPattern
&& // both null
957 fNegativePrefix
== other
->fNegativePrefix
)
958 || (fNegPrefixPattern
!= 0 && other
->fNegPrefixPattern
!= 0 &&
959 *fNegPrefixPattern
== *other
->fNegPrefixPattern
)) &&
960 ((fNegSuffixPattern
== other
->fNegSuffixPattern
&& // both null
961 fNegativeSuffix
== other
->fNegativeSuffix
)
962 || (fNegSuffixPattern
!= 0 && other
->fNegSuffixPattern
!= 0 &&
963 *fNegSuffixPattern
== *other
->fNegSuffixPattern
)))) &&
964 ((fRoundingIncrement
== other
->fRoundingIncrement
) // both null
965 || (fRoundingIncrement
!= NULL
&&
966 other
->fRoundingIncrement
!= NULL
&&
967 *fRoundingIncrement
== *other
->fRoundingIncrement
)) &&
968 getMultiplier() == other
->getMultiplier() &&
969 fGroupingSize
== other
->fGroupingSize
&&
970 fGroupingSize2
== other
->fGroupingSize2
&&
971 fDecimalSeparatorAlwaysShown
== other
->fDecimalSeparatorAlwaysShown
&&
972 fUseExponentialNotation
== other
->fUseExponentialNotation
&&
973 (!fUseExponentialNotation
||
974 fMinExponentDigits
== other
->fMinExponentDigits
) &&
975 *fSymbols
== *(other
->fSymbols
) &&
976 fUseSignificantDigits
== other
->fUseSignificantDigits
&&
977 (!fUseSignificantDigits
||
978 (fMinSignificantDigits
== other
->fMinSignificantDigits
&&
979 fMaxSignificantDigits
== other
->fMaxSignificantDigits
)) &&
980 fCurrencySignCount
== other
->fCurrencySignCount
&&
981 ((fCurrencyPluralInfo
== other
->fCurrencyPluralInfo
&&
982 fCurrencyPluralInfo
== NULL
) ||
983 (fCurrencyPluralInfo
!= NULL
&& other
->fCurrencyPluralInfo
!= NULL
&&
984 *fCurrencyPluralInfo
== *(other
->fCurrencyPluralInfo
))));
987 //------------------------------------------------------------------------------
990 DecimalFormat::clone() const
992 return new DecimalFormat(*this);
995 //------------------------------------------------------------------------------
998 DecimalFormat::format(int32_t number
,
999 UnicodeString
& appendTo
,
1000 FieldPosition
& fieldPosition
) const
1002 return format((int64_t)number
, appendTo
, fieldPosition
);
1006 DecimalFormat::format(int32_t number
,
1007 UnicodeString
& appendTo
,
1008 FieldPosition
& fieldPosition
,
1009 UErrorCode
& status
) const
1011 return format((int64_t)number
, appendTo
, fieldPosition
, status
);
1015 DecimalFormat::format(int32_t number
,
1016 UnicodeString
& appendTo
,
1017 FieldPositionIterator
* posIter
,
1018 UErrorCode
& status
) const
1020 return format((int64_t)number
, appendTo
, posIter
, status
);
1024 #if UCONFIG_FORMAT_FASTPATHS_49
1025 void DecimalFormat::handleChanged() {
1026 DecimalFormatInternal
&data
= internalData(fReserved
);
1028 if(data
.fFastFormatStatus
== kFastpathUNKNOWN
|| data
.fFastParseStatus
== kFastpathUNKNOWN
) {
1029 return; // still constructing. Wait.
1032 data
.fFastParseStatus
= data
.fFastFormatStatus
= kFastpathNO
;
1034 #if UCONFIG_HAVE_PARSEALLINPUT
1035 if(fParseAllInput
== UNUM_NO
) {
1036 debug("No Parse fastpath: fParseAllInput==UNUM_NO");
1039 if (fFormatWidth
!=0) {
1040 debug("No Parse fastpath: fFormatWidth");
1041 } else if(fPositivePrefix
.length()>0) {
1042 debug("No Parse fastpath: positive prefix");
1043 } else if(fPositiveSuffix
.length()>0) {
1044 debug("No Parse fastpath: positive suffix");
1045 } else if(fNegativePrefix
.length()>1
1046 || ((fNegativePrefix
.length()==1) && (fNegativePrefix
.charAt(0)!=0x002D))) {
1047 debug("No Parse fastpath: negative prefix that isn't '-'");
1048 } else if(fNegativeSuffix
.length()>0) {
1049 debug("No Parse fastpath: negative suffix");
1051 data
.fFastParseStatus
= kFastpathYES
;
1052 debug("parse fastpath: YES");
1055 if (fGroupingSize
!=0 && isGroupingUsed()) {
1056 debug("No format fastpath: fGroupingSize!=0 and grouping is used");
1058 printf("groupingsize=%d\n", fGroupingSize
);
1060 } else if(fGroupingSize2
!=0 && isGroupingUsed()) {
1061 debug("No format fastpath: fGroupingSize2!=0");
1062 } else if(fUseExponentialNotation
) {
1063 debug("No format fastpath: fUseExponentialNotation");
1064 } else if(fFormatWidth
!=0) {
1065 debug("No format fastpath: fFormatWidth!=0");
1066 } else if(fMinSignificantDigits
!=1) {
1067 debug("No format fastpath: fMinSignificantDigits!=1");
1068 } else if(fMultiplier
!=NULL
) {
1069 debug("No format fastpath: fMultiplier!=NULL");
1070 } else if(fScale
!=0) {
1071 debug("No format fastpath: fScale!=0");
1072 } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0)) {
1073 debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)");
1074 } else if(fDecimalSeparatorAlwaysShown
) {
1075 debug("No format fastpath: fDecimalSeparatorAlwaysShown");
1076 } else if(getMinimumFractionDigits()>0) {
1077 debug("No format fastpath: fMinFractionDigits>0");
1078 } else if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1079 debug("No format fastpath: fCurrencySignCount > fgCurrencySignCountZero");
1080 } else if(fRoundingIncrement
!=0) {
1081 debug("No format fastpath: fRoundingIncrement!=0");
1083 data
.fFastFormatStatus
= kFastpathYES
;
1084 debug("format:kFastpathYES!");
1090 //------------------------------------------------------------------------------
1093 DecimalFormat::format(int64_t number
,
1094 UnicodeString
& appendTo
,
1095 FieldPosition
& fieldPosition
) const
1097 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
1098 FieldPositionOnlyHandler
handler(fieldPosition
);
1099 return _format(number
, appendTo
, handler
, status
);
1103 DecimalFormat::format(int64_t number
,
1104 UnicodeString
& appendTo
,
1105 FieldPosition
& fieldPosition
,
1106 UErrorCode
& status
) const
1108 FieldPositionOnlyHandler
handler(fieldPosition
);
1109 return _format(number
, appendTo
, handler
, status
);
1113 DecimalFormat::format(int64_t number
,
1114 UnicodeString
& appendTo
,
1115 FieldPositionIterator
* posIter
,
1116 UErrorCode
& status
) const
1118 FieldPositionIteratorHandler
handler(posIter
, status
);
1119 return _format(number
, appendTo
, handler
, status
);
1123 DecimalFormat::_format(int64_t number
,
1124 UnicodeString
& appendTo
,
1125 FieldPositionHandler
& handler
,
1126 UErrorCode
&status
) const
1128 // Bottleneck function for formatting int64_t
1129 if (U_FAILURE(status
)) {
1133 #if UCONFIG_FORMAT_FASTPATHS_49
1134 // const UnicodeString *posPrefix = fPosPrefixPattern;
1135 // const UnicodeString *posSuffix = fPosSuffixPattern;
1136 // const UnicodeString *negSuffix = fNegSuffixPattern;
1138 const DecimalFormatInternal
&data
= internalData(fReserved
);
1142 printf("fastpath? [%d]\n", number
);
1145 if( data
.fFastFormatStatus
==kFastpathYES
) {
1147 #define kZero 0x0030
1148 const int32_t MAX_IDX
= MAX_DIGITS
+2;
1149 UChar outputStr
[MAX_IDX
];
1150 int32_t destIdx
= MAX_IDX
;
1151 outputStr
[--destIdx
] = 0; // term
1155 // Negative numbers are slightly larger than positive
1156 // output the first digit (or the leading zero)
1157 outputStr
[--destIdx
] = (-(n
% 10) + kZero
);
1160 // get any remaining digits
1162 outputStr
[--destIdx
] = (n
% 10) + kZero
;
1167 // Slide the number to the start of the output str
1168 U_ASSERT(destIdx
>= 0);
1169 int32_t length
= MAX_IDX
- destIdx
-1;
1170 /*int32_t prefixLen = */ appendAffix(appendTo
, number
, handler
, number
<0, TRUE
);
1171 int32_t maxIntDig
= getMaximumIntegerDigits();
1172 int32_t destlength
= length
<=maxIntDig
?length
:maxIntDig
; // dest length pinned to max int digits
1174 if(length
>maxIntDig
&& fBoolFlags
.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
)) {
1175 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1178 int32_t prependZero
= getMinimumIntegerDigits() - destlength
;
1181 printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d skip=%d\n", prependZero
, length
, getMinimumIntegerDigits(), maxIntDig
, destlength
, length
-destlength
);
1183 int32_t intBegin
= appendTo
.length();
1185 while((prependZero
--)>0) {
1186 appendTo
.append((UChar
)0x0030); // '0'
1189 appendTo
.append(outputStr
+destIdx
+
1190 (length
-destlength
), // skip any leading digits
1192 handler
.addAttribute(kIntegerField
, intBegin
, appendTo
.length());
1194 /*int32_t suffixLen =*/ appendAffix(appendTo
, number
, handler
, number
<0, FALSE
);
1196 //outputStr[length]=0;
1199 printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr
+destIdx
, length
, MAX_IDX
, number
);
1208 // Else the slow way - via DigitList
1211 return _format(digits
, appendTo
, handler
, status
);
1214 //------------------------------------------------------------------------------
1217 DecimalFormat::format( double number
,
1218 UnicodeString
& appendTo
,
1219 FieldPosition
& fieldPosition
) const
1221 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
1222 FieldPositionOnlyHandler
handler(fieldPosition
);
1223 return _format(number
, appendTo
, handler
, status
);
1227 DecimalFormat::format( double number
,
1228 UnicodeString
& appendTo
,
1229 FieldPosition
& fieldPosition
,
1230 UErrorCode
& status
) const
1232 FieldPositionOnlyHandler
handler(fieldPosition
);
1233 return _format(number
, appendTo
, handler
, status
);
1237 DecimalFormat::format( double number
,
1238 UnicodeString
& appendTo
,
1239 FieldPositionIterator
* posIter
,
1240 UErrorCode
& status
) const
1242 FieldPositionIteratorHandler
handler(posIter
, status
);
1243 return _format(number
, appendTo
, handler
, status
);
1247 DecimalFormat::_format( double number
,
1248 UnicodeString
& appendTo
,
1249 FieldPositionHandler
& handler
,
1250 UErrorCode
&status
) const
1252 if (U_FAILURE(status
)) {
1255 // Special case for NaN, sets the begin and end index to be the
1256 // the string length of localized name of NaN.
1257 // TODO: let NaNs go through DigitList.
1258 if (uprv_isNaN(number
))
1260 int begin
= appendTo
.length();
1261 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1263 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1265 addPadding(appendTo
, handler
, 0, 0);
1271 _format(digits
, appendTo
, handler
, status
);
1272 // No way to return status from here.
1276 //------------------------------------------------------------------------------
1280 DecimalFormat::format(const StringPiece
&number
,
1281 UnicodeString
&toAppendTo
,
1282 FieldPositionIterator
*posIter
,
1283 UErrorCode
&status
) const
1285 #if UCONFIG_FORMAT_FASTPATHS_49
1286 // don't bother if the int64 path is not optimized
1287 int32_t len
= number
.length();
1289 if(len
>0&&len
<10) { /* 10 or more digits may not be an int64 */
1290 const char *data
= number
.data();
1297 if(data
[start
]=='+') {
1299 } else if(data
[start
]=='-') {
1304 int32_t place
= 1; /* 1, 10, ... */
1305 for(int32_t i
=len
-1;i
>=start
;i
--) {
1306 if(data
[i
]>='0'&&data
[i
]<='9') {
1307 num
+=place
*(int64_t)(data
[i
]-'0');
1317 num
= -num
;// add minus bit
1319 // format as int64_t
1320 return format(num
, toAppendTo
, posIter
, status
);
1322 // else fall through
1327 dnum
.set(number
, status
);
1328 if (U_FAILURE(status
)) {
1331 FieldPositionIteratorHandler
handler(posIter
, status
);
1332 _format(dnum
, toAppendTo
, handler
, status
);
1338 DecimalFormat::format(const DigitList
&number
,
1339 UnicodeString
&appendTo
,
1340 FieldPositionIterator
*posIter
,
1341 UErrorCode
&status
) const {
1342 FieldPositionIteratorHandler
handler(posIter
, status
);
1343 _format(number
, appendTo
, handler
, status
);
1350 DecimalFormat::format(const DigitList
&number
,
1351 UnicodeString
& appendTo
,
1353 UErrorCode
&status
) const {
1354 FieldPositionOnlyHandler
handler(pos
);
1355 _format(number
, appendTo
, handler
, status
);
1360 DecimalFormat::_round(const DigitList
&number
, DigitList
&adjustedNum
, UBool
& isNegative
, UErrorCode
&status
) const {
1361 if (U_FAILURE(status
)) {
1364 adjustedNum
= number
;
1366 if (number
.isNaN()) {
1370 // Do this BEFORE checking to see if value is infinite or negative! Sets the
1371 // begin and end index to be length of the string composed of
1372 // localized name of Infinite and the positive/negative localized
1375 adjustedNum
.setRoundingMode(fRoundingMode
);
1376 if (fMultiplier
!= NULL
) {
1377 adjustedNum
.mult(*fMultiplier
, status
);
1378 if (U_FAILURE(status
)) {
1387 for (int32_t i
= fScale
; i
> 0 ; i
--) {
1388 adjustedNum
.mult(ten
, status
);
1389 if (U_FAILURE(status
)) {
1394 for (int32_t i
= fScale
; i
< 0 ; i
++) {
1395 adjustedNum
.div(ten
, status
);
1396 if (U_FAILURE(status
)) {
1404 * Note: sign is important for zero as well as non-zero numbers.
1405 * Proper detection of -0.0 is needed to deal with the
1406 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
1408 isNegative
= !adjustedNum
.isPositive();
1410 // Apply rounding after multiplier
1412 adjustedNum
.fContext
.status
&= ~DEC_Inexact
;
1413 if (fRoundingIncrement
!= NULL
) {
1414 adjustedNum
.div(*fRoundingIncrement
, status
);
1415 adjustedNum
.toIntegralValue();
1416 adjustedNum
.mult(*fRoundingIncrement
, status
);
1418 if (U_FAILURE(status
)) {
1422 if (fRoundingMode
== kRoundUnnecessary
&& (adjustedNum
.fContext
.status
& DEC_Inexact
)) {
1423 status
= U_FORMAT_INEXACT_ERROR
;
1427 if (adjustedNum
.isInfinite()) {
1431 if (fUseExponentialNotation
|| areSignificantDigitsUsed()) {
1432 int32_t sigDigits
= precision();
1433 if (sigDigits
> 0) {
1434 adjustedNum
.round(sigDigits
);
1437 // Fixed point format. Round to a set number of fraction digits.
1438 int32_t numFractionDigits
= precision();
1439 adjustedNum
.roundFixedPoint(numFractionDigits
);
1441 if (fRoundingMode
== kRoundUnnecessary
&& (adjustedNum
.fContext
.status
& DEC_Inexact
)) {
1442 status
= U_FORMAT_INEXACT_ERROR
;
1449 DecimalFormat::_format(const DigitList
&number
,
1450 UnicodeString
& appendTo
,
1451 FieldPositionHandler
& handler
,
1452 UErrorCode
&status
) const
1454 if (U_FAILURE(status
)) {
1458 // Special case for NaN, sets the begin and end index to be the
1459 // the string length of localized name of NaN.
1462 int begin
= appendTo
.length();
1463 appendTo
+= getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1465 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1467 addPadding(appendTo
, handler
, 0, 0);
1471 DigitList adjustedNum
;
1473 _round(number
, adjustedNum
, isNegative
, status
);
1474 if (U_FAILURE(status
)) {
1478 // Special case for INFINITE,
1479 if (adjustedNum
.isInfinite()) {
1480 int32_t prefixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, TRUE
);
1482 int begin
= appendTo
.length();
1483 appendTo
+= getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1485 handler
.addAttribute(kIntegerField
, begin
, appendTo
.length());
1487 int32_t suffixLen
= appendAffix(appendTo
, adjustedNum
.getDouble(), handler
, isNegative
, FALSE
);
1489 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1492 return subformat(appendTo
, handler
, adjustedNum
, FALSE
, status
);
1496 DecimalFormat::format( const Formattable
& obj
,
1497 UnicodeString
& appendTo
,
1498 FieldPosition
& fieldPosition
,
1499 UErrorCode
& status
) const
1501 return NumberFormat::format(obj
, appendTo
, fieldPosition
, status
);
1505 * Return true if a grouping separator belongs at the given
1506 * position, based on whether grouping is in use and the values of
1507 * the primary and secondary grouping interval.
1508 * @param pos the number of integer digits to the right of
1509 * the current position. Zero indicates the position after the
1510 * rightmost integer digit.
1511 * @return true if a grouping character belongs at the current
1514 UBool
DecimalFormat::isGroupingPosition(int32_t pos
) const {
1515 UBool result
= FALSE
;
1516 if (isGroupingUsed() && (pos
> 0) && (fGroupingSize
> 0)) {
1517 if ((fGroupingSize2
> 0) && (pos
> fGroupingSize
)) {
1518 result
= ((pos
- fGroupingSize
) % fGroupingSize2
) == 0;
1520 result
= pos
% fGroupingSize
== 0;
1526 //------------------------------------------------------------------------------
1529 * Complete the formatting of a finite number. On entry, the DigitList must
1530 * be filled in with the correct digits.
1533 DecimalFormat::subformat(UnicodeString
& appendTo
,
1534 FieldPositionHandler
& handler
,
1537 UErrorCode
& status
) const
1540 // DigitList returns digits as '0' thru '9', so we will need to
1541 // always need to subtract the character 0 to get the numeric value to use for indexing.
1543 UChar32 localizedDigits
[10];
1544 localizedDigits
[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1545 localizedDigits
[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol
).char32At(0);
1546 localizedDigits
[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol
).char32At(0);
1547 localizedDigits
[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol
).char32At(0);
1548 localizedDigits
[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol
).char32At(0);
1549 localizedDigits
[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol
).char32At(0);
1550 localizedDigits
[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol
).char32At(0);
1551 localizedDigits
[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol
).char32At(0);
1552 localizedDigits
[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol
).char32At(0);
1553 localizedDigits
[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol
).char32At(0);
1555 const UnicodeString
*grouping
;
1556 if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1557 grouping
= &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
1559 grouping
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
1561 const UnicodeString
*decimal
;
1562 if(fCurrencySignCount
> fgCurrencySignCountZero
) {
1563 decimal
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1565 decimal
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1567 UBool useSigDig
= areSignificantDigitsUsed();
1568 int32_t maxIntDig
= getMaximumIntegerDigits();
1569 int32_t minIntDig
= getMinimumIntegerDigits();
1571 // Appends the prefix.
1572 double doubleValue
= digits
.getDouble();
1573 int32_t prefixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), TRUE
);
1575 if (fUseExponentialNotation
)
1577 int currentLength
= appendTo
.length();
1578 int intBegin
= currentLength
;
1582 int32_t minFracDig
= 0;
1584 maxIntDig
= minIntDig
= 1;
1585 minFracDig
= getMinimumSignificantDigits() - 1;
1587 minFracDig
= getMinimumFractionDigits();
1588 if (maxIntDig
> kMaxScientificIntegerDigits
) {
1590 if (maxIntDig
< minIntDig
) {
1591 maxIntDig
= minIntDig
;
1594 if (maxIntDig
> minIntDig
) {
1599 // Minimum integer digits are handled in exponential format by
1600 // adjusting the exponent. For example, 0.01234 with 3 minimum
1601 // integer digits is "123.4E-4".
1603 // Maximum integer digits are interpreted as indicating the
1604 // repeating range. This is useful for engineering notation, in
1605 // which the exponent is restricted to a multiple of 3. For
1606 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1607 // If maximum integer digits are defined and are larger than
1608 // minimum integer digits, then minimum integer digits are
1610 digits
.reduce(); // Removes trailing zero digits.
1611 int32_t exponent
= digits
.getDecimalAt();
1612 if (maxIntDig
> 1 && maxIntDig
!= minIntDig
) {
1613 // A exponent increment is defined; adjust to it.
1614 exponent
= (exponent
> 0) ? (exponent
- 1) / maxIntDig
1615 : (exponent
/ maxIntDig
) - 1;
1616 exponent
*= maxIntDig
;
1618 // No exponent increment is defined; use minimum integer digits.
1619 // If none is specified, as in "#E0", generate 1 integer digit.
1620 exponent
-= (minIntDig
> 0 || minFracDig
> 0)
1624 // We now output a minimum number of digits, and more if there
1625 // are more digits, up to the maximum number of digits. We
1626 // place the decimal point after the "integer" digits, which
1627 // are the first (decimalAt - exponent) digits.
1628 int32_t minimumDigits
= minIntDig
+ minFracDig
;
1629 // The number of integer digits is handled specially if the number
1630 // is zero, since then there may be no digits.
1631 int32_t integerDigits
= digits
.isZero() ? minIntDig
:
1632 digits
.getDecimalAt() - exponent
;
1633 int32_t totalDigits
= digits
.getCount();
1634 if (minimumDigits
> totalDigits
)
1635 totalDigits
= minimumDigits
;
1636 if (integerDigits
> totalDigits
)
1637 totalDigits
= integerDigits
;
1639 // totalDigits records total number of digits needs to be processed
1641 for (i
=0; i
<totalDigits
; ++i
)
1643 if (i
== integerDigits
)
1645 intEnd
= appendTo
.length();
1646 handler
.addAttribute(kIntegerField
, intBegin
, intEnd
);
1648 appendTo
+= *decimal
;
1650 fracBegin
= appendTo
.length();
1651 handler
.addAttribute(kDecimalSeparatorField
, fracBegin
- 1, fracBegin
);
1653 // Restores the digit character or pads the buffer with zeros.
1654 UChar32 c
= (UChar32
)((i
< digits
.getCount()) ?
1655 localizedDigits
[digits
.getDigitValue(i
)] :
1656 localizedDigits
[0]);
1660 currentLength
= appendTo
.length();
1663 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1665 if (fracBegin
> 0) {
1666 handler
.addAttribute(kFractionField
, fracBegin
, currentLength
);
1669 // The exponent is output using the pattern-specified minimum
1670 // exponent digits. There is no maximum limit to the exponent
1671 // digits, since truncating the exponent would appendTo in an
1672 // unacceptable inaccuracy.
1673 appendTo
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1675 handler
.addAttribute(kExponentSymbolField
, currentLength
, appendTo
.length());
1676 currentLength
= appendTo
.length();
1678 // For zero values, we force the exponent to zero. We
1679 // must do this here, and not earlier, because the value
1680 // is used to determine integer digit count above.
1681 if (digits
.isZero())
1685 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1686 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1687 } else if (fExponentSignAlwaysShown
) {
1688 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1689 handler
.addAttribute(kExponentSignField
, currentLength
, appendTo
.length());
1692 currentLength
= appendTo
.length();
1694 DigitList expDigits
;
1695 expDigits
.set(exponent
);
1697 int expDig
= fMinExponentDigits
;
1698 if (fUseExponentialNotation
&& expDig
< 1) {
1701 for (i
=expDigits
.getDecimalAt(); i
<expDig
; ++i
)
1702 appendTo
+= (localizedDigits
[0]);
1704 for (i
=0; i
<expDigits
.getDecimalAt(); ++i
)
1706 UChar32 c
= (UChar32
)((i
< expDigits
.getCount()) ?
1707 localizedDigits
[expDigits
.getDigitValue(i
)] :
1708 localizedDigits
[0]);
1712 handler
.addAttribute(kExponentField
, currentLength
, appendTo
.length());
1714 else // Not using exponential notation
1716 int currentLength
= appendTo
.length();
1717 int intBegin
= currentLength
;
1719 int32_t sigCount
= 0;
1720 int32_t minSigDig
= getMinimumSignificantDigits();
1721 int32_t maxSigDig
= getMaximumSignificantDigits();
1724 maxSigDig
= INT32_MAX
;
1727 // Output the integer portion. Here 'count' is the total
1728 // number of integer digits we will display, including both
1729 // leading zeros required to satisfy getMinimumIntegerDigits,
1730 // and actual digits present in the number.
1731 int32_t count
= useSigDig
?
1732 _max(1, digits
.getDecimalAt()) : minIntDig
;
1733 if (digits
.getDecimalAt() > 0 && count
< digits
.getDecimalAt()) {
1734 count
= digits
.getDecimalAt();
1737 // Handle the case where getMaximumIntegerDigits() is smaller
1738 // than the real number of integer digits. If this is so, we
1739 // output the least significant max integer digits. For example,
1740 // the value 1997 printed with 2 max integer digits is just "97".
1742 int32_t digitIndex
= 0; // Index into digitList.fDigits[]
1743 if (count
> maxIntDig
&& maxIntDig
>= 0) {
1745 digitIndex
= digits
.getDecimalAt() - count
;
1746 if(fBoolFlags
.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
)) {
1747 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1751 int32_t sizeBeforeIntegerPart
= appendTo
.length();
1754 for (i
=count
-1; i
>=0; --i
)
1756 if (i
< digits
.getDecimalAt() && digitIndex
< digits
.getCount() &&
1757 sigCount
< maxSigDig
) {
1758 // Output a real digit
1759 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
1764 // Output a zero (leading or trailing)
1765 appendTo
+= localizedDigits
[0];
1771 // Output grouping separator if necessary.
1772 if (isGroupingPosition(i
)) {
1773 currentLength
= appendTo
.length();
1774 appendTo
.append(*grouping
);
1775 handler
.addAttribute(kGroupingSeparatorField
, currentLength
, appendTo
.length());
1779 // TODO(dlf): this looks like it was a bug, we marked the int field as ending
1780 // before the zero was generated.
1781 // Record field information for caller.
1782 // if (fieldPosition.getField() == NumberFormat::kIntegerField)
1783 // fieldPosition.setEndIndex(appendTo.length());
1785 // Determine whether or not there are any printable fractional
1786 // digits. If we've used up the digits we know there aren't.
1787 UBool fractionPresent
= (!isInteger
&& digitIndex
< digits
.getCount()) ||
1788 (useSigDig
? (sigCount
< minSigDig
) : (getMinimumFractionDigits() > 0));
1790 // If there is no fraction present, and we haven't printed any
1791 // integer digits, then print a zero. Otherwise we won't print
1792 // _any_ digits, and we won't be able to parse this string.
1793 if (!fractionPresent
&& appendTo
.length() == sizeBeforeIntegerPart
)
1794 appendTo
+= localizedDigits
[0];
1796 currentLength
= appendTo
.length();
1797 handler
.addAttribute(kIntegerField
, intBegin
, currentLength
);
1799 // Output the decimal separator if we always do so.
1800 if (fDecimalSeparatorAlwaysShown
|| fractionPresent
) {
1801 appendTo
+= *decimal
;
1802 handler
.addAttribute(kDecimalSeparatorField
, currentLength
, appendTo
.length());
1803 currentLength
= appendTo
.length();
1806 int fracBegin
= currentLength
;
1808 count
= useSigDig
? INT32_MAX
: getMaximumFractionDigits();
1809 if (useSigDig
&& (sigCount
== maxSigDig
||
1810 (sigCount
>= minSigDig
&& digitIndex
== digits
.getCount()))) {
1814 for (i
=0; i
< count
; ++i
) {
1815 // Here is where we escape from the loop. We escape
1816 // if we've output the maximum fraction digits
1817 // (specified in the for expression above). We also
1818 // stop when we've output the minimum digits and
1819 // either: we have an integer, so there is no
1820 // fractional stuff to display, or we're out of
1821 // significant digits.
1822 if (!useSigDig
&& i
>= getMinimumFractionDigits() &&
1823 (isInteger
|| digitIndex
>= digits
.getCount())) {
1827 // Output leading fractional zeros. These are zeros
1828 // that come after the decimal but before any
1829 // significant digits. These are only output if
1830 // abs(number being formatted) < 1.0.
1831 if (-1-i
> (digits
.getDecimalAt()-1)) {
1832 appendTo
+= localizedDigits
[0];
1836 // Output a digit, if we have any precision left, or a
1837 // zero if we don't. We don't want to output noise digits.
1838 if (!isInteger
&& digitIndex
< digits
.getCount()) {
1839 appendTo
+= (UChar32
)localizedDigits
[digits
.getDigitValue(digitIndex
++)];
1841 appendTo
+= localizedDigits
[0];
1844 // If we reach the maximum number of significant
1845 // digits, or if we output all the real digits and
1846 // reach the minimum, then we are done.
1849 (sigCount
== maxSigDig
||
1850 (digitIndex
== digits
.getCount() && sigCount
>= minSigDig
))) {
1855 handler
.addAttribute(kFractionField
, fracBegin
, appendTo
.length());
1858 int32_t suffixLen
= appendAffix(appendTo
, doubleValue
, handler
, !digits
.isPositive(), FALSE
);
1860 addPadding(appendTo
, handler
, prefixLen
, suffixLen
);
1865 * Inserts the character fPad as needed to expand result to fFormatWidth.
1866 * @param result the string to be padded
1868 void DecimalFormat::addPadding(UnicodeString
& appendTo
,
1869 FieldPositionHandler
& handler
,
1871 int32_t suffixLen
) const
1873 if (fFormatWidth
> 0) {
1874 int32_t len
= fFormatWidth
- appendTo
.length();
1876 UnicodeString padding
;
1877 for (int32_t i
=0; i
<len
; ++i
) {
1880 switch (fPadPosition
) {
1881 case kPadAfterPrefix
:
1882 appendTo
.insert(prefixLen
, padding
);
1884 case kPadBeforePrefix
:
1885 appendTo
.insert(0, padding
);
1887 case kPadBeforeSuffix
:
1888 appendTo
.insert(appendTo
.length() - suffixLen
, padding
);
1890 case kPadAfterSuffix
:
1891 appendTo
+= padding
;
1894 if (fPadPosition
== kPadBeforePrefix
|| fPadPosition
== kPadAfterPrefix
) {
1895 handler
.shiftLast(len
);
1901 //------------------------------------------------------------------------------
1904 DecimalFormat::parse(const UnicodeString
& text
,
1905 Formattable
& result
,
1906 UErrorCode
& status
) const
1908 NumberFormat::parse(text
, result
, status
);
1912 DecimalFormat::parse(const UnicodeString
& text
,
1913 Formattable
& result
,
1914 ParsePosition
& parsePosition
) const {
1915 parse(text
, result
, parsePosition
, NULL
);
1918 CurrencyAmount
* DecimalFormat::parseCurrency(const UnicodeString
& text
,
1919 ParsePosition
& pos
) const {
1920 Formattable parseResult
;
1921 int32_t start
= pos
.getIndex();
1922 UChar curbuf
[4] = {};
1923 parse(text
, parseResult
, pos
, curbuf
);
1924 if (pos
.getIndex() != start
) {
1925 UErrorCode ec
= U_ZERO_ERROR
;
1926 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curbuf
, ec
));
1927 if (U_FAILURE(ec
)) {
1928 pos
.setIndex(start
); // indicate failure
1930 return currAmt
.orphan();
1937 * Parses the given text as a number, optionally providing a currency amount.
1938 * @param text the string to parse
1939 * @param result output parameter for the numeric result.
1940 * @param parsePosition input-output position; on input, the
1941 * position within text to match; must have 0 <= pos.getIndex() <
1942 * text.length(); on output, the position after the last matched
1943 * character. If the parse fails, the position in unchanged upon
1945 * @param currency if non-NULL, it should point to a 4-UChar buffer.
1946 * In this case the text is parsed as a currency format, and the
1947 * ISO 4217 code for the parsed currency is put into the buffer.
1948 * Otherwise the text is parsed as a non-currency format.
1950 void DecimalFormat::parse(const UnicodeString
& text
,
1951 Formattable
& result
,
1952 ParsePosition
& parsePosition
,
1953 UChar
* currency
) const {
1954 int32_t startIdx
, backup
;
1955 int32_t i
= startIdx
= backup
= parsePosition
.getIndex();
1957 // clear any old contents in the result. In particular, clears any DigitList
1958 // that it may be holding.
1961 // Handle NaN as a special case:
1963 // Skip padding characters, if around prefix
1964 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforePrefix
||
1965 fPadPosition
== kPadAfterPrefix
)) {
1966 i
= skipPadding(text
, i
);
1970 // skip any leading whitespace
1971 i
= backup
= skipUWhiteSpace(text
, i
);
1974 // If the text is composed of the representation of NaN, returns NaN.length
1975 const UnicodeString
*nan
= &getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
1976 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
1977 ? 0 : nan
->length());
1980 if (fFormatWidth
> 0 && (fPadPosition
== kPadBeforeSuffix
||
1981 fPadPosition
== kPadAfterSuffix
)) {
1982 i
= skipPadding(text
, i
);
1984 parsePosition
.setIndex(i
);
1985 result
.setDouble(uprv_getNaN());
1989 // NaN parse failed; start over
1991 parsePosition
.setIndex(i
);
1993 // status is used to record whether a number is infinite.
1994 UBool status
[fgStatusLength
];
1996 DigitList
*digits
= result
.getInternalDigitList(); // get one from the stack buffer
1997 if (digits
== NULL
) {
1998 return; // no way to report error from here.
2001 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
2002 if (!parseForCurrency(text
, parsePosition
, *digits
,
2003 status
, currency
)) {
2008 fNegPrefixPattern
, fNegSuffixPattern
,
2009 fPosPrefixPattern
, fPosSuffixPattern
,
2010 FALSE
, UCURR_SYMBOL_NAME
,
2011 parsePosition
, *digits
, status
, currency
)) {
2012 debug("!subparse(...) - rewind");
2013 parsePosition
.setIndex(startIdx
);
2019 if (status
[fgStatusInfinite
]) {
2020 double inf
= uprv_getInfinity();
2021 result
.setDouble(digits
->isPositive() ? inf
: -inf
);
2022 // TODO: set the dl to infinity, and let it fall into the code below.
2027 if (fMultiplier
!= NULL
) {
2028 UErrorCode ec
= U_ZERO_ERROR
;
2029 digits
->div(*fMultiplier
, ec
);
2036 for (int32_t i
= fScale
; i
> 0; i
--) {
2037 UErrorCode ec
= U_ZERO_ERROR
;
2038 digits
->div(ten
,ec
);
2041 for (int32_t i
= fScale
; i
< 0; i
++) {
2042 UErrorCode ec
= U_ZERO_ERROR
;
2043 digits
->mult(ten
,ec
);
2048 // Negative zero special case:
2049 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
2050 // if not parsing integerOnly, leave as -0, which a double can represent.
2051 if (digits
->isZero() && !digits
->isPositive() && isParseIntegerOnly()) {
2052 digits
->setPositive(TRUE
);
2054 result
.adoptDigitList(digits
);
2061 DecimalFormat::parseForCurrency(const UnicodeString
& text
,
2062 ParsePosition
& parsePosition
,
2065 UChar
* currency
) const {
2066 int origPos
= parsePosition
.getIndex();
2067 int maxPosIndex
= origPos
;
2068 int maxErrorPos
= -1;
2069 // First, parse against current pattern.
2070 // Since current pattern could be set by applyPattern(),
2071 // it could be an arbitrary pattern, and it may not be the one
2072 // defined in current locale.
2073 UBool tmpStatus
[fgStatusLength
];
2074 ParsePosition
tmpPos(origPos
);
2075 DigitList tmpDigitList
;
2077 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
2078 found
= subparse(text
,
2079 fNegPrefixPattern
, fNegSuffixPattern
,
2080 fPosPrefixPattern
, fPosSuffixPattern
,
2081 TRUE
, UCURR_LONG_NAME
,
2082 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
2084 found
= subparse(text
,
2085 fNegPrefixPattern
, fNegSuffixPattern
,
2086 fPosPrefixPattern
, fPosSuffixPattern
,
2087 TRUE
, UCURR_SYMBOL_NAME
,
2088 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
2091 if (tmpPos
.getIndex() > maxPosIndex
) {
2092 maxPosIndex
= tmpPos
.getIndex();
2093 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
2094 status
[i
] = tmpStatus
[i
];
2096 digits
= tmpDigitList
;
2099 maxErrorPos
= tmpPos
.getErrorIndex();
2101 // Then, parse against affix patterns.
2102 // Those are currency patterns and currency plural patterns.
2104 const UHashElement
* element
= NULL
;
2105 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
2106 const UHashTok valueTok
= element
->value
;
2107 const AffixPatternsForCurrency
* affixPtn
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
2108 UBool tmpStatus
[fgStatusLength
];
2109 ParsePosition
tmpPos(origPos
);
2110 DigitList tmpDigitList
;
2111 UBool result
= subparse(text
,
2112 &affixPtn
->negPrefixPatternForCurrency
,
2113 &affixPtn
->negSuffixPatternForCurrency
,
2114 &affixPtn
->posPrefixPatternForCurrency
,
2115 &affixPtn
->posSuffixPatternForCurrency
,
2116 TRUE
, affixPtn
->patternType
,
2117 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
2120 if (tmpPos
.getIndex() > maxPosIndex
) {
2121 maxPosIndex
= tmpPos
.getIndex();
2122 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
2123 status
[i
] = tmpStatus
[i
];
2125 digits
= tmpDigitList
;
2128 maxErrorPos
= (tmpPos
.getErrorIndex() > maxErrorPos
) ?
2129 tmpPos
.getErrorIndex() : maxErrorPos
;
2132 // Finally, parse against simple affix to find the match.
2133 // For example, in TestMonster suite,
2134 // if the to-be-parsed text is "-\u00A40,00".
2135 // complexAffixCompare will not find match,
2136 // since there is no ISO code matches "\u00A4",
2137 // and the parse stops at "\u00A4".
2138 // We will just use simple affix comparison (look for exact match)
2140 UBool tmpStatus_2
[fgStatusLength
];
2141 ParsePosition
tmpPos_2(origPos
);
2142 DigitList tmpDigitList_2
;
2143 // set currencySignCount to 0 so that compareAffix function will
2144 // fall to compareSimpleAffix path, not compareComplexAffix path.
2145 // ?? TODO: is it right? need "false"?
2146 UBool result
= subparse(text
,
2147 &fNegativePrefix
, &fNegativeSuffix
,
2148 &fPositivePrefix
, &fPositiveSuffix
,
2149 FALSE
, UCURR_SYMBOL_NAME
,
2150 tmpPos_2
, tmpDigitList_2
, tmpStatus_2
,
2153 if (tmpPos_2
.getIndex() > maxPosIndex
) {
2154 maxPosIndex
= tmpPos_2
.getIndex();
2155 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
2156 status
[i
] = tmpStatus_2
[i
];
2158 digits
= tmpDigitList_2
;
2162 maxErrorPos
= (tmpPos_2
.getErrorIndex() > maxErrorPos
) ?
2163 tmpPos_2
.getErrorIndex() : maxErrorPos
;
2167 //parsePosition.setIndex(origPos);
2168 parsePosition
.setErrorIndex(maxErrorPos
);
2170 parsePosition
.setIndex(maxPosIndex
);
2171 parsePosition
.setErrorIndex(-1);
2178 * Parse the given text into a number. The text is parsed beginning at
2179 * parsePosition, until an unparseable character is seen.
2180 * @param text the string to parse.
2181 * @param negPrefix negative prefix.
2182 * @param negSuffix negative suffix.
2183 * @param posPrefix positive prefix.
2184 * @param posSuffix positive suffix.
2185 * @param currencyParsing whether it is currency parsing or not.
2186 * @param type the currency type to parse against, LONG_NAME only or not.
2187 * @param parsePosition The position at which to being parsing. Upon
2188 * return, the first unparsed character.
2189 * @param digits the DigitList to set to the parsed value.
2190 * @param status output param containing boolean status flags indicating
2191 * whether the value was infinite and whether it was positive.
2192 * @param currency return value for parsed currency, for generic
2193 * currency parsing mode, or NULL for normal parsing. In generic
2194 * currency parsing mode, any currency is parsed, not just the
2195 * currency that this formatter is set to.
2197 UBool
DecimalFormat::subparse(const UnicodeString
& text
,
2198 const UnicodeString
* negPrefix
,
2199 const UnicodeString
* negSuffix
,
2200 const UnicodeString
* posPrefix
,
2201 const UnicodeString
* posSuffix
,
2202 UBool currencyParsing
,
2204 ParsePosition
& parsePosition
,
2205 DigitList
& digits
, UBool
* status
,
2206 UChar
* currency
) const
2208 // The parsing process builds up the number as char string, in the neutral format that
2209 // will be acceptable to the decNumber library, then at the end passes that string
2210 // off for conversion to a decNumber.
2211 UErrorCode err
= U_ZERO_ERROR
;
2212 CharString parsedNum
;
2215 int32_t position
= parsePosition
.getIndex();
2216 int32_t oldStart
= position
;
2217 int32_t textLength
= text
.length(); // One less pointer to follow
2218 UBool strictParse
= !isLenient();
2219 UChar32 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
2220 const UnicodeString
*groupingString
= &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
);
2221 UChar32 groupingChar
= groupingString
->char32At(0);
2222 int32_t groupingStringLength
= groupingString
->length();
2223 int32_t groupingCharLength
= U16_LENGTH(groupingChar
);
2224 UBool groupingUsed
= isGroupingUsed();
2227 UnicodeString
s(dbgbuf
,0,300);;
2228 s
.append((UnicodeString
)"PARSE \"").append(text
.tempSubString(position
)).append((UnicodeString
)"\" " );
2229 #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 ")); }
2235 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);
2238 UBool fastParseOk
= false; /* TRUE iff fast parse is OK */
2239 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
2240 const DecimalFormatInternal
&data
= internalData(fReserved
);
2241 if((data
.fFastParseStatus
==kFastpathYES
) &&
2243 // (negPrefix!=NULL&&negPrefix->isEmpty()) ||
2246 (posPrefix
==NULL
||posPrefix
->isEmpty()) &&
2247 (posSuffix
==NULL
||posSuffix
->isEmpty()) &&
2248 // (negPrefix==NULL||negPrefix->isEmpty()) &&
2249 // (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
2250 TRUE
) { // optimized path
2252 int l
=text
.length();
2254 UChar32 ch
= text
.char32At(j
);
2255 const UnicodeString
*decimalString
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
2256 UChar32 decimalChar
= 0;
2257 UBool intOnly
= FALSE
;
2258 UChar32 lookForGroup
= (groupingUsed
&&intOnly
&&strictParse
)?groupingChar
:0;
2260 int32_t decimalCount
= decimalString
->countChar32(0,3);
2261 if(isParseIntegerOnly()) {
2262 decimalChar
= 0; // not allowed
2263 intOnly
= TRUE
; // Don't look for decimals.
2264 } else if(decimalCount
==1) {
2265 decimalChar
= decimalString
->char32At(0); // Look for this decimal
2266 } else if(decimalCount
==0) {
2267 decimalChar
=0; // NO decimal set
2269 j
=l
+1;//Set counter to end of line, so that we break. Unknown decimal situation.
2273 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
2274 decimalChar
, groupingChar
, ch
,
2276 (strictParse
)?'y':'n');
2278 if(ch
==0x002D) { // '-'
2279 j
=l
+1;//=break - negative number.
2282 parsedNum.append('-',err);
2284 if(j<l) ch = text.char32At(j);
2287 parsedNum
.append('+',err
);
2290 int32_t digit
= ch
- zero
;
2291 if(digit
>=0 && digit
<= 9) {
2292 parsedNum
.append((char)(digit
+ '0'), err
);
2293 if((digitCount
>0) || digit
!=0 || j
==(l
-1)) {
2296 } else if(ch
== 0) { // break out
2299 } else if(ch
== decimalChar
) {
2300 parsedNum
.append((char)('.'), err
);
2301 decimalChar
=0; // no more decimals.
2302 // fastParseHadDecimal=TRUE;
2303 } else if(ch
== lookForGroup
) {
2304 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
2305 } else if(intOnly
&& (lookForGroup
!=0) && !u_isdigit(ch
)) {
2306 // parsing integer only and can fall through
2308 digitCount
=-1; // fail - fall through to slow parse
2312 ch
= text
.char32At(j
); // for next
2315 ((j
==l
)||intOnly
) // end OR only parsing integer
2316 && (digitCount
>0)) { // and have at least one digit
2318 printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j
, parsedNum
.data(), digitCount
, fGroupingSize
, fGroupingSize2
);
2320 fastParseOk
=true; // Fast parse OK!
2324 /* for testing, try it the slow way. also */
2328 parsePosition
.setIndex(position
=j
);
2329 status
[fgStatusInfinite
]=false;
2332 // was not OK. reset, retry
2334 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j
, l
, digitCount
);
2340 printf("Could not fastpath parse. ");
2341 printf("fFormatWidth=%d ", fFormatWidth
);
2342 printf("text.length()=%d ", text
.length());
2343 printf("posPrefix=%p posSuffix=%p ", posPrefix
, posSuffix
);
2350 #if UCONFIG_HAVE_PARSEALLINPUT
2351 && fParseAllInput
!=UNUM_YES
2355 // Match padding before prefix
2356 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforePrefix
) {
2357 position
= skipPadding(text
, position
);
2360 // Match positive and negative prefixes; prefer longest match.
2361 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, posPrefix
, currencyParsing
, type
, currency
);
2362 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, negPrefix
, currencyParsing
, type
, currency
);
2363 if (posMatch
>= 0 && negMatch
>= 0) {
2364 if (posMatch
> negMatch
) {
2366 } else if (negMatch
> posMatch
) {
2370 if (posMatch
>= 0) {
2371 position
+= posMatch
;
2372 parsedNum
.append('+', err
);
2373 } else if (negMatch
>= 0) {
2374 position
+= negMatch
;
2375 parsedNum
.append('-', err
);
2376 } else if (strictParse
){
2377 parsePosition
.setErrorIndex(position
);
2380 // Temporary set positive. This might be changed after checking suffix
2381 parsedNum
.append('+', err
);
2384 // Match padding before prefix
2385 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterPrefix
) {
2386 position
= skipPadding(text
, position
);
2389 if (! strictParse
) {
2390 position
= skipUWhiteSpace(text
, position
);
2393 // process digits or Inf, find decimal position
2394 const UnicodeString
*inf
= &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
2395 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
2396 ? 0 : inf
->length());
2397 position
+= infLen
; // infLen is non-zero when it does equal to infinity
2398 status
[fgStatusInfinite
] = infLen
!= 0;
2401 parsedNum
.append("Infinity", err
);
2403 // We now have a string of digits, possibly with grouping symbols,
2404 // and decimal points. We want to process these into a DigitList.
2405 // We don't want to put a bunch of leading zeros into the DigitList
2406 // though, so we keep track of the location of the decimal point,
2407 // put only significant digits into the DigitList, and adjust the
2408 // exponent as needed.
2411 UBool strictFail
= FALSE
; // did we exit with a strict parse failure?
2412 int32_t lastGroup
= -1; // where did we last see a grouping separator?
2413 int32_t digitStart
= position
;
2414 int32_t gs2
= fGroupingSize2
== 0 ? fGroupingSize
: fGroupingSize2
;
2416 const UnicodeString
*decimalString
;
2417 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
2418 decimalString
= &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
2420 decimalString
= &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
2422 UChar32 decimalChar
= decimalString
->char32At(0);
2423 int32_t decimalStringLength
= decimalString
->length();
2424 int32_t decimalCharLength
= U16_LENGTH(decimalChar
);
2426 UBool sawDecimal
= FALSE
;
2427 UChar32 sawDecimalChar
= 0xFFFF;
2428 UBool sawGrouping
= FALSE
;
2429 UChar32 sawGroupingChar
= 0xFFFF;
2430 UBool sawDigit
= FALSE
;
2431 int32_t backup
= -1;
2434 // equivalent grouping and decimal support
2435 const UnicodeSet
*decimalSet
= NULL
;
2436 const UnicodeSet
*groupingSet
= NULL
;
2438 if (decimalCharLength
== decimalStringLength
) {
2439 decimalSet
= DecimalFormatStaticSets::getSimilarDecimals(decimalChar
, strictParse
);
2442 if (groupingCharLength
== groupingStringLength
) {
2444 groupingSet
= DecimalFormatStaticSets::gStaticSets
->fStrictDefaultGroupingSeparators
;
2446 groupingSet
= DecimalFormatStaticSets::gStaticSets
->fDefaultGroupingSeparators
;
2450 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
2451 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
2452 // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
2454 // We have to track digitCount ourselves, because digits.fCount will
2455 // pin when the maximum allowable digits is reached.
2456 int32_t digitCount
= 0;
2457 int32_t integerDigitCount
= 0;
2459 for (; position
< textLength
; )
2461 UChar32 ch
= text
.char32At(position
);
2463 /* We recognize all digit ranges, not only the Latin digit range
2464 * '0'..'9'. We do so by using the Character.digit() method,
2465 * which converts a valid Unicode digit to the range 0..9.
2467 * The character 'ch' may be a digit. If so, place its value
2468 * from 0 to 9 in 'digit'. First try using the locale digit,
2469 * which may or MAY NOT be a standard Unicode digit range. If
2470 * this fails, try using the standard Unicode digit ranges by
2471 * calling Character.digit(). If this also fails, digit will
2472 * have a value outside the range 0..9.
2475 if (digit
< 0 || digit
> 9)
2477 digit
= u_charDigitValue(ch
);
2480 // As a last resort, look through the localized digits if the zero digit
2481 // is not a "standard" Unicode digit.
2482 if ( (digit
< 0 || digit
> 9) && u_charDigitValue(zero
) != 0) {
2484 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is:
2485 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits.
2486 if ( zero
!=0x3007 || ch
!=0x96F6 ) {
2487 for (digit
= 1 ; digit
< 10 ; digit
++ ) {
2488 if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)(DecimalFormatSymbols::kOneDigitSymbol
+digit
-1)).char32At(0) == ch
) {
2495 if (digit
>= 0 && digit
<= 9)
2497 if (strictParse
&& backup
!= -1) {
2498 // comma followed by digit, so group before comma is a
2499 // secondary group. If there was a group separator
2500 // before that, the group must == the secondary group
2501 // length, else it can be <= the the secondary group
2503 if ((lastGroup
!= -1 && backup
- lastGroup
- 1 != gs2
) ||
2504 (lastGroup
== -1 && position
- digitStart
- 1 > gs2
)) {
2512 // Cancel out backup setting (see grouping handler below)
2516 // Note: this will append leading zeros
2517 parsedNum
.append((char)(digit
+ '0'), err
);
2519 // count any digit that's not a leading zero
2520 if (digit
> 0 || digitCount
> 0 || sawDecimal
) {
2523 // count any integer digit that's not a leading zero
2525 integerDigitCount
+= 1;
2529 position
+= U16_LENGTH(ch
);
2531 else if (groupingStringLength
> 0 &&
2532 matchGrouping(groupingChar
, sawGrouping
, sawGroupingChar
, groupingSet
,
2533 decimalChar
, decimalSet
,
2534 ch
) && groupingUsed
)
2541 if ( (!sawDigit
&& groupingSet
!=NULL
&& u_isWhitespace(ch
)) || backup
!= -1 ) {
2542 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for
2543 // backward compatibility) as long as it is not one of the breaking whitespace characters
2544 // that is only treated as a group separator because of the equivalence set. If we get
2545 // here it is because the leading sep was such a breaking space, or there were multiple
2546 // group separators in a row. Note that the DecimalFormat documentation says
2547 // "During parsing, grouping separators are ignored" and that was for strict parsing,
2548 // so we may need to further revisit this strictParse restriction to ensure compatibility.
2549 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F.
2550 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP).
2556 // Ignore grouping characters, if we are using them, but require
2557 // that they be followed by a digit. Otherwise we backup and
2560 position
+= groupingStringLength
;
2562 // Once we see a grouping character, we only accept that grouping character from then on.
2565 else if (matchDecimal(decimalChar
,sawDecimal
,sawDecimalChar
, decimalSet
, ch
))
2569 (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1)) {
2575 // If we're only parsing integers, or if we ALREADY saw the
2576 // decimal, then don't parse this one.
2577 if (isParseIntegerOnly() || sawDecimal
) {
2581 parsedNum
.append('.', err
);
2582 position
+= decimalStringLength
;
2584 // Once we see a decimal character, we only accept that decimal character from then on.
2586 // decimalSet is considered to consist of (ch,ch)
2590 if(!fBoolFlags
.contains(UNUM_PARSE_NO_EXPONENT
) || // don't parse if this is set unless..
2591 fUseExponentialNotation
/* should be: isScientificNotation() but it is not const (?!) see bug #9619 */) { // .. it's an exponent format - ignore setting and parse anyways
2592 const UnicodeString
*tmp
;
2593 tmp
= &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
2595 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
2597 // Parse sign, if present
2598 int32_t pos
= position
+ tmp
->length();
2599 char exponentSign
= '+';
2601 if (pos
< textLength
)
2603 tmp
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2604 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2606 pos
+= tmp
->length();
2609 tmp
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2610 if (!text
.compare(pos
, tmp
->length(), *tmp
))
2613 pos
+= tmp
->length();
2618 UBool sawExponentDigit
= FALSE
;
2619 while (pos
< textLength
) {
2620 ch
= text
[(int32_t)pos
];
2623 if (digit
< 0 || digit
> 9) {
2624 digit
= u_charDigitValue(ch
);
2626 if (0 <= digit
&& digit
<= 9) {
2627 if (!sawExponentDigit
) {
2628 parsedNum
.append('E', err
);
2629 parsedNum
.append(exponentSign
, err
);
2630 sawExponentDigit
= TRUE
;
2633 parsedNum
.append((char)(digit
+ '0'), err
);
2639 if (sawExponentDigit
) {
2640 position
= pos
; // Advance past the exponent
2643 break; // Whether we fail or succeed, we exit this loop
2647 } else { // not parsing exponent
2658 if (strictParse
&& !sawDecimal
) {
2659 if (lastGroup
!= -1 && position
- lastGroup
!= fGroupingSize
+ 1) {
2665 // only set with strictParse and a grouping separator error
2667 parsePosition
.setIndex(oldStart
);
2668 parsePosition
.setErrorIndex(position
);
2669 debug("strictFail!");
2673 // If there was no decimal point we have an integer
2675 // If none of the text string was recognized. For example, parse
2676 // "x" with pattern "#0.00" (return index and error index both 0)
2677 // parse "$" with pattern "$#0.00". (return index 0 and error index
2679 if (!sawDigit
&& digitCount
== 0) {
2681 debug("none of text rec");
2682 printf("position=%d\n",position
);
2684 parsePosition
.setIndex(oldStart
);
2685 parsePosition
.setErrorIndex(oldStart
);
2690 // Match padding before suffix
2691 if (fFormatWidth
> 0 && fPadPosition
== kPadBeforeSuffix
) {
2692 position
= skipPadding(text
, position
);
2695 int32_t posSuffixMatch
= -1, negSuffixMatch
= -1;
2697 // Match positive and negative suffixes; prefer longest match.
2698 if (posMatch
>= 0 || (!strictParse
&& negMatch
< 0)) {
2699 posSuffixMatch
= compareAffix(text
, position
, FALSE
, FALSE
, posSuffix
, currencyParsing
, type
, currency
);
2701 if (negMatch
>= 0) {
2702 negSuffixMatch
= compareAffix(text
, position
, TRUE
, FALSE
, negSuffix
, currencyParsing
, type
, currency
);
2704 if (posSuffixMatch
>= 0 && negSuffixMatch
>= 0) {
2705 if (posSuffixMatch
> negSuffixMatch
) {
2706 negSuffixMatch
= -1;
2707 } else if (negSuffixMatch
> posSuffixMatch
) {
2708 posSuffixMatch
= -1;
2712 // Fail if neither or both
2713 if (strictParse
&& ((posSuffixMatch
>= 0) == (negSuffixMatch
>= 0))) {
2714 parsePosition
.setErrorIndex(position
);
2715 debug("neither or both");
2719 position
+= (posSuffixMatch
>= 0 ? posSuffixMatch
: (negSuffixMatch
>= 0 ? negSuffixMatch
: 0));
2721 // Match padding before suffix
2722 if (fFormatWidth
> 0 && fPadPosition
== kPadAfterSuffix
) {
2723 position
= skipPadding(text
, position
);
2726 parsePosition
.setIndex(position
);
2728 parsedNum
.data()[0] = (posSuffixMatch
>= 0 || (!strictParse
&& negMatch
< 0 && negSuffixMatch
< 0)) ? '+' : '-';
2730 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position
, parsedNum
.data(), parsePosition
.getIndex(),oldStart
,u_errorName(err
));
2732 } /* end SLOW parse */
2733 if(parsePosition
.getIndex() == oldStart
)
2736 printf(" PP didnt move, err\n");
2738 parsePosition
.setErrorIndex(position
);
2741 #if UCONFIG_HAVE_PARSEALLINPUT
2742 else if (fParseAllInput
==UNUM_YES
&&parsePosition
.getIndex()!=textLength
)
2745 printf(" PP didnt consume all (UNUM_YES), err\n");
2747 parsePosition
.setErrorIndex(position
);
2751 // uint32_t bits = (fastParseOk?kFastpathOk:0) |
2752 // (fastParseHadDecimal?0:kNoDecimal);
2753 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
2754 digits
.set(parsedNum
.toStringPiece(),
2759 if (U_FAILURE(err
)) {
2761 printf(" err setting %s\n", u_errorName(err
));
2763 parsePosition
.setErrorIndex(position
);
2770 * Starting at position, advance past a run of pad characters, if any.
2771 * Return the index of the first character after position that is not a pad
2772 * character. Result is >= position.
2774 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
2775 int32_t padLen
= U16_LENGTH(fPad
);
2776 while (position
< text
.length() &&
2777 text
.char32At(position
) == fPad
) {
2784 * Return the length matched by the given affix, or -1 if none.
2785 * Runs of white space in the affix, match runs of white space in
2786 * the input. Pattern white space and input white space are
2787 * determined differently; see code.
2788 * @param text input text
2789 * @param pos offset into input at which to begin matching
2792 * @param affixPat affix pattern used for currency affix comparison.
2793 * @param currencyParsing whether it is currency parsing or not
2794 * @param type the currency type to parse against, LONG_NAME only or not.
2795 * @param currency return value for parsed currency, for generic
2796 * currency parsing mode, or null for normal parsing. In generic
2797 * currency parsing mode, any currency is parsed, not just the
2798 * currency that this formatter is set to.
2799 * @return length of input that matches, or -1 if match failure
2801 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
2805 const UnicodeString
* affixPat
,
2806 UBool currencyParsing
,
2808 UChar
* currency
) const
2810 const UnicodeString
*patternToCompare
;
2811 if (fCurrencyChoice
!= NULL
|| currency
!= NULL
||
2812 (fCurrencySignCount
> fgCurrencySignCountZero
&& currencyParsing
)) {
2814 if (affixPat
!= NULL
) {
2815 return compareComplexAffix(*affixPat
, text
, pos
, type
, currency
);
2821 patternToCompare
= &fNegativePrefix
;
2824 patternToCompare
= &fNegativeSuffix
;
2829 patternToCompare
= &fPositivePrefix
;
2832 patternToCompare
= &fPositiveSuffix
;
2835 return compareSimpleAffix(*patternToCompare
, text
, pos
, isLenient());
2839 * Return the length matched by the given affix, or -1 if none.
2840 * Runs of white space in the affix, match runs of white space in
2841 * the input. Pattern white space and input white space are
2842 * determined differently; see code.
2843 * @param affix pattern string, taken as a literal
2844 * @param input input text
2845 * @param pos offset into input at which to begin matching
2846 * @return length of input that matches, or -1 if match failure
2848 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
2849 const UnicodeString
& input
,
2852 int32_t start
= pos
;
2853 UChar32 affixChar
= affix
.char32At(0);
2854 int32_t affixLength
= affix
.length();
2855 int32_t inputLength
= input
.length();
2856 int32_t affixCharLength
= U16_LENGTH(affixChar
);
2857 UnicodeSet
*affixSet
;
2860 affixSet
= DecimalFormatStaticSets::gStaticSets
->fStrictDashEquivalents
;
2862 // If the affix is exactly one character long and that character
2863 // is in the dash set and the very next input character is also
2864 // in the dash set, return a match.
2865 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2866 if (affixSet
->contains(input
.char32At(pos
))) {
2871 for (int32_t i
= 0; i
< affixLength
; ) {
2872 UChar32 c
= affix
.char32At(i
);
2873 int32_t len
= U16_LENGTH(c
);
2874 if (PatternProps::isWhiteSpace(c
)) {
2875 // We may have a pattern like: \u200F \u0020
2876 // and input text like: \u200F \u0020
2877 // Note that U+200F and U+0020 are Pattern_White_Space but only
2878 // U+0020 is UWhiteSpace. So we have to first do a direct
2879 // match of the run of Pattern_White_Space in the pattern,
2880 // then match any extra characters.
2881 UBool literalMatch
= FALSE
;
2882 while (pos
< inputLength
&&
2883 input
.char32At(pos
) == c
) {
2884 literalMatch
= TRUE
;
2887 if (i
== affixLength
) {
2890 c
= affix
.char32At(i
);
2891 len
= U16_LENGTH(c
);
2892 if (!PatternProps::isWhiteSpace(c
)) {
2897 // Advance over run in pattern
2898 i
= skipPatternWhiteSpace(affix
, i
);
2900 UBool patternWhitespaceWasJustMark
= (i
== 1 && (c
== 0x200E || c
== 0x200F));
2902 // Advance over run in input text
2903 // Must see at least one white space char in input,
2904 // unless we've already matched some characters literally,
2905 // or unless the pattern whitespace was just LRM/RLM
2907 pos
= skipUWhiteSpace(input
, pos
);
2908 if (pos
== s
&& !literalMatch
&& !patternWhitespaceWasJustMark
) {
2912 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2913 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2914 // is also in the affix.
2915 i
= skipUWhiteSpace(affix
, i
);
2917 if (pos
< inputLength
&&
2918 input
.char32At(pos
) == c
) {
2927 UBool match
= FALSE
;
2929 affixSet
= DecimalFormatStaticSets::gStaticSets
->fDashEquivalents
;
2931 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2932 pos
= skipUWhiteSpace(input
, pos
);
2934 if (affixSet
->contains(input
.char32At(pos
))) {
2935 return pos
- start
+ 1;
2939 for (int32_t i
= 0; i
< affixLength
; )
2941 //i = skipRuleWhiteSpace(affix, i);
2942 i
= skipUWhiteSpace(affix
, i
);
2943 pos
= skipUWhiteSpace(input
, pos
);
2945 if (i
>= affixLength
|| pos
>= inputLength
) {
2949 UChar32 c
= affix
.char32At(i
);
2950 int32_t len
= U16_LENGTH(c
);
2952 if (input
.char32At(pos
) != c
) {
2961 if (affixLength
> 0 && ! match
) {
2969 * Skip over a run of zero or more Pattern_White_Space characters at
2972 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2973 const UChar
* s
= text
.getBuffer();
2974 return (int32_t)(PatternProps::skipWhiteSpace(s
+ pos
, text
.length() - pos
) - s
);
2978 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2981 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2982 while (pos
< text
.length()) {
2983 UChar32 c
= text
.char32At(pos
);
2984 if (!u_isUWhiteSpace(c
) && c
!=0x200E && c
!=0x200F) { // u_isUWhiteSpace does not include LRM,RLM
2987 pos
+= U16_LENGTH(c
);
2993 * Return the length matched by the given affix, or -1 if none.
2994 * @param affixPat pattern string
2995 * @param input input text
2996 * @param pos offset into input at which to begin matching
2997 * @param type the currency type to parse against, LONG_NAME only or not.
2998 * @param currency return value for parsed currency, for generic
2999 * currency parsing mode, or null for normal parsing. In generic
3000 * currency parsing mode, any currency is parsed, not just the
3001 * currency that this formatter is set to.
3002 * @return length of input that matches, or -1 if match failure
3004 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
3005 const UnicodeString
& text
,
3008 UChar
* currency
) const
3010 int32_t start
= pos
;
3011 U_ASSERT(currency
!= NULL
||
3012 (fCurrencyChoice
!= NULL
&& *getCurrency() != 0) ||
3013 fCurrencySignCount
> fgCurrencySignCountZero
);
3016 i
<affixPat
.length() && pos
>= 0; ) {
3017 UChar32 c
= affixPat
.char32At(i
);
3021 U_ASSERT(i
<= affixPat
.length());
3022 c
= affixPat
.char32At(i
);
3025 const UnicodeString
* affix
= NULL
;
3028 case kCurrencySign
: {
3029 // since the currency names in choice format is saved
3030 // the same way as other currency names,
3031 // do not need to do currency choice parsing here.
3032 // the general currency parsing parse against all names,
3033 // including names in choice format.
3034 UBool intl
= i
<affixPat
.length() &&
3035 affixPat
.char32At(i
) == kCurrencySign
;
3039 UBool plural
= i
<affixPat
.length() &&
3040 affixPat
.char32At(i
) == kCurrencySign
;
3045 // Parse generic currency -- anything for which we
3046 // have a display name, or any 3-letter ISO code.
3047 // Try to parse display name for our locale; first
3048 // determine our locale.
3049 const char* loc
= fCurrencyPluralInfo
->getLocale().getName();
3050 ParsePosition
ppos(pos
);
3052 UErrorCode ec
= U_ZERO_ERROR
;
3053 // Delegate parse of display name => ISO code to Currency
3054 uprv_parseCurrency(loc
, text
, ppos
, type
, curr
, ec
);
3056 // If parse succeeds, populate currency[0]
3057 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
3059 u_strcpy(currency
, curr
);
3061 // The formatter is currency-style but the client has not requested
3062 // the value of the parsed currency. In this case, if that value does
3063 // not match the formatter's current value, then the parse fails.
3064 UChar effectiveCurr
[4];
3065 getEffectiveCurrency(effectiveCurr
, ec
);
3066 if ( U_FAILURE(ec
) || u_strncmp(curr
,effectiveCurr
,4) != 0 ) {
3071 pos
= ppos
.getIndex();
3072 } else if (!isLenient()){
3077 case kPatternPercent
:
3078 affix
= &getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
3080 case kPatternPerMill
:
3081 affix
= &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
3084 affix
= &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
3087 affix
= &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
3090 // fall through to affix!=0 test, which will fail
3094 if (affix
!= NULL
) {
3095 pos
= match(text
, pos
, *affix
);
3100 pos
= match(text
, pos
, c
);
3101 if (PatternProps::isWhiteSpace(c
)) {
3102 i
= skipPatternWhiteSpace(affixPat
, i
);
3109 * Match a single character at text[pos] and return the index of the
3110 * next character upon success. Return -1 on failure. If
3111 * ch is a Pattern_White_Space then match a run of white space in text.
3113 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
3114 if (PatternProps::isWhiteSpace(ch
)) {
3115 // Advance over run of white space in input text
3116 // Must see at least one white space char in input
3118 pos
= skipPatternWhiteSpace(text
, pos
);
3124 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
3125 (pos
+ U16_LENGTH(ch
)) : -1;
3129 * Match a string at text[pos] and return the index of the next
3130 * character upon success. Return -1 on failure. Match a run of
3131 * white space in str with a run of white space in text.
3133 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
3134 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
3135 UChar32 ch
= str
.char32At(i
);
3136 i
+= U16_LENGTH(ch
);
3137 if (PatternProps::isWhiteSpace(ch
)) {
3138 i
= skipPatternWhiteSpace(str
, i
);
3140 pos
= match(text
, pos
, ch
);
3145 UBool
DecimalFormat::matchSymbol(const UnicodeString
&text
, int32_t position
, int32_t length
, const UnicodeString
&symbol
,
3146 UnicodeSet
*sset
, UChar32 schar
)
3149 return sset
->contains(schar
);
3152 return text
.compare(position
, length
, symbol
) == 0;
3155 UBool
DecimalFormat::matchDecimal(UChar32 symbolChar
,
3156 UBool sawDecimal
, UChar32 sawDecimalChar
,
3157 const UnicodeSet
*sset
, UChar32 schar
) {
3159 return schar
==sawDecimalChar
;
3160 } else if(schar
==symbolChar
) {
3162 } else if(sset
!=NULL
) {
3163 return sset
->contains(schar
);
3169 UBool
DecimalFormat::matchGrouping(UChar32 groupingChar
,
3170 UBool sawGrouping
, UChar32 sawGroupingChar
,
3171 const UnicodeSet
*sset
,
3172 UChar32
/*decimalChar*/, const UnicodeSet
*decimalSet
,
3175 return schar
==sawGroupingChar
; // previously found
3176 } else if(schar
==groupingChar
) {
3177 return TRUE
; // char from symbols
3178 } else if(sset
!=NULL
) {
3179 return sset
->contains(schar
) && // in groupingSet but...
3180 ((decimalSet
==NULL
) || !decimalSet
->contains(schar
)); // Exclude decimalSet from groupingSet
3188 //------------------------------------------------------------------------------
3189 // Gets the pointer to the localized decimal format symbols
3191 const DecimalFormatSymbols
*
3192 DecimalFormat::getDecimalFormatSymbols() const
3197 //------------------------------------------------------------------------------
3198 // De-owning the current localized symbols and adopt the new symbols.
3201 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
3203 if (symbolsToAdopt
== NULL
) {
3204 return; // do not allow caller to set fSymbols to NULL
3207 UBool sameSymbols
= FALSE
;
3208 if (fSymbols
!= NULL
) {
3209 sameSymbols
= (UBool
)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) ==
3210 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) &&
3211 getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) ==
3212 symbolsToAdopt
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
3216 fSymbols
= symbolsToAdopt
;
3218 // If the currency symbols are the same, there is no need to recalculate.
3219 setCurrencyForSymbols();
3221 expandAffixes(NULL
);
3222 #if UCONFIG_FORMAT_FASTPATHS_49
3226 //------------------------------------------------------------------------------
3227 // Setting the symbols is equlivalent to adopting a newly created localized
3231 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
3233 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
3234 #if UCONFIG_FORMAT_FASTPATHS_49
3240 const CurrencyPluralInfo
*
3241 DecimalFormat::getCurrencyPluralInfo(void) const
3243 return fCurrencyPluralInfo
;
3248 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo
* toAdopt
)
3250 if (toAdopt
!= NULL
) {
3251 delete fCurrencyPluralInfo
;
3252 fCurrencyPluralInfo
= toAdopt
;
3253 // re-set currency affix patterns and currency affixes.
3254 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
3255 UErrorCode status
= U_ZERO_ERROR
;
3256 if (fAffixPatternsForCurrency
) {
3257 deleteHashForAffixPattern();
3259 setupCurrencyAffixPatterns(status
);
3260 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
3261 // only setup the affixes of the plural pattern.
3262 setupCurrencyAffixes(fFormatPattern
, FALSE
, TRUE
, status
);
3266 #if UCONFIG_FORMAT_FASTPATHS_49
3272 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo
& info
)
3274 adoptCurrencyPluralInfo(info
.clone());
3275 #if UCONFIG_FORMAT_FASTPATHS_49
3282 * Update the currency object to match the symbols. This method
3283 * is used only when the caller has passed in a symbols object
3284 * that may not be the default object for its locale.
3287 DecimalFormat::setCurrencyForSymbols() {
3289 Update the affix strings accroding to symbols in order to keep
3290 the affix strings up to date.
3294 // With the introduction of the Currency object, the currency
3295 // symbols in the DFS object are ignored. For backward
3296 // compatibility, we check any explicitly set DFS object. If it
3297 // is a default symbols object for its locale, we change the
3298 // currency object to one for that locale. If it is custom,
3299 // we set the currency to null.
3300 UErrorCode ec
= U_ZERO_ERROR
;
3301 const UChar
* c
= NULL
;
3302 const char* loc
= fSymbols
->getLocale().getName();
3303 UChar intlCurrencySymbol
[4];
3304 ucurr_forLocale(loc
, intlCurrencySymbol
, 4, &ec
);
3305 UnicodeString currencySymbol
;
3307 uprv_getStaticCurrencyName(intlCurrencySymbol
, loc
, currencySymbol
, ec
);
3309 && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
) == currencySymbol
3310 && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
) == UnicodeString(intlCurrencySymbol
))
3312 // Trap an error in mapping locale to currency. If we can't
3313 // map, then don't fail and set the currency to "".
3314 c
= intlCurrencySymbol
;
3316 ec
= U_ZERO_ERROR
; // reset local error code!
3317 setCurrencyInternally(c
, ec
);
3318 #if UCONFIG_FORMAT_FASTPATHS_49
3324 //------------------------------------------------------------------------------
3325 // Gets the positive prefix of the number pattern.
3328 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
3330 result
= fPositivePrefix
;
3334 //------------------------------------------------------------------------------
3335 // Sets the positive prefix of the number pattern.
3338 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
3340 fPositivePrefix
= newValue
;
3341 delete fPosPrefixPattern
;
3342 fPosPrefixPattern
= 0;
3343 #if UCONFIG_FORMAT_FASTPATHS_49
3348 //------------------------------------------------------------------------------
3349 // Gets the negative prefix of the number pattern.
3352 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
3354 result
= fNegativePrefix
;
3358 //------------------------------------------------------------------------------
3359 // Gets the negative prefix of the number pattern.
3362 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
3364 fNegativePrefix
= newValue
;
3365 delete fNegPrefixPattern
;
3366 fNegPrefixPattern
= 0;
3367 #if UCONFIG_FORMAT_FASTPATHS_49
3372 //------------------------------------------------------------------------------
3373 // Gets the positive suffix of the number pattern.
3376 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
3378 result
= fPositiveSuffix
;
3382 //------------------------------------------------------------------------------
3383 // Sets the positive suffix of the number pattern.
3386 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
3388 fPositiveSuffix
= newValue
;
3389 delete fPosSuffixPattern
;
3390 fPosSuffixPattern
= 0;
3391 #if UCONFIG_FORMAT_FASTPATHS_49
3396 //------------------------------------------------------------------------------
3397 // Gets the negative suffix of the number pattern.
3400 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
3402 result
= fNegativeSuffix
;
3406 //------------------------------------------------------------------------------
3407 // Sets the negative suffix of the number pattern.
3410 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
3412 fNegativeSuffix
= newValue
;
3413 delete fNegSuffixPattern
;
3414 fNegSuffixPattern
= 0;
3415 #if UCONFIG_FORMAT_FASTPATHS_49
3420 //------------------------------------------------------------------------------
3421 // Gets the multiplier of the number pattern.
3422 // Multipliers are stored as decimal numbers (DigitLists) because that
3423 // is the most convenient for muliplying or dividing the numbers to be formatted.
3424 // A NULL multiplier implies one, and the scaling operations are skipped.
3427 DecimalFormat::getMultiplier() const
3429 if (fMultiplier
== NULL
) {
3432 return fMultiplier
->getLong();
3436 //------------------------------------------------------------------------------
3437 // Sets the multiplier of the number pattern.
3439 DecimalFormat::setMultiplier(int32_t newValue
)
3441 // if (newValue == 0) {
3442 // throw new IllegalArgumentException("Bad multiplier: " + newValue);
3444 if (newValue
== 0) {
3445 newValue
= 1; // one being the benign default value for a multiplier.
3447 if (newValue
== 1) {
3451 if (fMultiplier
== NULL
) {
3452 fMultiplier
= new DigitList
;
3454 if (fMultiplier
!= NULL
) {
3455 fMultiplier
->set(newValue
);
3458 #if UCONFIG_FORMAT_FASTPATHS_49
3464 * Get the rounding increment.
3465 * @return A positive rounding increment, or 0.0 if rounding
3467 * @see #setRoundingIncrement
3468 * @see #getRoundingMode
3469 * @see #setRoundingMode
3471 double DecimalFormat::getRoundingIncrement() const {
3472 if (fRoundingIncrement
== NULL
) {
3475 return fRoundingIncrement
->getDouble();
3480 * Set the rounding increment. This method also controls whether
3481 * rounding is enabled.
3482 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
3483 * Negative increments are equivalent to 0.0.
3484 * @see #getRoundingIncrement
3485 * @see #getRoundingMode
3486 * @see #setRoundingMode
3488 void DecimalFormat::setRoundingIncrement(double newValue
) {
3489 if (newValue
> 0.0) {
3490 if (fRoundingIncrement
== NULL
) {
3491 fRoundingIncrement
= new DigitList();
3493 if (fRoundingIncrement
!= NULL
) {
3494 fRoundingIncrement
->set(newValue
);
3498 // These statements are executed if newValue is less than 0.0
3499 // or fRoundingIncrement could not be created.
3500 delete fRoundingIncrement
;
3501 fRoundingIncrement
= NULL
;
3502 #if UCONFIG_FORMAT_FASTPATHS_49
3508 * Get the rounding mode.
3509 * @return A rounding mode
3510 * @see #setRoundingIncrement
3511 * @see #getRoundingIncrement
3512 * @see #setRoundingMode
3514 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
3515 return fRoundingMode
;
3519 * Set the rounding mode. This has no effect unless the rounding
3520 * increment is greater than zero.
3521 * @param roundingMode A rounding mode
3522 * @see #setRoundingIncrement
3523 * @see #getRoundingIncrement
3524 * @see #getRoundingMode
3526 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
3527 fRoundingMode
= roundingMode
;
3528 #if UCONFIG_FORMAT_FASTPATHS_49
3534 * Get the width to which the output of <code>format()</code> is padded.
3535 * @return the format width, or zero if no padding is in effect
3536 * @see #setFormatWidth
3537 * @see #getPadCharacter
3538 * @see #setPadCharacter
3539 * @see #getPadPosition
3540 * @see #setPadPosition
3542 int32_t DecimalFormat::getFormatWidth() const {
3543 return fFormatWidth
;
3547 * Set the width to which the output of <code>format()</code> is padded.
3548 * This method also controls whether padding is enabled.
3549 * @param width the width to which to pad the result of
3550 * <code>format()</code>, or zero to disable padding. A negative
3551 * width is equivalent to 0.
3552 * @see #getFormatWidth
3553 * @see #getPadCharacter
3554 * @see #setPadCharacter
3555 * @see #getPadPosition
3556 * @see #setPadPosition
3558 void DecimalFormat::setFormatWidth(int32_t width
) {
3559 fFormatWidth
= (width
> 0) ? width
: 0;
3560 #if UCONFIG_FORMAT_FASTPATHS_49
3565 UnicodeString
DecimalFormat::getPadCharacterString() const {
3566 return UnicodeString(fPad
);
3569 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
3570 if (padChar
.length() > 0) {
3571 fPad
= padChar
.char32At(0);
3576 #if UCONFIG_FORMAT_FASTPATHS_49
3582 * Get the position at which padding will take place. This is the location
3583 * at which padding will be inserted if the result of <code>format()</code>
3584 * is shorter than the format width.
3585 * @return the pad position, one of <code>kPadBeforePrefix</code>,
3586 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3587 * <code>kPadAfterSuffix</code>.
3588 * @see #setFormatWidth
3589 * @see #getFormatWidth
3590 * @see #setPadCharacter
3591 * @see #getPadCharacter
3592 * @see #setPadPosition
3593 * @see #kPadBeforePrefix
3594 * @see #kPadAfterPrefix
3595 * @see #kPadBeforeSuffix
3596 * @see #kPadAfterSuffix
3598 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
3599 return fPadPosition
;
3603 * <strong><font face=helvetica color=red>NEW</font></strong>
3604 * Set the position at which padding will take place. This is the location
3605 * at which padding will be inserted if the result of <code>format()</code>
3606 * is shorter than the format width. This has no effect unless padding is
3608 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
3609 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
3610 * <code>kPadAfterSuffix</code>.
3611 * @see #setFormatWidth
3612 * @see #getFormatWidth
3613 * @see #setPadCharacter
3614 * @see #getPadCharacter
3615 * @see #getPadPosition
3616 * @see #kPadBeforePrefix
3617 * @see #kPadAfterPrefix
3618 * @see #kPadBeforeSuffix
3619 * @see #kPadAfterSuffix
3621 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
3622 fPadPosition
= padPos
;
3623 #if UCONFIG_FORMAT_FASTPATHS_49
3629 * Return whether or not scientific notation is used.
3630 * @return TRUE if this object formats and parses scientific notation
3631 * @see #setScientificNotation
3632 * @see #getMinimumExponentDigits
3633 * @see #setMinimumExponentDigits
3634 * @see #isExponentSignAlwaysShown
3635 * @see #setExponentSignAlwaysShown
3637 UBool
DecimalFormat::isScientificNotation() {
3638 return fUseExponentialNotation
;
3642 * Set whether or not scientific notation is used.
3643 * @param useScientific TRUE if this object formats and parses scientific
3645 * @see #isScientificNotation
3646 * @see #getMinimumExponentDigits
3647 * @see #setMinimumExponentDigits
3648 * @see #isExponentSignAlwaysShown
3649 * @see #setExponentSignAlwaysShown
3651 void DecimalFormat::setScientificNotation(UBool useScientific
) {
3652 fUseExponentialNotation
= useScientific
;
3653 #if UCONFIG_FORMAT_FASTPATHS_49
3659 * Return the minimum exponent digits that will be shown.
3660 * @return the minimum exponent digits that will be shown
3661 * @see #setScientificNotation
3662 * @see #isScientificNotation
3663 * @see #setMinimumExponentDigits
3664 * @see #isExponentSignAlwaysShown
3665 * @see #setExponentSignAlwaysShown
3667 int8_t DecimalFormat::getMinimumExponentDigits() const {
3668 return fMinExponentDigits
;
3672 * Set the minimum exponent digits that will be shown. This has no
3673 * effect unless scientific notation is in use.
3674 * @param minExpDig a value >= 1 indicating the fewest exponent digits
3675 * that will be shown. Values less than 1 will be treated as 1.
3676 * @see #setScientificNotation
3677 * @see #isScientificNotation
3678 * @see #getMinimumExponentDigits
3679 * @see #isExponentSignAlwaysShown
3680 * @see #setExponentSignAlwaysShown
3682 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
3683 fMinExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
3684 #if UCONFIG_FORMAT_FASTPATHS_49
3690 * Return whether the exponent sign is always shown.
3691 * @return TRUE if the exponent is always prefixed with either the
3692 * localized minus sign or the localized plus sign, false if only negative
3693 * exponents are prefixed with the localized minus sign.
3694 * @see #setScientificNotation
3695 * @see #isScientificNotation
3696 * @see #setMinimumExponentDigits
3697 * @see #getMinimumExponentDigits
3698 * @see #setExponentSignAlwaysShown
3700 UBool
DecimalFormat::isExponentSignAlwaysShown() {
3701 return fExponentSignAlwaysShown
;
3705 * Set whether the exponent sign is always shown. This has no effect
3706 * unless scientific notation is in use.
3707 * @param expSignAlways TRUE if the exponent is always prefixed with either
3708 * the localized minus sign or the localized plus sign, false if only
3709 * negative exponents are prefixed with the localized minus sign.
3710 * @see #setScientificNotation
3711 * @see #isScientificNotation
3712 * @see #setMinimumExponentDigits
3713 * @see #getMinimumExponentDigits
3714 * @see #isExponentSignAlwaysShown
3716 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
3717 fExponentSignAlwaysShown
= expSignAlways
;
3718 #if UCONFIG_FORMAT_FASTPATHS_49
3723 //------------------------------------------------------------------------------
3724 // Gets the grouping size of the number pattern. For example, thousand or 10
3725 // thousand groupings.
3728 DecimalFormat::getGroupingSize() const
3730 return fGroupingSize
;
3733 //------------------------------------------------------------------------------
3734 // Gets the grouping size of the number pattern.
3737 DecimalFormat::setGroupingSize(int32_t newValue
)
3739 fGroupingSize
= newValue
;
3740 #if UCONFIG_FORMAT_FASTPATHS_49
3745 //------------------------------------------------------------------------------
3748 DecimalFormat::getSecondaryGroupingSize() const
3750 return fGroupingSize2
;
3753 //------------------------------------------------------------------------------
3756 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
3758 fGroupingSize2
= newValue
;
3759 #if UCONFIG_FORMAT_FASTPATHS_49
3764 //------------------------------------------------------------------------------
3765 // Checks if to show the decimal separator.
3768 DecimalFormat::isDecimalSeparatorAlwaysShown() const
3770 return fDecimalSeparatorAlwaysShown
;
3773 //------------------------------------------------------------------------------
3774 // Sets to always show the decimal separator.
3777 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
3779 fDecimalSeparatorAlwaysShown
= newValue
;
3780 #if UCONFIG_FORMAT_FASTPATHS_49
3785 //------------------------------------------------------------------------------
3786 // Emits the pattern of this DecimalFormat instance.
3789 DecimalFormat::toPattern(UnicodeString
& result
) const
3791 return toPattern(result
, FALSE
);
3794 //------------------------------------------------------------------------------
3795 // Emits the localized pattern this DecimalFormat instance.
3798 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
3800 return toPattern(result
, TRUE
);
3803 //------------------------------------------------------------------------------
3805 * Expand the affix pattern strings into the expanded affix strings. If any
3806 * affix pattern string is null, do not expand it. This method should be
3807 * called any time the symbols or the affix patterns change in order to keep
3808 * the expanded affix strings up to date.
3809 * This method also will be called before formatting if format currency
3810 * plural names, since the plural name is not a static one, it is
3811 * based on the currency plural count, the affix will be known only
3812 * after the currency plural count is know.
3813 * In which case, the parameter
3814 * 'pluralCount' will be a non-null currency plural count.
3815 * In all other cases, the 'pluralCount' is null, which means it is not needed.
3817 void DecimalFormat::expandAffixes(const UnicodeString
* pluralCount
) {
3818 FieldPositionHandler none
;
3819 if (fPosPrefixPattern
!= 0) {
3820 expandAffix(*fPosPrefixPattern
, fPositivePrefix
, 0, none
, FALSE
, pluralCount
);
3822 if (fPosSuffixPattern
!= 0) {
3823 expandAffix(*fPosSuffixPattern
, fPositiveSuffix
, 0, none
, FALSE
, pluralCount
);
3825 if (fNegPrefixPattern
!= 0) {
3826 expandAffix(*fNegPrefixPattern
, fNegativePrefix
, 0, none
, FALSE
, pluralCount
);
3828 if (fNegSuffixPattern
!= 0) {
3829 expandAffix(*fNegSuffixPattern
, fNegativeSuffix
, 0, none
, FALSE
, pluralCount
);
3833 s
.append(UnicodeString("["))
3834 .append(DEREFSTR(fPosPrefixPattern
)).append((UnicodeString
)"|").append(DEREFSTR(fPosSuffixPattern
))
3835 .append((UnicodeString
)";") .append(DEREFSTR(fNegPrefixPattern
)).append((UnicodeString
)"|").append(DEREFSTR(fNegSuffixPattern
))
3836 .append((UnicodeString
)"]->[")
3837 .append(fPositivePrefix
).append((UnicodeString
)"|").append(fPositiveSuffix
)
3838 .append((UnicodeString
)";") .append(fNegativePrefix
).append((UnicodeString
)"|").append(fNegativeSuffix
)
3839 .append((UnicodeString
)"]\n");
3845 * Expand an affix pattern into an affix string. All characters in the
3846 * pattern are literal unless prefixed by kQuote. The following characters
3847 * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
3848 * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
3849 * kCurrencySign + kCurrencySign), it is interpreted as an international
3850 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
3851 * currency plural long names, such as "US Dollars".
3852 * Any other character after a kQuote represents itself.
3853 * kQuote must be followed by another character; kQuote may not occur by
3854 * itself at the end of the pattern.
3856 * This method is used in two distinct ways. First, it is used to expand
3857 * the stored affix patterns into actual affixes. For this usage, doFormat
3858 * must be false. Second, it is used to expand the stored affix patterns
3859 * given a specific number (doFormat == true), for those rare cases in
3860 * which a currency format references a ChoiceFormat (e.g., en_IN display
3861 * name for INR). The number itself is taken from digitList.
3863 * When used in the first way, this method has a side effect: It sets
3864 * currencyChoice to a ChoiceFormat object, if the currency's display name
3865 * in this locale is a ChoiceFormat pattern (very rare). It only does this
3866 * if currencyChoice is null to start with.
3868 * @param pattern the non-null, fPossibly empty pattern
3869 * @param affix string to receive the expanded equivalent of pattern.
3870 * Previous contents are deleted.
3871 * @param doFormat if false, then the pattern will be expanded, and if a
3872 * currency symbol is encountered that expands to a ChoiceFormat, the
3873 * currencyChoice member variable will be initialized if it is null. If
3874 * doFormat is true, then it is assumed that the currencyChoice has been
3875 * created, and it will be used to format the value in digitList.
3876 * @param pluralCount the plural count. It is only used for currency
3877 * plural format. In which case, it is the plural
3878 * count of the currency amount. For example,
3879 * in en_US, it is the singular "one", or the plural
3880 * "other". For all other cases, it is null, and
3881 * is not being used.
3883 void DecimalFormat::expandAffix(const UnicodeString
& pattern
,
3884 UnicodeString
& affix
,
3886 FieldPositionHandler
& handler
,
3888 const UnicodeString
* pluralCount
) const {
3890 for (int i
=0; i
<pattern
.length(); ) {
3891 UChar32 c
= pattern
.char32At(i
);
3894 c
= pattern
.char32At(i
);
3896 int beginIdx
= affix
.length();
3898 case kCurrencySign
: {
3899 // As of ICU 2.2 we use the currency object, and
3900 // ignore the currency symbols in the DFS, unless
3901 // we have a null currency object. This occurs if
3902 // resurrecting a pre-2.2 object or if the user
3903 // sets a custom DFS.
3904 UBool intl
= i
<pattern
.length() &&
3905 pattern
.char32At(i
) == kCurrencySign
;
3906 UBool plural
= FALSE
;
3909 plural
= i
<pattern
.length() &&
3910 pattern
.char32At(i
) == kCurrencySign
;
3916 const UChar
* currencyUChars
= getCurrency();
3917 if (currencyUChars
[0] != 0) {
3918 UErrorCode ec
= U_ZERO_ERROR
;
3919 if (plural
&& pluralCount
!= NULL
) {
3920 // plural name is only needed when pluralCount != null,
3921 // which means when formatting currency plural names.
3922 // For other cases, pluralCount == null,
3923 // and plural names are not needed.
3925 CharString pluralCountChar
;
3926 pluralCountChar
.appendInvariantChars(*pluralCount
, ec
);
3927 UBool isChoiceFormat
;
3928 const UChar
* s
= ucurr_getPluralName(currencyUChars
,
3929 fSymbols
!= NULL
? fSymbols
->getLocale().getName() :
3930 Locale::getDefault().getName(), &isChoiceFormat
,
3931 pluralCountChar
.data(), &len
, &ec
);
3932 affix
+= UnicodeString(s
, len
);
3933 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3935 affix
.append(currencyUChars
, -1);
3936 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3939 UBool isChoiceFormat
;
3940 // If fSymbols is NULL, use default locale
3941 const UChar
* s
= ucurr_getName(currencyUChars
,
3942 fSymbols
!= NULL
? fSymbols
->getLocale().getName() : Locale::getDefault().getName(),
3943 UCURR_SYMBOL_NAME
, &isChoiceFormat
, &len
, &ec
);
3944 if (isChoiceFormat
) {
3945 // Two modes here: If doFormat is false, we set up
3946 // currencyChoice. If doFormat is true, we use the
3947 // previously created currencyChoice to format the
3948 // value in digitList.
3950 // If the currency is handled by a ChoiceFormat,
3951 // then we're not going to use the expanded
3952 // patterns. Instantiate the ChoiceFormat and
3954 if (fCurrencyChoice
== NULL
) {
3955 // TODO Replace double-check with proper thread-safe code
3956 ChoiceFormat
* fmt
= new ChoiceFormat(UnicodeString(s
), ec
);
3957 if (U_SUCCESS(ec
)) {
3959 if (fCurrencyChoice
== NULL
) {
3961 ((DecimalFormat
*)this)->fCurrencyChoice
= fmt
;
3968 // We could almost return null or "" here, since the
3969 // expanded affixes are almost not used at all
3970 // in this situation. However, one method --
3971 // toPattern() -- still does use the expanded
3972 // affixes, in order to set up a padding
3973 // pattern. We use the CURRENCY_SIGN as a
3975 affix
.append(kCurrencySign
);
3977 if (fCurrencyChoice
!= NULL
) {
3978 FieldPosition
pos(0); // ignored
3982 fCurrencyChoice
->format(number
, affix
, pos
);
3984 // We only arrive here if the currency choice
3985 // format in the locale data is INVALID.
3986 affix
.append(currencyUChars
, -1);
3987 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3992 affix
+= UnicodeString(s
, len
);
3993 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
3997 affix
+= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3999 affix
+= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
4001 handler
.addAttribute(kCurrencyField
, beginIdx
, affix
.length());
4005 case kPatternPercent
:
4006 affix
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
4007 handler
.addAttribute(kPercentField
, beginIdx
, affix
.length());
4009 case kPatternPerMill
:
4010 affix
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
4011 handler
.addAttribute(kPermillField
, beginIdx
, affix
.length());
4014 affix
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
4015 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
4018 affix
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
4019 handler
.addAttribute(kSignField
, beginIdx
, affix
.length());
4033 * Append an affix to the given StringBuffer.
4034 * @param buf buffer to append to
4038 int32_t DecimalFormat::appendAffix(UnicodeString
& buf
, double number
,
4039 FieldPositionHandler
& handler
,
4040 UBool isNegative
, UBool isPrefix
) const {
4041 // plural format precedes choice format
4042 if (fCurrencyChoice
!= 0 &&
4043 fCurrencySignCount
!= fgCurrencySignCountInPluralFormat
) {
4044 const UnicodeString
* affixPat
;
4046 affixPat
= isNegative
? fNegPrefixPattern
: fPosPrefixPattern
;
4048 affixPat
= isNegative
? fNegSuffixPattern
: fPosSuffixPattern
;
4051 UnicodeString affixBuf
;
4052 expandAffix(*affixPat
, affixBuf
, number
, handler
, TRUE
, NULL
);
4053 buf
.append(affixBuf
);
4054 return affixBuf
.length();
4056 // else someone called a function that reset the pattern.
4059 const UnicodeString
* affix
;
4060 if (fCurrencySignCount
== fgCurrencySignCountInPluralFormat
) {
4061 UnicodeString pluralCount
= fCurrencyPluralInfo
->getPluralRules()->select(number
);
4062 AffixesForCurrency
* oneSet
;
4063 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
4064 oneSet
= (AffixesForCurrency
*)fPluralAffixesForCurrency
->get(pluralCount
);
4066 oneSet
= (AffixesForCurrency
*)fAffixesForCurrency
->get(pluralCount
);
4069 affix
= isNegative
? &oneSet
->negPrefixForCurrency
:
4070 &oneSet
->posPrefixForCurrency
;
4072 affix
= isNegative
? &oneSet
->negSuffixForCurrency
:
4073 &oneSet
->posSuffixForCurrency
;
4077 affix
= isNegative
? &fNegativePrefix
: &fPositivePrefix
;
4079 affix
= isNegative
? &fNegativeSuffix
: &fPositiveSuffix
;
4083 int32_t begin
= (int) buf
.length();
4087 if (handler
.isRecording()) {
4088 int32_t offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
));
4090 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kCurrencySymbol
);
4091 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4094 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
4096 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
4097 handler
.addAttribute(kCurrencyField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4100 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
4102 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
4103 handler
.addAttribute(kSignField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4106 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
4108 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
4109 handler
.addAttribute(kPercentField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4112 offset
= (int) (*affix
).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
4114 UnicodeString aff
= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
4115 handler
.addAttribute(kPermillField
, begin
+ offset
, begin
+ offset
+ aff
.length());
4118 return affix
->length();
4122 * Appends an affix pattern to the given StringBuffer, quoting special
4123 * characters as needed. Uses the internal affix pattern, if that exists,
4124 * or the literal affix, if the internal affix pattern is null. The
4125 * appended string will generate the same affix pattern (or literal affix)
4126 * when passed to toPattern().
4128 * @param appendTo the affix string is appended to this
4129 * @param affixPattern a pattern such as fPosPrefixPattern; may be null
4130 * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
4131 * Ignored unless affixPattern is null. If affixPattern is null, then
4132 * expAffix is appended as a literal affix.
4133 * @param localized true if the appended pattern should contain localized
4134 * pattern characters; otherwise, non-localized pattern chars are appended
4136 void DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
4137 const UnicodeString
* affixPattern
,
4138 const UnicodeString
& expAffix
,
4139 UBool localized
) const {
4140 if (affixPattern
== 0) {
4141 appendAffixPattern(appendTo
, expAffix
, localized
);
4144 for (int pos
=0; pos
<affixPattern
->length(); pos
=i
) {
4145 i
= affixPattern
->indexOf(kQuote
, pos
);
4148 affixPattern
->extractBetween(pos
, affixPattern
->length(), s
);
4149 appendAffixPattern(appendTo
, s
, localized
);
4154 affixPattern
->extractBetween(pos
, i
, s
);
4155 appendAffixPattern(appendTo
, s
, localized
);
4157 UChar32 c
= affixPattern
->char32At(++i
);
4160 appendTo
.append(c
).append(c
);
4161 // Fall through and append another kQuote below
4162 } else if (c
== kCurrencySign
&&
4163 i
<affixPattern
->length() &&
4164 affixPattern
->char32At(i
) == kCurrencySign
) {
4166 appendTo
.append(c
).append(c
);
4167 } else if (localized
) {
4169 case kPatternPercent
:
4170 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
4172 case kPatternPerMill
:
4173 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
4176 appendTo
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
4179 appendTo
+= getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
4192 * Append an affix to the given StringBuffer, using quotes if
4193 * there are special characters. Single quotes themselves must be
4194 * escaped in either case.
4197 DecimalFormat::appendAffixPattern(UnicodeString
& appendTo
,
4198 const UnicodeString
& affix
,
4199 UBool localized
) const {
4202 needQuote
= affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
)) >= 0
4203 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
)) >= 0
4204 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
)) >= 0
4205 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
)) >= 0
4206 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
)) >= 0
4207 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
)) >= 0
4208 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
)) >= 0
4209 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
)) >= 0
4210 || affix
.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) >= 0
4211 || affix
.indexOf(kCurrencySign
) >= 0;
4214 needQuote
= affix
.indexOf(kPatternZeroDigit
) >= 0
4215 || affix
.indexOf(kPatternGroupingSeparator
) >= 0
4216 || affix
.indexOf(kPatternDecimalSeparator
) >= 0
4217 || affix
.indexOf(kPatternPercent
) >= 0
4218 || affix
.indexOf(kPatternPerMill
) >= 0
4219 || affix
.indexOf(kPatternDigit
) >= 0
4220 || affix
.indexOf(kPatternSeparator
) >= 0
4221 || affix
.indexOf(kPatternExponent
) >= 0
4222 || affix
.indexOf(kPatternPlus
) >= 0
4223 || affix
.indexOf(kPatternMinus
) >= 0
4224 || affix
.indexOf(kCurrencySign
) >= 0;
4227 appendTo
+= (UChar
)0x0027 /*'\''*/;
4228 if (affix
.indexOf((UChar
)0x0027 /*'\''*/) < 0)
4231 for (int32_t j
= 0; j
< affix
.length(); ) {
4232 UChar32 c
= affix
.char32At(j
);
4235 if (c
== 0x0027 /*'\''*/)
4240 appendTo
+= (UChar
)0x0027 /*'\''*/;
4243 //------------------------------------------------------------------------------
4246 DecimalFormat::toPattern(UnicodeString
& result
, UBool localized
) const
4248 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
4249 // the prefix or suffix pattern might not be defined yet,
4250 // so they can not be synthesized,
4251 // instead, get them directly.
4252 // but it might not be the actual pattern used in formatting.
4253 // the actual pattern used in formatting depends on the
4254 // formatted number's plural count.
4255 result
= fFormatPattern
;
4259 UChar32 zero
, sigDigit
= kPatternSignificantDigit
;
4260 UnicodeString digit
, group
;
4262 int32_t roundingDecimalPos
= 0; // Pos of decimal in roundingDigits
4263 UnicodeString roundingDigits
;
4264 int32_t padPos
= (fFormatWidth
> 0) ? fPadPosition
: -1;
4265 UnicodeString padSpec
;
4266 UBool useSigDig
= areSignificantDigitsUsed();
4269 digit
.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
4270 group
.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
4271 zero
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
4273 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
4277 digit
.append((UChar
)kPatternDigit
);
4278 group
.append((UChar
)kPatternGroupingSeparator
);
4279 zero
= (UChar32
)kPatternZeroDigit
;
4281 if (fFormatWidth
> 0) {
4283 padSpec
.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
4286 padSpec
.append((UChar
)kPatternPadEscape
);
4288 padSpec
.append(fPad
);
4290 if (fRoundingIncrement
!= NULL
) {
4291 for(i
=0; i
<fRoundingIncrement
->getCount(); ++i
) {
4292 roundingDigits
.append(zero
+(fRoundingIncrement
->getDigitValue(i
))); // Convert to Unicode digit
4294 roundingDecimalPos
= fRoundingIncrement
->getDecimalAt();
4296 for (int32_t part
=0; part
<2; ++part
) {
4297 if (padPos
== kPadBeforePrefix
) {
4298 result
.append(padSpec
);
4300 appendAffixPattern(result
,
4301 (part
==0 ? fPosPrefixPattern
: fNegPrefixPattern
),
4302 (part
==0 ? fPositivePrefix
: fNegativePrefix
),
4304 if (padPos
== kPadAfterPrefix
&& ! padSpec
.isEmpty()) {
4305 result
.append(padSpec
);
4307 int32_t sub0Start
= result
.length();
4308 int32_t g
= isGroupingUsed() ? _max(0, fGroupingSize
) : 0;
4309 if (g
> 0 && fGroupingSize2
> 0 && fGroupingSize2
!= fGroupingSize
) {
4310 g
+= fGroupingSize2
;
4312 int32_t maxDig
= 0, minDig
= 0, maxSigDig
= 0;
4314 minDig
= getMinimumSignificantDigits();
4315 maxDig
= maxSigDig
= getMaximumSignificantDigits();
4317 minDig
= getMinimumIntegerDigits();
4318 maxDig
= getMaximumIntegerDigits();
4320 if (fUseExponentialNotation
) {
4321 if (maxDig
> kMaxScientificIntegerDigits
) {
4324 } else if (useSigDig
) {
4325 maxDig
= _max(maxDig
, g
+1);
4327 maxDig
= _max(_max(g
, getMinimumIntegerDigits()),
4328 roundingDecimalPos
) + 1;
4330 for (i
= maxDig
; i
> 0; --i
) {
4331 if (!fUseExponentialNotation
&& i
<maxDig
&&
4332 isGroupingPosition(i
)) {
4333 result
.append(group
);
4336 // #@,@### (maxSigDig == 5, minSigDig == 2)
4337 // 65 4321 (1-based pos, count from the right)
4338 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
4339 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
4340 if (maxSigDig
>= i
&& i
> (maxSigDig
- minDig
)) {
4341 result
.append(sigDigit
);
4343 result
.append(digit
);
4346 if (! roundingDigits
.isEmpty()) {
4347 int32_t pos
= roundingDecimalPos
- i
;
4348 if (pos
>= 0 && pos
< roundingDigits
.length()) {
4349 result
.append((UChar
) (roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
4354 result
.append(zero
);
4356 result
.append(digit
);
4361 if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown
) {
4363 result
+= getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
4366 result
.append((UChar
)kPatternDecimalSeparator
);
4369 int32_t pos
= roundingDecimalPos
;
4370 for (i
= 0; i
< getMaximumFractionDigits(); ++i
) {
4371 if (! roundingDigits
.isEmpty() && pos
< roundingDigits
.length()) {
4373 result
.append(zero
);
4376 result
.append((UChar
)(roundingDigits
.char32At(pos
) - kPatternZeroDigit
+ zero
));
4381 if (i
<getMinimumFractionDigits()) {
4382 result
.append(zero
);
4385 result
.append(digit
);
4389 if (fUseExponentialNotation
) {
4391 result
+= getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
4394 result
.append((UChar
)kPatternExponent
);
4396 if (fExponentSignAlwaysShown
) {
4398 result
+= getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
4401 result
.append((UChar
)kPatternPlus
);
4404 for (i
=0; i
<fMinExponentDigits
; ++i
) {
4405 result
.append(zero
);
4408 if (! padSpec
.isEmpty() && !fUseExponentialNotation
) {
4409 int32_t add
= fFormatWidth
- result
.length() + sub0Start
4411 ? fPositivePrefix
.length() + fPositiveSuffix
.length()
4412 : fNegativePrefix
.length() + fNegativeSuffix
.length());
4414 result
.insert(sub0Start
, digit
);
4417 // Only add a grouping separator if we have at least
4418 // 2 additional characters to be added, so we don't
4419 // end up with ",###".
4420 if (add
>1 && isGroupingPosition(maxDig
)) {
4421 result
.insert(sub0Start
, group
);
4426 if (fPadPosition
== kPadBeforeSuffix
&& ! padSpec
.isEmpty()) {
4427 result
.append(padSpec
);
4430 appendAffixPattern(result
, fPosSuffixPattern
, fPositiveSuffix
, localized
);
4431 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
4432 result
.append(padSpec
);
4434 UBool isDefault
= FALSE
;
4435 if ((fNegSuffixPattern
== fPosSuffixPattern
&& // both null
4436 fNegativeSuffix
== fPositiveSuffix
)
4437 || (fNegSuffixPattern
!= 0 && fPosSuffixPattern
!= 0 &&
4438 *fNegSuffixPattern
== *fPosSuffixPattern
))
4440 if (fNegPrefixPattern
!= NULL
&& fPosPrefixPattern
!= NULL
)
4442 int32_t length
= fPosPrefixPattern
->length();
4443 isDefault
= fNegPrefixPattern
->length() == (length
+2) &&
4444 (*fNegPrefixPattern
)[(int32_t)0] == kQuote
&&
4445 (*fNegPrefixPattern
)[(int32_t)1] == kPatternMinus
&&
4446 fNegPrefixPattern
->compare(2, length
, *fPosPrefixPattern
, 0, length
) == 0;
4449 fNegPrefixPattern
== NULL
&& fPosPrefixPattern
== NULL
)
4451 int32_t length
= fPositivePrefix
.length();
4452 isDefault
= fNegativePrefix
.length() == (length
+1) &&
4453 fNegativePrefix
.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
)) == 0 &&
4454 fNegativePrefix
.compare(1, length
, fPositivePrefix
, 0, length
) == 0;
4458 break; // Don't output default negative subpattern
4461 result
+= getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
);
4464 result
.append((UChar
)kPatternSeparator
);
4468 appendAffixPattern(result
, fNegSuffixPattern
, fNegativeSuffix
, localized
);
4469 if (fPadPosition
== kPadAfterSuffix
&& ! padSpec
.isEmpty()) {
4470 result
.append(padSpec
);
4478 //------------------------------------------------------------------------------
4481 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
4483 UParseError parseError
;
4484 applyPattern(pattern
, FALSE
, parseError
, status
);
4487 //------------------------------------------------------------------------------
4490 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
4491 UParseError
& parseError
,
4494 applyPattern(pattern
, FALSE
, parseError
, status
);
4496 //------------------------------------------------------------------------------
4499 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
4501 UParseError parseError
;
4502 applyPattern(pattern
, TRUE
,parseError
,status
);
4505 //------------------------------------------------------------------------------
4508 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
4509 UParseError
& parseError
,
4512 applyPattern(pattern
, TRUE
,parseError
,status
);
4515 //------------------------------------------------------------------------------
4518 DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString
& pattern
,
4520 UParseError
& parseError
,
4523 if (U_FAILURE(status
))
4527 // Clear error struct
4528 parseError
.offset
= -1;
4529 parseError
.preContext
[0] = parseError
.postContext
[0] = (UChar
)0;
4531 // Set the significant pattern symbols
4532 UChar32 zeroDigit
= kPatternZeroDigit
; // '0'
4533 UChar32 sigDigit
= kPatternSignificantDigit
; // '@'
4534 UnicodeString
groupingSeparator ((UChar
)kPatternGroupingSeparator
);
4535 UnicodeString
decimalSeparator ((UChar
)kPatternDecimalSeparator
);
4536 UnicodeString
percent ((UChar
)kPatternPercent
);
4537 UnicodeString
perMill ((UChar
)kPatternPerMill
);
4538 UnicodeString
digit ((UChar
)kPatternDigit
); // '#'
4539 UnicodeString
separator ((UChar
)kPatternSeparator
);
4540 UnicodeString
exponent ((UChar
)kPatternExponent
);
4541 UnicodeString
plus ((UChar
)kPatternPlus
);
4542 UnicodeString
minus ((UChar
)kPatternMinus
);
4543 UnicodeString
padEscape ((UChar
)kPatternPadEscape
);
4544 // Substitute with the localized symbols if necessary
4546 zeroDigit
= getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
4547 sigDigit
= getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol
).char32At(0);
4548 groupingSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
));
4549 decimalSeparator
. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
));
4550 percent
. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol
));
4551 perMill
. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
));
4552 digit
. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol
));
4553 separator
. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol
));
4554 exponent
. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
));
4555 plus
. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
));
4556 minus
. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
));
4557 padEscape
. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol
));
4559 UChar nineDigit
= (UChar
)(zeroDigit
+ 9);
4560 int32_t digitLen
= digit
.length();
4561 int32_t groupSepLen
= groupingSeparator
.length();
4562 int32_t decimalSepLen
= decimalSeparator
.length();
4565 int32_t patLen
= pattern
.length();
4566 // Part 0 is the positive pattern. Part 1, if present, is the negative
4568 for (int32_t part
=0; part
<2 && pos
<patLen
; ++part
) {
4569 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
4570 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
4571 // between the prefix and suffix, and consists of pattern
4572 // characters. In the prefix and suffix, percent, perMill, and
4573 // currency symbols are recognized and translated.
4574 int32_t subpart
= 1, sub0Start
= 0, sub0Limit
= 0, sub2Limit
= 0;
4576 // It's important that we don't change any fields of this object
4577 // prematurely. We set the following variables for the multiplier,
4578 // grouping, etc., and then only change the actual object fields if
4579 // everything parses correctly. This also lets us register
4580 // the data from part 0 and ignore the part 1, except for the
4581 // prefix and suffix.
4582 UnicodeString prefix
;
4583 UnicodeString suffix
;
4584 int32_t decimalPos
= -1;
4585 int32_t multiplier
= 1;
4586 int32_t digitLeftCount
= 0, zeroDigitCount
= 0, digitRightCount
= 0, sigDigitCount
= 0;
4587 int8_t groupingCount
= -1;
4588 int8_t groupingCount2
= -1;
4589 int32_t padPos
= -1;
4590 UChar32 padChar
= 0;
4591 int32_t roundingPos
= -1;
4592 DigitList roundingInc
;
4593 int8_t expDigits
= -1;
4594 UBool expSignAlways
= FALSE
;
4596 // The affix is either the prefix or the suffix.
4597 UnicodeString
* affix
= &prefix
;
4599 int32_t start
= pos
;
4600 UBool isPartDone
= FALSE
;
4603 for (; !isPartDone
&& pos
< patLen
; ) {
4604 // Todo: account for surrogate pairs
4605 ch
= pattern
.char32At(pos
);
4607 case 0: // Pattern proper subpart (between prefix & suffix)
4608 // Process the digits, decimal, and grouping characters. We
4609 // record five pieces of information. We expect the digits
4610 // to occur in the pattern ####00.00####, and we record the
4611 // number of left digits, zero (central) digits, and right
4612 // digits. The position of the last grouping character is
4613 // recorded (should be somewhere within the first two blocks
4614 // of characters), as is the position of the decimal point,
4615 // if any (should be in the zero digits). If there is no
4616 // decimal point, then there should be no right digits.
4617 if (pattern
.compare(pos
, digitLen
, digit
) == 0) {
4618 if (zeroDigitCount
> 0 || sigDigitCount
> 0) {
4623 if (groupingCount
>= 0 && decimalPos
< 0) {
4627 } else if ((ch
>= zeroDigit
&& ch
<= nineDigit
) ||
4629 if (digitRightCount
> 0) {
4631 debug("Unexpected '0'")
4632 status
= U_UNEXPECTED_TOKEN
;
4633 syntaxError(pattern
,pos
,parseError
);
4636 if (ch
== sigDigit
) {
4639 if (ch
!= zeroDigit
&& roundingPos
< 0) {
4640 roundingPos
= digitLeftCount
+ zeroDigitCount
;
4642 if (roundingPos
>= 0) {
4643 roundingInc
.append((char)(ch
- zeroDigit
+ '0'));
4647 if (groupingCount
>= 0 && decimalPos
< 0) {
4650 pos
+= U16_LENGTH(ch
);
4651 } else if (pattern
.compare(pos
, groupSepLen
, groupingSeparator
) == 0) {
4652 if (decimalPos
>= 0) {
4653 // Grouping separator after decimal
4654 debug("Grouping separator after decimal")
4655 status
= U_UNEXPECTED_TOKEN
;
4656 syntaxError(pattern
,pos
,parseError
);
4659 groupingCount2
= groupingCount
;
4662 } else if (pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) == 0) {
4663 if (decimalPos
>= 0) {
4664 // Multiple decimal separators
4665 debug("Multiple decimal separators")
4666 status
= U_MULTIPLE_DECIMAL_SEPARATORS
;
4667 syntaxError(pattern
,pos
,parseError
);
4670 // Intentionally incorporate the digitRightCount,
4671 // even though it is illegal for this to be > 0
4672 // at this point. We check pattern syntax below.
4673 decimalPos
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
4674 pos
+= decimalSepLen
;
4676 if (pattern
.compare(pos
, exponent
.length(), exponent
) == 0) {
4677 if (expDigits
>= 0) {
4678 // Multiple exponential symbols
4679 debug("Multiple exponential symbols")
4680 status
= U_MULTIPLE_EXPONENTIAL_SYMBOLS
;
4681 syntaxError(pattern
,pos
,parseError
);
4684 if (groupingCount
>= 0) {
4685 // Grouping separator in exponential pattern
4686 debug("Grouping separator in exponential pattern")
4687 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
4688 syntaxError(pattern
,pos
,parseError
);
4691 pos
+= exponent
.length();
4692 // Check for positive prefix
4694 && pattern
.compare(pos
, plus
.length(), plus
) == 0) {
4695 expSignAlways
= TRUE
;
4696 pos
+= plus
.length();
4698 // Use lookahead to parse out the exponential part of the
4699 // pattern, then jump into suffix subpart.
4701 while (pos
< patLen
&&
4702 pattern
.char32At(pos
) == zeroDigit
) {
4704 pos
+= U16_LENGTH(zeroDigit
);
4707 // 1. Require at least one mantissa pattern digit
4708 // 2. Disallow "#+ @" in mantissa
4709 // 3. Require at least one exponent pattern digit
4710 if (((digitLeftCount
+ zeroDigitCount
) < 1 &&
4711 (sigDigitCount
+ digitRightCount
) < 1) ||
4712 (sigDigitCount
> 0 && digitLeftCount
> 0) ||
4714 // Malformed exponential pattern
4715 debug("Malformed exponential pattern")
4716 status
= U_MALFORMED_EXPONENTIAL_PATTERN
;
4717 syntaxError(pattern
,pos
,parseError
);
4721 // Transition to suffix subpart
4722 subpart
= 2; // suffix subpart
4728 case 1: // Prefix subpart
4729 case 2: // Suffix subpart
4730 // Process the prefix / suffix characters
4731 // Process unquoted characters seen in prefix or suffix
4734 // Several syntax characters implicitly begins the
4735 // next subpart if we are in the prefix; otherwise
4736 // they are illegal if unquoted.
4737 if (!pattern
.compare(pos
, digitLen
, digit
) ||
4738 !pattern
.compare(pos
, groupSepLen
, groupingSeparator
) ||
4739 !pattern
.compare(pos
, decimalSepLen
, decimalSeparator
) ||
4740 (ch
>= zeroDigit
&& ch
<= nineDigit
) ||
4742 if (subpart
== 1) { // prefix subpart
4743 subpart
= 0; // pattern proper subpart
4744 sub0Start
= pos
; // Reprocess this character
4747 status
= U_UNQUOTED_SPECIAL
;
4748 syntaxError(pattern
,pos
,parseError
);
4751 } else if (ch
== kCurrencySign
) {
4752 affix
->append(kQuote
); // Encode currency
4753 // Use lookahead to determine if the currency sign is
4755 U_ASSERT(U16_LENGTH(kCurrencySign
) == 1);
4756 if ((pos
+1) < pattern
.length() && pattern
[pos
+1] == kCurrencySign
) {
4757 affix
->append(kCurrencySign
);
4758 ++pos
; // Skip over the doubled character
4759 if ((pos
+1) < pattern
.length() &&
4760 pattern
[pos
+1] == kCurrencySign
) {
4761 affix
->append(kCurrencySign
);
4762 ++pos
; // Skip over the doubled character
4763 fCurrencySignCount
= fgCurrencySignCountInPluralFormat
;
4765 fCurrencySignCount
= fgCurrencySignCountInISOFormat
;
4768 fCurrencySignCount
= fgCurrencySignCountInSymbolFormat
;
4770 // Fall through to append(ch)
4771 } else if (ch
== kQuote
) {
4772 // A quote outside quotes indicates either the opening
4773 // quote or two quotes, which is a quote literal. That is,
4774 // we have the first quote in 'do' or o''clock.
4775 U_ASSERT(U16_LENGTH(kQuote
) == 1);
4777 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
4778 affix
->append(kQuote
); // Encode quote
4779 // Fall through to append(ch)
4781 subpart
+= 2; // open quote
4784 } else if (pattern
.compare(pos
, separator
.length(), separator
) == 0) {
4785 // Don't allow separators in the prefix, and don't allow
4786 // separators in the second pattern (part == 1).
4787 if (subpart
== 1 || part
== 1) {
4788 // Unexpected separator
4789 debug("Unexpected separator")
4790 status
= U_UNEXPECTED_TOKEN
;
4791 syntaxError(pattern
,pos
,parseError
);
4795 isPartDone
= TRUE
; // Go to next part
4796 pos
+= separator
.length();
4798 } else if (pattern
.compare(pos
, percent
.length(), percent
) == 0) {
4799 // Next handle characters which are appended directly.
4800 if (multiplier
!= 1) {
4801 // Too many percent/perMill characters
4802 debug("Too many percent characters")
4803 status
= U_MULTIPLE_PERCENT_SYMBOLS
;
4804 syntaxError(pattern
,pos
,parseError
);
4807 affix
->append(kQuote
); // Encode percent/perMill
4808 affix
->append(kPatternPercent
); // Use unlocalized pattern char
4810 pos
+= percent
.length();
4812 } else if (pattern
.compare(pos
, perMill
.length(), perMill
) == 0) {
4813 // Next handle characters which are appended directly.
4814 if (multiplier
!= 1) {
4815 // Too many percent/perMill characters
4816 debug("Too many perMill characters")
4817 status
= U_MULTIPLE_PERMILL_SYMBOLS
;
4818 syntaxError(pattern
,pos
,parseError
);
4821 affix
->append(kQuote
); // Encode percent/perMill
4822 affix
->append(kPatternPerMill
); // Use unlocalized pattern char
4824 pos
+= perMill
.length();
4826 } else if (pattern
.compare(pos
, padEscape
.length(), padEscape
) == 0) {
4827 if (padPos
>= 0 || // Multiple pad specifiers
4828 (pos
+1) == pattern
.length()) { // Nothing after padEscape
4829 debug("Multiple pad specifiers")
4830 status
= U_MULTIPLE_PAD_SPECIFIERS
;
4831 syntaxError(pattern
,pos
,parseError
);
4835 pos
+= padEscape
.length();
4836 padChar
= pattern
.char32At(pos
);
4837 pos
+= U16_LENGTH(padChar
);
4839 } else if (pattern
.compare(pos
, minus
.length(), minus
) == 0) {
4840 affix
->append(kQuote
); // Encode minus
4841 affix
->append(kPatternMinus
);
4842 pos
+= minus
.length();
4844 } else if (pattern
.compare(pos
, plus
.length(), plus
) == 0) {
4845 affix
->append(kQuote
); // Encode plus
4846 affix
->append(kPatternPlus
);
4847 pos
+= plus
.length();
4850 // Unquoted, non-special characters fall through to here, as
4851 // well as other code which needs to append something to the
4854 pos
+= U16_LENGTH(ch
);
4856 case 3: // Prefix subpart, in quote
4857 case 4: // Suffix subpart, in quote
4858 // A quote within quotes indicates either the closing
4859 // quote or two quotes, which is a quote literal. That is,
4860 // we have the second quote in 'do' or 'don''t'.
4863 if (pos
< pattern
.length() && pattern
[pos
] == kQuote
) {
4864 affix
->append(kQuote
); // Encode quote
4865 // Fall through to append(ch)
4867 subpart
-= 2; // close quote
4872 pos
+= U16_LENGTH(ch
);
4877 if (sub0Limit
== 0) {
4878 sub0Limit
= pattern
.length();
4881 if (sub2Limit
== 0) {
4882 sub2Limit
= pattern
.length();
4885 /* Handle patterns with no '0' pattern character. These patterns
4886 * are legal, but must be recodified to make sense. "##.###" ->
4887 * "#0.###". ".###" -> ".0##".
4889 * We allow patterns of the form "####" to produce a zeroDigitCount
4890 * of zero (got that?); although this seems like it might make it
4891 * possible for format() to produce empty strings, format() checks
4892 * for this condition and outputs a zero digit in this situation.
4893 * Having a zeroDigitCount of zero yields a minimum integer digits
4894 * of zero, which allows proper round-trip patterns. We don't want
4895 * "#" to become "#0" when toPattern() is called (even though that's
4896 * what it really is, semantically).
4898 if (zeroDigitCount
== 0 && sigDigitCount
== 0 &&
4899 digitLeftCount
> 0 && decimalPos
>= 0) {
4900 // Handle "###.###" and "###." and ".###"
4903 ++n
; // Handle ".###"
4904 digitRightCount
= digitLeftCount
- n
;
4905 digitLeftCount
= n
- 1;
4909 // Do syntax checking on the digits, decimal points, and quotes.
4910 if ((decimalPos
< 0 && digitRightCount
> 0 && sigDigitCount
== 0) ||
4912 (sigDigitCount
> 0 ||
4913 decimalPos
< digitLeftCount
||
4914 decimalPos
> (digitLeftCount
+ zeroDigitCount
))) ||
4915 groupingCount
== 0 || groupingCount2
== 0 ||
4916 (sigDigitCount
> 0 && zeroDigitCount
> 0) ||
4918 { // subpart > 2 == unmatched quote
4919 debug("Syntax error")
4920 status
= U_PATTERN_SYNTAX_ERROR
;
4921 syntaxError(pattern
,pos
,parseError
);
4925 // Make sure pad is at legal position before or after affix.
4927 if (padPos
== start
) {
4928 padPos
= kPadBeforePrefix
;
4929 } else if (padPos
+2 == sub0Start
) {
4930 padPos
= kPadAfterPrefix
;
4931 } else if (padPos
== sub0Limit
) {
4932 padPos
= kPadBeforeSuffix
;
4933 } else if (padPos
+2 == sub2Limit
) {
4934 padPos
= kPadAfterSuffix
;
4936 // Illegal pad position
4937 debug("Illegal pad position")
4938 status
= U_ILLEGAL_PAD_POSITION
;
4939 syntaxError(pattern
,pos
,parseError
);
4945 delete fPosPrefixPattern
;
4946 delete fPosSuffixPattern
;
4947 delete fNegPrefixPattern
;
4948 delete fNegSuffixPattern
;
4949 fPosPrefixPattern
= new UnicodeString(prefix
);
4951 if (fPosPrefixPattern
== 0) {
4952 status
= U_MEMORY_ALLOCATION_ERROR
;
4955 fPosSuffixPattern
= new UnicodeString(suffix
);
4957 if (fPosSuffixPattern
== 0) {
4958 status
= U_MEMORY_ALLOCATION_ERROR
;
4959 delete fPosPrefixPattern
;
4962 fNegPrefixPattern
= 0;
4963 fNegSuffixPattern
= 0;
4965 fUseExponentialNotation
= (expDigits
>= 0);
4966 if (fUseExponentialNotation
) {
4967 fMinExponentDigits
= expDigits
;
4969 fExponentSignAlwaysShown
= expSignAlways
;
4970 int32_t digitTotalCount
= digitLeftCount
+ zeroDigitCount
+ digitRightCount
;
4971 // The effectiveDecimalPos is the position the decimal is at or
4972 // would be at if there is no decimal. Note that if
4973 // decimalPos<0, then digitTotalCount == digitLeftCount +
4975 int32_t effectiveDecimalPos
= decimalPos
>= 0 ? decimalPos
: digitTotalCount
;
4976 UBool isSigDig
= (sigDigitCount
> 0);
4977 setSignificantDigitsUsed(isSigDig
);
4979 setMinimumSignificantDigits(sigDigitCount
);
4980 setMaximumSignificantDigits(sigDigitCount
+ digitRightCount
);
4982 int32_t minInt
= effectiveDecimalPos
- digitLeftCount
;
4983 setMinimumIntegerDigits(minInt
);
4984 setMaximumIntegerDigits(fUseExponentialNotation
4985 ? digitLeftCount
+ getMinimumIntegerDigits()
4986 : kDoubleIntegerDigits
);
4987 setMaximumFractionDigits(decimalPos
>= 0
4988 ? (digitTotalCount
- decimalPos
) : 0);
4989 setMinimumFractionDigits(decimalPos
>= 0
4990 ? (digitLeftCount
+ zeroDigitCount
- decimalPos
) : 0);
4992 setGroupingUsed(groupingCount
> 0);
4993 fGroupingSize
= (groupingCount
> 0) ? groupingCount
: 0;
4994 fGroupingSize2
= (groupingCount2
> 0 && groupingCount2
!= groupingCount
)
4995 ? groupingCount2
: 0;
4996 setMultiplier(multiplier
);
4997 setDecimalSeparatorAlwaysShown(decimalPos
== 0
4998 || decimalPos
== digitTotalCount
);
5000 fPadPosition
= (EPadPosition
) padPos
;
5001 // To compute the format width, first set up sub0Limit -
5002 // sub0Start. Add in prefix/suffix length later.
5004 // fFormatWidth = prefix.length() + suffix.length() +
5005 // sub0Limit - sub0Start;
5006 fFormatWidth
= sub0Limit
- sub0Start
;
5011 if (roundingPos
>= 0) {
5012 roundingInc
.setDecimalAt(effectiveDecimalPos
- roundingPos
);
5013 if (fRoundingIncrement
!= NULL
) {
5014 *fRoundingIncrement
= roundingInc
;
5016 fRoundingIncrement
= new DigitList(roundingInc
);
5018 if (fRoundingIncrement
== NULL
) {
5019 status
= U_MEMORY_ALLOCATION_ERROR
;
5020 delete fPosPrefixPattern
;
5021 delete fPosSuffixPattern
;
5025 fRoundingMode
= kRoundHalfEven
;
5027 setRoundingIncrement(0.0);
5030 fNegPrefixPattern
= new UnicodeString(prefix
);
5032 if (fNegPrefixPattern
== 0) {
5033 status
= U_MEMORY_ALLOCATION_ERROR
;
5036 fNegSuffixPattern
= new UnicodeString(suffix
);
5038 if (fNegSuffixPattern
== 0) {
5039 delete fNegPrefixPattern
;
5040 status
= U_MEMORY_ALLOCATION_ERROR
;
5046 if (pattern
.length() == 0) {
5047 delete fNegPrefixPattern
;
5048 delete fNegSuffixPattern
;
5049 fNegPrefixPattern
= NULL
;
5050 fNegSuffixPattern
= NULL
;
5051 if (fPosPrefixPattern
!= NULL
) {
5052 fPosPrefixPattern
->remove();
5054 fPosPrefixPattern
= new UnicodeString();
5056 if (fPosPrefixPattern
== 0) {
5057 status
= U_MEMORY_ALLOCATION_ERROR
;
5061 if (fPosSuffixPattern
!= NULL
) {
5062 fPosSuffixPattern
->remove();
5064 fPosSuffixPattern
= new UnicodeString();
5066 if (fPosSuffixPattern
== 0) {
5067 delete fPosPrefixPattern
;
5068 status
= U_MEMORY_ALLOCATION_ERROR
;
5073 setMinimumIntegerDigits(0);
5074 setMaximumIntegerDigits(kDoubleIntegerDigits
);
5075 setMinimumFractionDigits(0);
5076 setMaximumFractionDigits(kDoubleFractionDigits
);
5078 fUseExponentialNotation
= FALSE
;
5079 fCurrencySignCount
= 0;
5080 setGroupingUsed(FALSE
);
5084 setDecimalSeparatorAlwaysShown(FALSE
);
5086 setRoundingIncrement(0.0);
5089 // If there was no negative pattern, or if the negative pattern is
5090 // identical to the positive pattern, then prepend the minus sign to the
5091 // positive pattern to form the negative pattern.
5092 if (fNegPrefixPattern
== NULL
||
5093 (*fNegPrefixPattern
== *fPosPrefixPattern
5094 && *fNegSuffixPattern
== *fPosSuffixPattern
)) {
5095 _copy_ptr(&fNegSuffixPattern
, fPosSuffixPattern
);
5096 if (fNegPrefixPattern
== NULL
) {
5097 fNegPrefixPattern
= new UnicodeString();
5099 if (fNegPrefixPattern
== 0) {
5100 status
= U_MEMORY_ALLOCATION_ERROR
;
5104 fNegPrefixPattern
->remove();
5106 fNegPrefixPattern
->append(kQuote
).append(kPatternMinus
)
5107 .append(*fPosPrefixPattern
);
5111 s
.append((UnicodeString
)"\"").append(pattern
).append((UnicodeString
)"\"->");
5116 fFormatPattern
= pattern
;
5121 DecimalFormat::expandAffixAdjustWidth(const UnicodeString
* pluralCount
) {
5122 expandAffixes(pluralCount
);
5123 if (fFormatWidth
> 0) {
5124 // Finish computing format width (see above)
5125 // TODO: how to handle fFormatWidth,
5126 // need to save in f(Plural)AffixesForCurrecy?
5127 fFormatWidth
+= fPositivePrefix
.length() + fPositiveSuffix
.length();
5133 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
5135 UParseError
& parseError
,
5138 // do the following re-set first. since they change private data by
5139 // apply pattern again.
5140 if (pattern
.indexOf(kCurrencySign
) != -1) {
5141 if (fCurrencyPluralInfo
== NULL
) {
5142 // initialize currencyPluralInfo if needed
5143 fCurrencyPluralInfo
= new CurrencyPluralInfo(fSymbols
->getLocale(), status
);
5145 if (fAffixPatternsForCurrency
== NULL
) {
5146 setupCurrencyAffixPatterns(status
);
5148 if (pattern
.indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
5149 // only setup the affixes of the current pattern.
5150 setupCurrencyAffixes(pattern
, TRUE
, FALSE
, status
);
5153 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
5154 expandAffixAdjustWidth(NULL
);
5155 #if UCONFIG_FORMAT_FASTPATHS_49
5162 DecimalFormat::applyPatternInternally(const UnicodeString
& pluralCount
,
5163 const UnicodeString
& pattern
,
5165 UParseError
& parseError
,
5166 UErrorCode
& status
) {
5167 applyPatternWithoutExpandAffix(pattern
, localized
, parseError
, status
);
5168 expandAffixAdjustWidth(&pluralCount
);
5169 #if UCONFIG_FORMAT_FASTPATHS_49
5176 * Sets the maximum number of digits allowed in the integer portion of a
5177 * number. This override limits the integer digit count to 309.
5178 * @see NumberFormat#setMaximumIntegerDigits
5180 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
5181 NumberFormat::setMaximumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
5182 #if UCONFIG_FORMAT_FASTPATHS_49
5188 * Sets the minimum number of digits allowed in the integer portion of a
5189 * number. This override limits the integer digit count to 309.
5190 * @see NumberFormat#setMinimumIntegerDigits
5192 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
5193 NumberFormat::setMinimumIntegerDigits(_min(newValue
, kDoubleIntegerDigits
));
5194 #if UCONFIG_FORMAT_FASTPATHS_49
5200 * Sets the maximum number of digits allowed in the fraction portion of a
5201 * number. This override limits the fraction digit count to 340.
5202 * @see NumberFormat#setMaximumFractionDigits
5204 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
5205 NumberFormat::setMaximumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
5206 #if UCONFIG_FORMAT_FASTPATHS_49
5212 * Sets the minimum number of digits allowed in the fraction portion of a
5213 * number. This override limits the fraction digit count to 340.
5214 * @see NumberFormat#setMinimumFractionDigits
5216 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
5217 NumberFormat::setMinimumFractionDigits(_min(newValue
, kDoubleFractionDigits
));
5218 #if UCONFIG_FORMAT_FASTPATHS_49
5223 int32_t DecimalFormat::getMinimumSignificantDigits() const {
5224 return fMinSignificantDigits
;
5227 int32_t DecimalFormat::getMaximumSignificantDigits() const {
5228 return fMaxSignificantDigits
;
5231 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
5235 // pin max sig dig to >= min
5236 int32_t max
= _max(fMaxSignificantDigits
, min
);
5237 fMinSignificantDigits
= min
;
5238 fMaxSignificantDigits
= max
;
5239 #if UCONFIG_FORMAT_FASTPATHS_49
5244 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
5248 // pin min sig dig to 1..max
5249 U_ASSERT(fMinSignificantDigits
>= 1);
5250 int32_t min
= _min(fMinSignificantDigits
, max
);
5251 fMinSignificantDigits
= min
;
5252 fMaxSignificantDigits
= max
;
5253 #if UCONFIG_FORMAT_FASTPATHS_49
5258 UBool
DecimalFormat::areSignificantDigitsUsed() const {
5259 return fUseSignificantDigits
;
5262 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
5263 fUseSignificantDigits
= useSignificantDigits
;
5264 #if UCONFIG_FORMAT_FASTPATHS_49
5269 void DecimalFormat::setCurrencyInternally(const UChar
* theCurrency
,
5271 // If we are a currency format, then modify our affixes to
5272 // encode the currency symbol for the given currency in our
5273 // locale, and adjust the decimal digits and rounding for the
5276 // Note: The code is ordered so that this object is *not changed*
5277 // until we are sure we are going to succeed.
5279 // NULL or empty currency is *legal* and indicates no currency.
5280 UBool isCurr
= (theCurrency
&& *theCurrency
);
5282 double rounding
= 0.0;
5284 if (fCurrencySignCount
> fgCurrencySignCountZero
&& isCurr
) {
5285 rounding
= ucurr_getRoundingIncrement(theCurrency
, &ec
);
5286 frac
= ucurr_getDefaultFractionDigits(theCurrency
, &ec
);
5289 NumberFormat::setCurrency(theCurrency
, ec
);
5290 if (U_FAILURE(ec
)) return;
5292 if (fCurrencySignCount
> fgCurrencySignCountZero
) {
5293 // NULL or empty currency is *legal* and indicates no currency.
5295 setRoundingIncrement(rounding
);
5296 setMinimumFractionDigits(frac
);
5297 setMaximumFractionDigits(frac
);
5299 expandAffixes(NULL
);
5301 #if UCONFIG_FORMAT_FASTPATHS_49
5306 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
5307 // set the currency before compute affixes to get the right currency names
5308 NumberFormat::setCurrency(theCurrency
, ec
);
5309 if (fFormatPattern
.indexOf(fgTripleCurrencySign
, 3, 0) != -1) {
5310 UnicodeString savedPtn
= fFormatPattern
;
5311 setupCurrencyAffixes(fFormatPattern
, TRUE
, TRUE
, ec
);
5312 UParseError parseErr
;
5313 applyPattern(savedPtn
, FALSE
, parseErr
, ec
);
5315 // set the currency after apply pattern to get the correct rounding/fraction
5316 setCurrencyInternally(theCurrency
, ec
);
5317 #if UCONFIG_FORMAT_FASTPATHS_49
5322 // Deprecated variant with no UErrorCode parameter
5323 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
5324 UErrorCode ec
= U_ZERO_ERROR
;
5325 setCurrency(theCurrency
, ec
);
5326 #if UCONFIG_FORMAT_FASTPATHS_49
5331 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
5332 if (fSymbols
== NULL
) {
5333 ec
= U_MEMORY_ALLOCATION_ERROR
;
5337 const UChar
* c
= getCurrency();
5339 const UnicodeString
&intl
=
5340 fSymbols
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
5341 c
= intl
.getBuffer(); // ok for intl to go out of scope
5343 u_strncpy(result
, c
, 3);
5348 * Return the number of fraction digits to display, or the total
5349 * number of digits for significant digit formats and exponential
5353 DecimalFormat::precision() const {
5354 if (areSignificantDigitsUsed()) {
5355 return getMaximumSignificantDigits();
5356 } else if (fUseExponentialNotation
) {
5357 return getMinimumIntegerDigits() + getMaximumFractionDigits();
5359 return getMaximumFractionDigits();
5364 // TODO: template algorithm
5366 DecimalFormat::initHashForAffix(UErrorCode
& status
) {
5367 if ( U_FAILURE(status
) ) {
5371 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
5372 status
= U_MEMORY_ALLOCATION_ERROR
;
5375 if ( U_FAILURE(status
) ) {
5379 hTable
->setValueComparator(decimfmtAffixValueComparator
);
5384 DecimalFormat::initHashForAffixPattern(UErrorCode
& status
) {
5385 if ( U_FAILURE(status
) ) {
5389 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
5390 status
= U_MEMORY_ALLOCATION_ERROR
;
5393 if ( U_FAILURE(status
) ) {
5397 hTable
->setValueComparator(decimfmtAffixPatternValueComparator
);
5402 DecimalFormat::deleteHashForAffix(Hashtable
*& table
)
5404 if ( table
== NULL
) {
5408 const UHashElement
* element
= NULL
;
5409 while ( (element
= table
->nextElement(pos
)) != NULL
) {
5410 const UHashTok valueTok
= element
->value
;
5411 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
5421 DecimalFormat::deleteHashForAffixPattern()
5423 if ( fAffixPatternsForCurrency
== NULL
) {
5427 const UHashElement
* element
= NULL
;
5428 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
5429 const UHashTok valueTok
= element
->value
;
5430 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
5433 delete fAffixPatternsForCurrency
;
5434 fAffixPatternsForCurrency
= NULL
;
5439 DecimalFormat::copyHashForAffixPattern(const Hashtable
* source
,
5441 UErrorCode
& status
) {
5442 if ( U_FAILURE(status
) ) {
5446 const UHashElement
* element
= NULL
;
5448 while ( (element
= source
->nextElement(pos
)) != NULL
) {
5449 const UHashTok keyTok
= element
->key
;
5450 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
5451 const UHashTok valueTok
= element
->value
;
5452 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
5453 AffixPatternsForCurrency
* copy
= new AffixPatternsForCurrency(
5454 value
->negPrefixPatternForCurrency
,
5455 value
->negSuffixPatternForCurrency
,
5456 value
->posPrefixPatternForCurrency
,
5457 value
->posSuffixPatternForCurrency
,
5458 value
->patternType
);
5459 target
->put(UnicodeString(*key
), copy
, status
);
5460 if ( U_FAILURE(status
) ) {
5467 DecimalFormat
& DecimalFormat::setAttribute( UNumberFormatAttribute attr
,
5469 UErrorCode
&status
) {
5470 if(U_FAILURE(status
)) return *this;
5473 case UNUM_LENIENT_PARSE
:
5474 setLenient(newValue
!=0);
5477 case UNUM_PARSE_INT_ONLY
:
5478 setParseIntegerOnly(newValue
!=0);
5481 case UNUM_GROUPING_USED
:
5482 setGroupingUsed(newValue
!=0);
5485 case UNUM_DECIMAL_ALWAYS_SHOWN
:
5486 setDecimalSeparatorAlwaysShown(newValue
!=0);
5489 case UNUM_MAX_INTEGER_DIGITS
:
5490 setMaximumIntegerDigits(newValue
);
5493 case UNUM_MIN_INTEGER_DIGITS
:
5494 setMinimumIntegerDigits(newValue
);
5497 case UNUM_INTEGER_DIGITS
:
5498 setMinimumIntegerDigits(newValue
);
5499 setMaximumIntegerDigits(newValue
);
5502 case UNUM_MAX_FRACTION_DIGITS
:
5503 setMaximumFractionDigits(newValue
);
5506 case UNUM_MIN_FRACTION_DIGITS
:
5507 setMinimumFractionDigits(newValue
);
5510 case UNUM_FRACTION_DIGITS
:
5511 setMinimumFractionDigits(newValue
);
5512 setMaximumFractionDigits(newValue
);
5515 case UNUM_SIGNIFICANT_DIGITS_USED
:
5516 setSignificantDigitsUsed(newValue
!=0);
5519 case UNUM_MAX_SIGNIFICANT_DIGITS
:
5520 setMaximumSignificantDigits(newValue
);
5523 case UNUM_MIN_SIGNIFICANT_DIGITS
:
5524 setMinimumSignificantDigits(newValue
);
5527 case UNUM_MULTIPLIER
:
5528 setMultiplier(newValue
);
5531 case UNUM_GROUPING_SIZE
:
5532 setGroupingSize(newValue
);
5535 case UNUM_ROUNDING_MODE
:
5536 setRoundingMode((DecimalFormat::ERoundingMode
)newValue
);
5539 case UNUM_FORMAT_WIDTH
:
5540 setFormatWidth(newValue
);
5543 case UNUM_PADDING_POSITION
:
5544 /** The position at which padding will take place. */
5545 setPadPosition((DecimalFormat::EPadPosition
)newValue
);
5548 case UNUM_SECONDARY_GROUPING_SIZE
:
5549 setSecondaryGroupingSize(newValue
);
5552 #if UCONFIG_HAVE_PARSEALLINPUT
5553 case UNUM_PARSE_ALL_INPUT
:
5554 setParseAllInput((UNumberFormatAttributeValue
)newValue
);
5558 /* These are stored in fBoolFlags */
5559 case UNUM_PARSE_NO_EXPONENT
:
5560 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
5561 if(!fBoolFlags
.isValidValue(newValue
)) {
5562 status
= U_ILLEGAL_ARGUMENT_ERROR
;
5564 fBoolFlags
.set(attr
, newValue
);
5573 status
= U_UNSUPPORTED_ERROR
;
5579 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr
,
5580 UErrorCode
&status
) const {
5581 if(U_FAILURE(status
)) return -1;
5583 case UNUM_LENIENT_PARSE
:
5586 case UNUM_PARSE_INT_ONLY
:
5587 return isParseIntegerOnly();
5589 case UNUM_GROUPING_USED
:
5590 return isGroupingUsed();
5592 case UNUM_DECIMAL_ALWAYS_SHOWN
:
5593 return isDecimalSeparatorAlwaysShown();
5595 case UNUM_MAX_INTEGER_DIGITS
:
5596 return getMaximumIntegerDigits();
5598 case UNUM_MIN_INTEGER_DIGITS
:
5599 return getMinimumIntegerDigits();
5601 case UNUM_INTEGER_DIGITS
:
5602 // TBD: what should this return?
5603 return getMinimumIntegerDigits();
5605 case UNUM_MAX_FRACTION_DIGITS
:
5606 return getMaximumFractionDigits();
5608 case UNUM_MIN_FRACTION_DIGITS
:
5609 return getMinimumFractionDigits();
5611 case UNUM_FRACTION_DIGITS
:
5612 // TBD: what should this return?
5613 return getMinimumFractionDigits();
5615 case UNUM_SIGNIFICANT_DIGITS_USED
:
5616 return areSignificantDigitsUsed();
5618 case UNUM_MAX_SIGNIFICANT_DIGITS
:
5619 return getMaximumSignificantDigits();
5621 case UNUM_MIN_SIGNIFICANT_DIGITS
:
5622 return getMinimumSignificantDigits();
5624 case UNUM_MULTIPLIER
:
5625 return getMultiplier();
5627 case UNUM_GROUPING_SIZE
:
5628 return getGroupingSize();
5630 case UNUM_ROUNDING_MODE
:
5631 return getRoundingMode();
5633 case UNUM_FORMAT_WIDTH
:
5634 return getFormatWidth();
5636 case UNUM_PADDING_POSITION
:
5637 return getPadPosition();
5639 case UNUM_SECONDARY_GROUPING_SIZE
:
5640 return getSecondaryGroupingSize();
5642 /* These are stored in fBoolFlags */
5643 case UNUM_PARSE_NO_EXPONENT
:
5644 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
5645 return fBoolFlags
.get(attr
);
5651 status
= U_UNSUPPORTED_ERROR
;
5655 return -1; /* undefined */
5658 #if UCONFIG_HAVE_PARSEALLINPUT
5659 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value
) {
5660 fParseAllInput
= value
;
5661 #if UCONFIG_FORMAT_FASTPATHS_49
5668 DecimalFormat::copyHashForAffix(const Hashtable
* source
,
5670 UErrorCode
& status
) {
5671 if ( U_FAILURE(status
) ) {
5675 const UHashElement
* element
= NULL
;
5677 while ( (element
= source
->nextElement(pos
)) != NULL
) {
5678 const UHashTok keyTok
= element
->key
;
5679 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
5681 const UHashTok valueTok
= element
->value
;
5682 const AffixesForCurrency
* value
= (AffixesForCurrency
*)valueTok
.pointer
;
5683 AffixesForCurrency
* copy
= new AffixesForCurrency(
5684 value
->negPrefixForCurrency
,
5685 value
->negSuffixForCurrency
,
5686 value
->posPrefixForCurrency
,
5687 value
->posSuffixForCurrency
);
5688 target
->put(UnicodeString(*key
), copy
, status
);
5689 if ( U_FAILURE(status
) ) {
5698 #endif /* #if !UCONFIG_NO_FORMATTING */