1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2015, International Business Machines Corporation and *
6 * others. All Rights Reserved. *
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 02/19/97 aliu Converted from java.
15 * 03/20/97 clhuang Implemented with new APIs.
16 * 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it.
17 * 04/3/97 aliu Rewrote parsing and formatting completely, and
18 * cleaned up and debugged. Actually works now.
19 * Implemented NAN and INF handling, for both parsing
20 * and formatting. Extensive testing & debugging.
21 * 04/10/97 aliu Modified to compile on AIX.
22 * 04/16/97 aliu Rewrote to use DigitList, which has been resurrected.
23 * Changed DigitCount to int per code review.
24 * 07/09/97 helena Made ParsePosition into a class.
25 * 08/26/97 aliu Extensive changes to applyPattern; completely
26 * rewritten from the Java.
27 * 09/09/97 aliu Ported over support for exponential formats.
28 * 07/20/98 stephen JDK 1.2 sync up.
29 * Various instances of '0' replaced with 'NULL'
30 * Check for grouping size in subFormat()
31 * Brought subParse() in line with Java 1.2
32 * Added method appendAffix()
33 * 08/24/1998 srl Removed Mutex calls. This is not a thread safe class!
34 * 02/22/99 stephen Removed character literals for EBCDIC safety
35 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
36 * 06/28/99 stephen Fixed bugs in toPattern().
37 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
39 ********************************************************************************
43 #include "unicode/utypes.h"
45 #if !UCONFIG_NO_FORMATTING
47 #include "unicode/uniset.h"
48 #include "unicode/currpinf.h"
49 #include "unicode/plurrule.h"
50 #include "unicode/utf16.h"
51 #include "unicode/numsys.h"
52 #include "unicode/localpointer.h"
53 #include "unicode/ustring.h"
57 #include "patternprops.h"
62 #include "plurrule_impl.h"
63 #include "decimalformatpattern.h"
64 #include "fmtableimp.h"
65 #include "decimfmtimpl.h"
66 #include "visibledigits.h"
69 * On certain platforms, round is a macro defined in math.h
70 * This undefine is to avoid conflict between the macro and
71 * the function defined below.
82 static void _debugout(const char *f
, int l
, const UnicodeString
& s
) {
84 s
.extract((int32_t) 0, s
.length(), buf
, "utf-8");
85 printf("%s:%d: %s\n", f
,l
, buf
);
87 #define debugout(x) _debugout(__FILE__,__LINE__,x)
88 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
89 static const UnicodeString
dbg_null("<NULL>","");
90 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
97 /* For currency parsing purose,
98 * Need to remember all prefix patterns and suffix patterns of
99 * every currency format pattern,
100 * including the pattern of default currecny style
101 * and plural currency style. And the patterns are set through applyPattern.
103 struct AffixPatternsForCurrency
: public UMemory
{
104 // negative prefix pattern
105 UnicodeString negPrefixPatternForCurrency
;
106 // negative suffix pattern
107 UnicodeString negSuffixPatternForCurrency
;
108 // positive prefix pattern
109 UnicodeString posPrefixPatternForCurrency
;
110 // positive suffix pattern
111 UnicodeString posSuffixPatternForCurrency
;
114 AffixPatternsForCurrency(const UnicodeString
& negPrefix
,
115 const UnicodeString
& negSuffix
,
116 const UnicodeString
& posPrefix
,
117 const UnicodeString
& posSuffix
,
119 negPrefixPatternForCurrency
= negPrefix
;
120 negSuffixPatternForCurrency
= negSuffix
;
121 posPrefixPatternForCurrency
= posPrefix
;
122 posSuffixPatternForCurrency
= posSuffix
;
127 debugout( UnicodeString("AffixPatternsForCurrency( -=\"") +
128 negPrefixPatternForCurrency
+ (UnicodeString
)"\"/\"" +
129 negSuffixPatternForCurrency
+ (UnicodeString
)"\" +=\"" +
130 posPrefixPatternForCurrency
+ (UnicodeString
)"\"/\"" +
131 posSuffixPatternForCurrency
+ (UnicodeString
)"\" )");
136 /* affix for currency formatting when the currency sign in the pattern
137 * equals to 3, such as the pattern contains 3 currency sign or
138 * the formatter style is currency plural format style.
140 struct AffixesForCurrency
: public UMemory
{
142 UnicodeString negPrefixForCurrency
;
144 UnicodeString negSuffixForCurrency
;
146 UnicodeString posPrefixForCurrency
;
148 UnicodeString posSuffixForCurrency
;
152 AffixesForCurrency(const UnicodeString
& negPrefix
,
153 const UnicodeString
& negSuffix
,
154 const UnicodeString
& posPrefix
,
155 const UnicodeString
& posSuffix
) {
156 negPrefixForCurrency
= negPrefix
;
157 negSuffixForCurrency
= negSuffix
;
158 posPrefixForCurrency
= posPrefix
;
159 posSuffixForCurrency
= posSuffix
;
163 debugout( UnicodeString("AffixesForCurrency( -=\"") +
164 negPrefixForCurrency
+ (UnicodeString
)"\"/\"" +
165 negSuffixForCurrency
+ (UnicodeString
)"\" +=\"" +
166 posPrefixForCurrency
+ (UnicodeString
)"\"/\"" +
167 posSuffixForCurrency
+ (UnicodeString
)"\" )");
177 static UBool U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
);
181 U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
) {
182 const AffixPatternsForCurrency
* affix_1
=
183 (AffixPatternsForCurrency
*)val1
.pointer
;
184 const AffixPatternsForCurrency
* affix_2
=
185 (AffixPatternsForCurrency
*)val2
.pointer
;
186 return affix_1
->negPrefixPatternForCurrency
==
187 affix_2
->negPrefixPatternForCurrency
&&
188 affix_1
->negSuffixPatternForCurrency
==
189 affix_2
->negSuffixPatternForCurrency
&&
190 affix_1
->posPrefixPatternForCurrency
==
191 affix_2
->posPrefixPatternForCurrency
&&
192 affix_1
->posSuffixPatternForCurrency
==
193 affix_2
->posSuffixPatternForCurrency
&&
194 affix_1
->patternType
== affix_2
->patternType
;
202 // *****************************************************************************
203 // class DecimalFormat
204 // *****************************************************************************
206 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat
)
208 // Constants for characters used in programmatic (unlocalized) patterns.
209 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
210 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
211 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
212 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
213 #define kPatternPerMill ((UChar)0x2030)
214 #define kPatternPercent ((UChar)0x0025) /*'%'*/
215 #define kPatternDigit ((UChar)0x0023) /*'#'*/
216 #define kPatternSeparator ((UChar)0x003B) /*';'*/
217 #define kPatternExponent ((UChar)0x0045) /*'E'*/
218 #define kPatternPlus ((UChar)0x002B) /*'+'*/
219 #define kPatternMinus ((UChar)0x002D) /*'-'*/
220 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
221 #define kQuote ((UChar)0x0027) /*'\''*/
223 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
224 * is used in patterns and substitued with either the currency symbol,
225 * or if it is doubled, with the international currency symbol. If the
226 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
227 * replaced with the monetary decimal separator.
229 #define kCurrencySign ((UChar)0x00A4)
230 #define kDefaultPad ((UChar)0x0020) /* */
232 const int32_t DecimalFormat::kDoubleIntegerDigits
= 309;
233 const int32_t DecimalFormat::kDoubleFractionDigits
= 340;
235 const int32_t DecimalFormat::kMaxScientificIntegerDigits
= 8;
238 * These are the tags we expect to see in normal resource bundle files associated
241 const char DecimalFormat::fgNumberPatterns
[]="NumberPatterns"; // Deprecated - not used
242 static const char fgNumberElements
[]="NumberElements";
243 static const char fgLatn
[]="latn";
244 static const char fgPatterns
[]="patterns";
245 static const char fgDecimalFormat
[]="decimalFormat";
246 static const char fgCurrencyFormat
[]="currencyFormat";
248 inline int32_t _min(int32_t a
, int32_t b
) { return (a
<b
) ? a
: b
; }
249 inline int32_t _max(int32_t a
, int32_t b
) { return (a
<b
) ? b
: a
; }
251 //------------------------------------------------------------------------------
252 // Constructs a DecimalFormat instance in the default locale.
254 DecimalFormat::DecimalFormat(UErrorCode
& status
) {
256 UParseError parseError
;
257 construct(status
, parseError
);
260 //------------------------------------------------------------------------------
261 // Constructs a DecimalFormat instance with the specified number format
262 // pattern in the default locale.
264 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
265 UErrorCode
& status
) {
267 UParseError parseError
;
268 construct(status
, parseError
, &pattern
);
271 //------------------------------------------------------------------------------
272 // Constructs a DecimalFormat instance with the specified number format
273 // pattern and the number format symbols in the default locale. The
274 // created instance owns the symbols.
276 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
277 DecimalFormatSymbols
* symbolsToAdopt
,
278 UErrorCode
& status
) {
280 UParseError parseError
;
281 if (symbolsToAdopt
== NULL
)
282 status
= U_ILLEGAL_ARGUMENT_ERROR
;
283 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
286 DecimalFormat::DecimalFormat( const UnicodeString
& pattern
,
287 DecimalFormatSymbols
* symbolsToAdopt
,
288 UParseError
& parseErr
,
289 UErrorCode
& status
) {
291 if (symbolsToAdopt
== NULL
)
292 status
= U_ILLEGAL_ARGUMENT_ERROR
;
293 construct(status
,parseErr
, &pattern
, symbolsToAdopt
);
296 //------------------------------------------------------------------------------
297 // Constructs a DecimalFormat instance with the specified number format
298 // pattern and the number format symbols in the default locale. The
299 // created instance owns the clone of the symbols.
301 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
302 const DecimalFormatSymbols
& symbols
,
303 UErrorCode
& status
) {
305 UParseError parseError
;
306 construct(status
, parseError
, &pattern
, new DecimalFormatSymbols(symbols
));
309 //------------------------------------------------------------------------------
310 // Constructs a DecimalFormat instance with the specified number format
311 // pattern, the number format symbols, and the number format style.
312 // The created instance owns the clone of the symbols.
314 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
315 DecimalFormatSymbols
* symbolsToAdopt
,
316 UNumberFormatStyle style
,
317 UErrorCode
& status
) {
320 UParseError parseError
;
321 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
324 //-----------------------------------------------------------------------------
325 // Common DecimalFormat initialization.
326 // Put all fields of an uninitialized object into a known state.
327 // Common code, shared by all constructors.
328 // Can not fail. Leave the object in good enough shape that the destructor
329 // or assignment operator can run successfully.
331 DecimalFormat::init() {
333 fStyle
= UNUM_DECIMAL
;
334 fAffixPatternsForCurrency
= NULL
;
335 fCurrencyPluralInfo
= NULL
;
336 #if UCONFIG_HAVE_PARSEALLINPUT
337 fParseAllInput
= UNUM_MAYBE
;
344 //------------------------------------------------------------------------------
345 // Constructs a DecimalFormat instance with the specified number format
346 // pattern and the number format symbols in the desired locale. The
347 // created instance owns the symbols.
350 DecimalFormat::construct(UErrorCode
& status
,
351 UParseError
& parseErr
,
352 const UnicodeString
* pattern
,
353 DecimalFormatSymbols
* symbolsToAdopt
)
355 LocalPointer
<DecimalFormatSymbols
> adoptedSymbols(symbolsToAdopt
);
356 if (U_FAILURE(status
))
359 if (adoptedSymbols
.isNull())
361 adoptedSymbols
.adoptInstead(
362 new DecimalFormatSymbols(Locale::getDefault(), status
));
363 if (adoptedSymbols
.isNull() && U_SUCCESS(status
)) {
364 status
= U_MEMORY_ALLOCATION_ERROR
;
366 if (U_FAILURE(status
)) {
370 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
371 if (U_FAILURE(status
)) {
376 // Uses the default locale's number format pattern if there isn't
380 UErrorCode nsStatus
= U_ZERO_ERROR
;
381 LocalPointer
<NumberingSystem
> ns(
382 NumberingSystem::createInstance(nsStatus
));
383 if (U_FAILURE(nsStatus
)) {
389 UResourceBundle
*top
= ures_open(NULL
, Locale::getDefault().getName(), &status
);
391 UResourceBundle
*resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, NULL
, &status
);
392 resource
= ures_getByKeyWithFallback(resource
, ns
->getName(), resource
, &status
);
393 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
394 const UChar
*resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
395 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(fgLatn
,ns
->getName())) {
396 status
= U_ZERO_ERROR
;
397 resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, resource
, &status
);
398 resource
= ures_getByKeyWithFallback(resource
, fgLatn
, resource
, &status
);
399 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
400 resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
402 str
.setTo(TRUE
, resStr
, len
);
404 ures_close(resource
);
408 fImpl
= new DecimalFormatImpl(this, *pattern
, adoptedSymbols
.getAlias(), parseErr
, status
);
410 adoptedSymbols
.orphan();
411 } else if (U_SUCCESS(status
)) {
412 status
= U_MEMORY_ALLOCATION_ERROR
;
414 if (U_FAILURE(status
)) {
418 if (U_FAILURE(status
))
423 const UnicodeString
* patternUsed
;
424 UnicodeString currencyPluralPatternForOther
;
426 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
427 fCurrencyPluralInfo
= new CurrencyPluralInfo(fImpl
->fSymbols
->getLocale(), status
);
428 if (U_FAILURE(status
)) {
432 // the pattern used in format is not fixed until formatting,
433 // in which, the number is known and
434 // will be used to pick the right pattern based on plural count.
435 // Here, set the pattern as the pattern of plural count == "other".
436 // For most locale, the patterns are probably the same for all
437 // plural count. If not, the right pattern need to be re-applied
439 fCurrencyPluralInfo
->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther
);
440 // TODO(refactor): Revisit, we are setting the pattern twice.
441 fImpl
->applyPatternFavorCurrencyPrecision(
442 currencyPluralPatternForOther
, status
);
443 patternUsed
= ¤cyPluralPatternForOther
;
446 patternUsed
= pattern
;
449 if (patternUsed
->indexOf(kCurrencySign
) != -1) {
450 // initialize for currency, not only for plural format,
451 // but also for mix parsing
452 handleCurrencySignInPattern(status
);
457 DecimalFormat::handleCurrencySignInPattern(UErrorCode
& status
) {
458 // initialize for currency, not only for plural format,
459 // but also for mix parsing
460 if (U_FAILURE(status
)) {
463 if (fCurrencyPluralInfo
== NULL
) {
464 fCurrencyPluralInfo
= new CurrencyPluralInfo(fImpl
->fSymbols
->getLocale(), status
);
465 if (U_FAILURE(status
)) {
469 // need it for mix parsing
470 if (fAffixPatternsForCurrency
== NULL
) {
471 setupCurrencyAffixPatterns(status
);
476 applyPatternWithNoSideEffects(
477 const UnicodeString
& pattern
,
478 UParseError
& parseError
,
479 UnicodeString
&negPrefix
,
480 UnicodeString
&negSuffix
,
481 UnicodeString
&posPrefix
,
482 UnicodeString
&posSuffix
,
483 UErrorCode
& status
) {
484 if (U_FAILURE(status
))
488 DecimalFormatPatternParser patternParser
;
489 DecimalFormatPattern out
;
490 patternParser
.applyPatternWithoutExpandAffix(
495 if (U_FAILURE(status
)) {
498 negPrefix
= out
.fNegPrefixPattern
;
499 negSuffix
= out
.fNegSuffixPattern
;
500 posPrefix
= out
.fPosPrefixPattern
;
501 posSuffix
= out
.fPosSuffixPattern
;
505 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode
& status
) {
506 if (U_FAILURE(status
)) {
509 UParseError parseErr
;
510 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
511 if (U_FAILURE(status
)) {
515 NumberingSystem
*ns
= NumberingSystem::createInstance(fImpl
->fSymbols
->getLocale(),status
);
516 if (U_FAILURE(status
)) {
520 // Save the default currency patterns of this locale.
521 // Here, chose onlyApplyPatternWithoutExpandAffix without
522 // expanding the affix patterns into affixes.
523 UnicodeString currencyPattern
;
524 UErrorCode error
= U_ZERO_ERROR
;
526 UResourceBundle
*resource
= ures_open(NULL
, fImpl
->fSymbols
->getLocale().getName(), &error
);
527 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, fgNumberElements
, NULL
, &error
);
528 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &error
);
529 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
531 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
532 if ( error
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(ns
->getName(),fgLatn
)) {
533 error
= U_ZERO_ERROR
;
534 resource
= ures_getByKeyWithFallback(numElements
, fgLatn
, resource
, &error
);
535 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
536 patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
538 ures_close(numElements
);
539 ures_close(resource
);
542 if (U_SUCCESS(error
)) {
543 UnicodeString negPrefix
;
544 UnicodeString negSuffix
;
545 UnicodeString posPrefix
;
546 UnicodeString posSuffix
;
547 applyPatternWithNoSideEffects(UnicodeString(patResStr
, patLen
),
549 negPrefix
, negSuffix
, posPrefix
, posSuffix
, status
);
550 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
556 fAffixPatternsForCurrency
->put(UNICODE_STRING("default", 7), affixPtn
, status
);
559 // save the unique currency plural patterns of this locale.
560 Hashtable
* pluralPtn
= fCurrencyPluralInfo
->fPluralCountToCurrencyUnitPattern
;
561 const UHashElement
* element
= NULL
;
562 int32_t pos
= UHASH_FIRST
;
563 Hashtable pluralPatternSet
;
564 while ((element
= pluralPtn
->nextElement(pos
)) != NULL
) {
565 const UHashTok valueTok
= element
->value
;
566 const UnicodeString
* value
= (UnicodeString
*)valueTok
.pointer
;
567 const UHashTok keyTok
= element
->key
;
568 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
569 if (pluralPatternSet
.geti(*value
) != 1) {
570 UnicodeString negPrefix
;
571 UnicodeString negSuffix
;
572 UnicodeString posPrefix
;
573 UnicodeString posSuffix
;
574 pluralPatternSet
.puti(*value
, 1, status
);
575 applyPatternWithNoSideEffects(
577 negPrefix
, negSuffix
, posPrefix
, posSuffix
, status
);
578 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
584 fAffixPatternsForCurrency
->put(*key
, affixPtn
, status
);
590 //------------------------------------------------------------------------------
592 DecimalFormat::~DecimalFormat()
594 deleteHashForAffixPattern();
595 delete fCurrencyPluralInfo
;
599 //------------------------------------------------------------------------------
602 DecimalFormat::DecimalFormat(const DecimalFormat
&source
) :
603 NumberFormat(source
) {
608 //------------------------------------------------------------------------------
609 // assignment operator
612 static void _clone_ptr(T
** pdest
, const T
* source
) {
614 if (source
== NULL
) {
617 *pdest
= static_cast<T
*>(source
->clone());
622 DecimalFormat::operator=(const DecimalFormat
& rhs
)
625 UErrorCode status
= U_ZERO_ERROR
;
626 NumberFormat::operator=(rhs
);
628 fImpl
= new DecimalFormatImpl(this, *rhs
.fImpl
, status
);
630 fImpl
->assign(*rhs
.fImpl
, status
);
632 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
634 _clone_ptr(&fCurrencyPluralInfo
, rhs
.fCurrencyPluralInfo
);
635 deleteHashForAffixPattern();
636 if (rhs
.fAffixPatternsForCurrency
) {
637 UErrorCode status
= U_ZERO_ERROR
;
638 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
639 copyHashForAffixPattern(rhs
.fAffixPatternsForCurrency
,
640 fAffixPatternsForCurrency
, status
);
647 //------------------------------------------------------------------------------
650 DecimalFormat::operator==(const Format
& that
) const
655 // NumberFormat::operator== guarantees this cast is safe
656 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
659 NumberFormat::operator==(that
) &&
660 fBoolFlags
.getAll() == other
->fBoolFlags
.getAll() &&
661 *fImpl
== *other
->fImpl
);
665 //------------------------------------------------------------------------------
668 DecimalFormat::clone() const
670 return new DecimalFormat(*this);
675 DecimalFormat::getFixedDecimal(double number
, UErrorCode
&status
) const {
676 VisibleDigitsWithExponent digits
;
677 initVisibleDigitsWithExponent(number
, digits
, status
);
678 if (U_FAILURE(status
)) {
679 return FixedDecimal();
681 return FixedDecimal(digits
.getMantissa());
684 VisibleDigitsWithExponent
&
685 DecimalFormat::initVisibleDigitsWithExponent(
687 VisibleDigitsWithExponent
&digits
,
688 UErrorCode
&status
) const {
689 return fImpl
->initVisibleDigitsWithExponent(number
, digits
, status
);
693 DecimalFormat::getFixedDecimal(const Formattable
&number
, UErrorCode
&status
) const {
694 VisibleDigitsWithExponent digits
;
695 initVisibleDigitsWithExponent(number
, digits
, status
);
696 if (U_FAILURE(status
)) {
697 return FixedDecimal();
699 return FixedDecimal(digits
.getMantissa());
702 VisibleDigitsWithExponent
&
703 DecimalFormat::initVisibleDigitsWithExponent(
704 const Formattable
&number
,
705 VisibleDigitsWithExponent
&digits
,
706 UErrorCode
&status
) const {
707 if (U_FAILURE(status
)) {
710 if (!number
.isNumeric()) {
711 status
= U_ILLEGAL_ARGUMENT_ERROR
;
715 DigitList
*dl
= number
.getDigitList();
717 DigitList
dlCopy(*dl
);
718 return fImpl
->initVisibleDigitsWithExponent(
719 dlCopy
, digits
, status
);
722 Formattable::Type type
= number
.getType();
723 if (type
== Formattable::kDouble
|| type
== Formattable::kLong
) {
724 return fImpl
->initVisibleDigitsWithExponent(
725 number
.getDouble(status
), digits
, status
);
727 return fImpl
->initVisibleDigitsWithExponent(
728 number
.getInt64(), digits
, status
);
732 // Create a fixed decimal from a DigitList.
733 // The digit list may be modified.
734 // Internal function only.
736 DecimalFormat::getFixedDecimal(DigitList
&number
, UErrorCode
&status
) const {
737 VisibleDigitsWithExponent digits
;
738 initVisibleDigitsWithExponent(number
, digits
, status
);
739 if (U_FAILURE(status
)) {
740 return FixedDecimal();
742 return FixedDecimal(digits
.getMantissa());
745 VisibleDigitsWithExponent
&
746 DecimalFormat::initVisibleDigitsWithExponent(
748 VisibleDigitsWithExponent
&digits
,
749 UErrorCode
&status
) const {
750 return fImpl
->initVisibleDigitsWithExponent(
751 number
, digits
, status
);
755 //------------------------------------------------------------------------------
758 DecimalFormat::format(int32_t number
,
759 UnicodeString
& appendTo
,
760 FieldPosition
& fieldPosition
) const
762 UErrorCode status
= U_ZERO_ERROR
;
763 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
767 DecimalFormat::format(int32_t number
,
768 UnicodeString
& appendTo
,
769 FieldPosition
& fieldPosition
,
770 UErrorCode
& status
) const
772 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
776 DecimalFormat::format(int32_t number
,
777 UnicodeString
& appendTo
,
778 FieldPositionIterator
* posIter
,
779 UErrorCode
& status
) const
781 return fImpl
->format(number
, appendTo
, posIter
, status
);
785 //------------------------------------------------------------------------------
788 DecimalFormat::format(int64_t number
,
789 UnicodeString
& appendTo
,
790 FieldPosition
& fieldPosition
) const
792 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
793 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
797 DecimalFormat::format(int64_t number
,
798 UnicodeString
& appendTo
,
799 FieldPosition
& fieldPosition
,
800 UErrorCode
& status
) const
802 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
806 DecimalFormat::format(int64_t number
,
807 UnicodeString
& appendTo
,
808 FieldPositionIterator
* posIter
,
809 UErrorCode
& status
) const
811 return fImpl
->format(number
, appendTo
, posIter
, status
);
814 //------------------------------------------------------------------------------
817 DecimalFormat::format( double number
,
818 UnicodeString
& appendTo
,
819 FieldPosition
& fieldPosition
) const
821 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
822 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
826 DecimalFormat::format( double number
,
827 UnicodeString
& appendTo
,
828 FieldPosition
& fieldPosition
,
829 UErrorCode
& status
) const
831 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
835 DecimalFormat::format( double number
,
836 UnicodeString
& appendTo
,
837 FieldPositionIterator
* posIter
,
838 UErrorCode
& status
) const
840 return fImpl
->format(number
, appendTo
, posIter
, status
);
843 //------------------------------------------------------------------------------
847 DecimalFormat::format(StringPiece number
,
848 UnicodeString
&toAppendTo
,
849 FieldPositionIterator
*posIter
,
850 UErrorCode
&status
) const
852 return fImpl
->format(number
, toAppendTo
, posIter
, status
);
857 DecimalFormat::format(const DigitList
&number
,
858 UnicodeString
&appendTo
,
859 FieldPositionIterator
*posIter
,
860 UErrorCode
&status
) const {
861 return fImpl
->format(number
, appendTo
, posIter
, status
);
866 DecimalFormat::format(const DigitList
&number
,
867 UnicodeString
& appendTo
,
869 UErrorCode
&status
) const {
870 return fImpl
->format(number
, appendTo
, pos
, status
);
874 DecimalFormat::format(const VisibleDigitsWithExponent
&number
,
875 UnicodeString
&appendTo
,
876 FieldPositionIterator
*posIter
,
877 UErrorCode
&status
) const {
878 return fImpl
->format(number
, appendTo
, posIter
, status
);
883 DecimalFormat::format(const VisibleDigitsWithExponent
&number
,
884 UnicodeString
& appendTo
,
886 UErrorCode
&status
) const {
887 return fImpl
->format(number
, appendTo
, pos
, status
);
891 DecimalFormat::_round(const DigitList
& number
, DigitList
& adjustedNum
, UBool
& isNegative
, UErrorCode
& status
) const {
892 adjustedNum
= number
;
893 fImpl
->round(adjustedNum
, status
);
894 isNegative
= !adjustedNum
.isPositive();
899 DecimalFormat::parse(const UnicodeString
& text
,
901 ParsePosition
& parsePosition
) const {
902 parse(text
, result
, parsePosition
, NULL
);
905 CurrencyAmount
* DecimalFormat::parseCurrency(const UnicodeString
& text
,
906 ParsePosition
& pos
) const {
907 Formattable parseResult
;
908 int32_t start
= pos
.getIndex();
909 UChar curbuf
[4] = {0};
910 parse(text
, parseResult
, pos
, curbuf
);
911 if (pos
.getIndex() != start
) {
912 if (curbuf
[0]!=0) { // Add this for ICU 61 compatibility
913 UErrorCode ec
= U_ZERO_ERROR
;
914 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curbuf
, ec
), ec
);
916 return currAmt
.orphan();
919 pos
.setIndex(start
); // indicate failure
925 * Parses the given text as a number, optionally providing a currency amount.
926 * @param text the string to parse
927 * @param result output parameter for the numeric result.
928 * @param parsePosition input-output position; on input, the
929 * position within text to match; must have 0 <= pos.getIndex() <
930 * text.length(); on output, the position after the last matched
931 * character. If the parse fails, the position in unchanged upon
933 * @param currency if non-NULL, it should point to a 4-UChar buffer.
934 * In this case the text is parsed as a currency format, and the
935 * ISO 4217 code for the parsed currency is put into the buffer.
936 * Otherwise the text is parsed as a non-currency format.
938 void DecimalFormat::parse(const UnicodeString
& text
,
940 ParsePosition
& parsePosition
,
941 UChar
* currency
) const {
942 int32_t startIdx
, backup
;
943 int32_t i
= startIdx
= backup
= parsePosition
.getIndex();
945 // clear any old contents in the result. In particular, clears any DigitList
946 // that it may be holding.
948 if (currency
!= NULL
) {
949 for (int32_t ci
=0; ci
<4; ci
++) {
954 // Handle NaN as a special case:
955 int32_t formatWidth
= fImpl
->getOldFormatWidth();
957 // Skip padding characters, if around prefix
958 if (formatWidth
> 0 && (
959 fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforePrefix
||
960 fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterPrefix
)) {
961 i
= skipPadding(text
, i
);
965 // skip any leading whitespace
966 i
= backup
= skipUWhiteSpace(text
, i
);
969 // If the text is composed of the representation of NaN, returns NaN.length
970 const UnicodeString
*nan
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
971 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
972 ? 0 : nan
->length());
975 if (formatWidth
> 0 && (fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforeSuffix
|| fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterSuffix
)) {
976 i
= skipPadding(text
, i
);
978 parsePosition
.setIndex(i
);
979 result
.setDouble(uprv_getNaN());
983 // NaN parse failed; start over
985 parsePosition
.setIndex(i
);
987 // status is used to record whether a number is infinite.
988 UBool status
[fgStatusLength
];
990 DigitList
*digits
= result
.getInternalDigitList(); // get one from the stack buffer
991 if (digits
== NULL
) {
992 return; // no way to report error from here.
995 if (fImpl
->fMonetary
) {
996 if (!parseForCurrency(text
, parsePosition
, *digits
,
1002 &fImpl
->fAffixes
.fNegativePrefix
.getOtherVariant().toString(),
1003 &fImpl
->fAffixes
.fNegativeSuffix
.getOtherVariant().toString(),
1004 &fImpl
->fAffixes
.fPositivePrefix
.getOtherVariant().toString(),
1005 &fImpl
->fAffixes
.fPositiveSuffix
.getOtherVariant().toString(),
1006 FALSE
, UCURR_SYMBOL_NAME
,
1007 parsePosition
, *digits
, status
, currency
)) {
1008 debug("!subparse(...) - rewind");
1009 parsePosition
.setIndex(startIdx
);
1015 if (status
[fgStatusInfinite
]) {
1016 double inf
= uprv_getInfinity();
1017 result
.setDouble(digits
->isPositive() ? inf
: -inf
);
1018 // TODO: set the dl to infinity, and let it fall into the code below.
1023 if (!fImpl
->fMultiplier
.isZero()) {
1024 UErrorCode ec
= U_ZERO_ERROR
;
1025 digits
->div(fImpl
->fMultiplier
, ec
);
1028 if (fImpl
->fScale
!= 0) {
1030 ten
.set((int32_t)10);
1031 if (fImpl
->fScale
> 0) {
1032 for (int32_t i
= fImpl
->fScale
; i
> 0; i
--) {
1033 UErrorCode ec
= U_ZERO_ERROR
;
1034 digits
->div(ten
,ec
);
1037 for (int32_t i
= fImpl
->fScale
; i
< 0; i
++) {
1038 UErrorCode ec
= U_ZERO_ERROR
;
1039 digits
->mult(ten
,ec
);
1044 // Negative zero special case:
1045 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1046 // if not parsing integerOnly, leave as -0, which a double can represent.
1047 if (digits
->isZero() && !digits
->isPositive() && isParseIntegerOnly()) {
1048 digits
->setPositive(TRUE
);
1050 result
.adoptDigitList(digits
);
1057 DecimalFormat::parseForCurrency(const UnicodeString
& text
,
1058 ParsePosition
& parsePosition
,
1061 UChar
* currency
) const {
1062 UnicodeString positivePrefix
;
1063 UnicodeString positiveSuffix
;
1064 UnicodeString negativePrefix
;
1065 UnicodeString negativeSuffix
;
1066 fImpl
->fPositivePrefixPattern
.toString(positivePrefix
);
1067 fImpl
->fPositiveSuffixPattern
.toString(positiveSuffix
);
1068 fImpl
->fNegativePrefixPattern
.toString(negativePrefix
);
1069 fImpl
->fNegativeSuffixPattern
.toString(negativeSuffix
);
1071 int origPos
= parsePosition
.getIndex();
1072 int maxPosIndex
= origPos
;
1073 int maxErrorPos
= -1;
1074 // First, parse against current pattern.
1075 // Since current pattern could be set by applyPattern(),
1076 // it could be an arbitrary pattern, and it may not be the one
1077 // defined in current locale.
1078 UBool tmpStatus
[fgStatusLength
];
1079 ParsePosition
tmpPos(origPos
);
1080 DigitList tmpDigitList
;
1082 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
1083 found
= subparse(text
,
1084 &negativePrefix
, &negativeSuffix
,
1085 &positivePrefix
, &positiveSuffix
,
1086 TRUE
, UCURR_LONG_NAME
,
1087 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1089 found
= subparse(text
,
1090 &negativePrefix
, &negativeSuffix
,
1091 &positivePrefix
, &positiveSuffix
,
1092 TRUE
, UCURR_SYMBOL_NAME
,
1093 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1096 if (tmpPos
.getIndex() > maxPosIndex
) {
1097 maxPosIndex
= tmpPos
.getIndex();
1098 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1099 status
[i
] = tmpStatus
[i
];
1101 digits
= tmpDigitList
;
1104 maxErrorPos
= tmpPos
.getErrorIndex();
1106 // Then, parse against affix patterns.
1107 // Those are currency patterns and currency plural patterns.
1108 int32_t pos
= UHASH_FIRST
;
1109 const UHashElement
* element
= NULL
;
1110 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
1111 const UHashTok valueTok
= element
->value
;
1112 const AffixPatternsForCurrency
* affixPtn
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
1113 UBool tmpStatus
[fgStatusLength
];
1114 ParsePosition
tmpPos(origPos
);
1115 DigitList tmpDigitList
;
1118 debug("trying affix for currency..");
1122 UBool result
= subparse(text
,
1123 &affixPtn
->negPrefixPatternForCurrency
,
1124 &affixPtn
->negSuffixPatternForCurrency
,
1125 &affixPtn
->posPrefixPatternForCurrency
,
1126 &affixPtn
->posSuffixPatternForCurrency
,
1127 TRUE
, affixPtn
->patternType
,
1128 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1131 if (tmpPos
.getIndex() > maxPosIndex
) {
1132 maxPosIndex
= tmpPos
.getIndex();
1133 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1134 status
[i
] = tmpStatus
[i
];
1136 digits
= tmpDigitList
;
1139 maxErrorPos
= (tmpPos
.getErrorIndex() > maxErrorPos
) ?
1140 tmpPos
.getErrorIndex() : maxErrorPos
;
1143 // Finally, parse against simple affix to find the match.
1144 // For example, in TestMonster suite,
1145 // if the to-be-parsed text is "-\u00A40,00".
1146 // complexAffixCompare will not find match,
1147 // since there is no ISO code matches "\u00A4",
1148 // and the parse stops at "\u00A4".
1149 // We will just use simple affix comparison (look for exact match)
1152 // TODO: We should parse against simple affix first when
1153 // output currency is not requested. After the complex currency
1154 // parsing implementation was introduced, the default currency
1155 // instance parsing slowed down because of the new code flow.
1156 // I filed #10312 - Yoshito
1157 UBool tmpStatus_2
[fgStatusLength
];
1158 ParsePosition
tmpPos_2(origPos
);
1159 DigitList tmpDigitList_2
;
1161 // Disable complex currency parsing and try it again.
1162 UBool result
= subparse(text
,
1163 &fImpl
->fAffixes
.fNegativePrefix
.getOtherVariant().toString(),
1164 &fImpl
->fAffixes
.fNegativeSuffix
.getOtherVariant().toString(),
1165 &fImpl
->fAffixes
.fPositivePrefix
.getOtherVariant().toString(),
1166 &fImpl
->fAffixes
.fPositiveSuffix
.getOtherVariant().toString(),
1167 FALSE
/* disable complex currency parsing */, UCURR_SYMBOL_NAME
,
1168 tmpPos_2
, tmpDigitList_2
, tmpStatus_2
,
1171 if (tmpPos_2
.getIndex() > maxPosIndex
) {
1172 maxPosIndex
= tmpPos_2
.getIndex();
1173 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1174 status
[i
] = tmpStatus_2
[i
];
1176 digits
= tmpDigitList_2
;
1180 maxErrorPos
= (tmpPos_2
.getErrorIndex() > maxErrorPos
) ?
1181 tmpPos_2
.getErrorIndex() : maxErrorPos
;
1185 //parsePosition.setIndex(origPos);
1186 parsePosition
.setErrorIndex(maxErrorPos
);
1188 parsePosition
.setIndex(maxPosIndex
);
1189 parsePosition
.setErrorIndex(-1);
1196 * Parse the given text into a number. The text is parsed beginning at
1197 * parsePosition, until an unparseable character is seen.
1198 * @param text the string to parse.
1199 * @param negPrefix negative prefix.
1200 * @param negSuffix negative suffix.
1201 * @param posPrefix positive prefix.
1202 * @param posSuffix positive suffix.
1203 * @param complexCurrencyParsing whether it is complex currency parsing or not.
1204 * @param type the currency type to parse against, LONG_NAME only or not.
1205 * @param parsePosition The position at which to being parsing. Upon
1206 * return, the first unparsed character.
1207 * @param digits the DigitList to set to the parsed value.
1208 * @param status output param containing boolean status flags indicating
1209 * whether the value was infinite and whether it was positive.
1210 * @param currency return value for parsed currency, for generic
1211 * currency parsing mode, or NULL for normal parsing. In generic
1212 * currency parsing mode, any currency is parsed, not just the
1213 * currency that this formatter is set to.
1215 UBool
DecimalFormat::subparse(const UnicodeString
& text
,
1216 const UnicodeString
* negPrefix
,
1217 const UnicodeString
* negSuffix
,
1218 const UnicodeString
* posPrefix
,
1219 const UnicodeString
* posSuffix
,
1220 UBool complexCurrencyParsing
,
1222 ParsePosition
& parsePosition
,
1223 DigitList
& digits
, UBool
* status
,
1224 UChar
* currency
) const
1226 // The parsing process builds up the number as char string, in the neutral format that
1227 // will be acceptable to the decNumber library, then at the end passes that string
1228 // off for conversion to a decNumber.
1229 UErrorCode err
= U_ZERO_ERROR
;
1230 CharString parsedNum
;
1233 int32_t position
= parsePosition
.getIndex();
1234 int32_t oldStart
= position
;
1235 int32_t textLength
= text
.length(); // One less pointer to follow
1236 UBool strictParse
= !isLenient();
1237 UChar32 zero
= fImpl
->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1238 const UnicodeString
*groupingString
= &fImpl
->getConstSymbol(
1240 DecimalFormatSymbols::kGroupingSeparatorSymbol
: DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
1241 UChar32 groupingChar
= groupingString
->char32At(0);
1242 int32_t groupingStringLength
= groupingString
->length();
1243 int32_t groupingCharLength
= U16_LENGTH(groupingChar
);
1244 UBool groupingUsed
= isGroupingUsed();
1247 UnicodeString
s(dbgbuf
,0,300);;
1248 s
.append((UnicodeString
)"PARSE \"").append(text
.tempSubString(position
)).append((UnicodeString
)"\" " );
1249 #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 ")); }
1257 UBool fastParseOk
= false; /* TRUE iff fast parse is OK */
1258 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
1259 if((fImpl
->isParseFastpath()) && !fImpl
->fMonetary
&&
1262 (posPrefix
==NULL
||posPrefix
->isEmpty()) &&
1263 (posSuffix
==NULL
||posSuffix
->isEmpty()) &&
1264 // (negPrefix==NULL||negPrefix->isEmpty()) &&
1265 // (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
1266 TRUE
) { // optimized path
1268 int l
=text
.length();
1270 UChar32 ch
= text
.char32At(j
);
1271 const UnicodeString
*decimalString
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1272 UChar32 decimalChar
= 0;
1273 UBool intOnly
= FALSE
;
1274 UChar32 lookForGroup
= (groupingUsed
&&intOnly
&&strictParse
)?groupingChar
:0;
1276 int32_t decimalCount
= decimalString
->countChar32(0,3);
1277 if(isParseIntegerOnly()) {
1278 decimalChar
= 0; // not allowed
1279 intOnly
= TRUE
; // Don't look for decimals.
1280 } else if(decimalCount
==1) {
1281 decimalChar
= decimalString
->char32At(0); // Look for this decimal
1282 } else if(decimalCount
==0) {
1283 decimalChar
=0; // NO decimal set
1285 j
=l
+1;//Set counter to end of line, so that we break. Unknown decimal situation.
1289 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
1290 decimalChar
, groupingChar
, ch
,
1292 (strictParse
)?'y':'n');
1294 if(ch
==0x002D) { // '-'
1295 j
=l
+1;//=break - negative number.
1298 parsedNum.append('-',err);
1300 if(j<l) ch = text.char32At(j);
1303 parsedNum
.append('+',err
);
1306 int32_t digit
= ch
- zero
;
1307 if(digit
>=0 && digit
<= 9) {
1308 parsedNum
.append((char)(digit
+ '0'), err
);
1309 if((digitCount
>0) || digit
!=0 || j
==(l
-1)) {
1312 } else if(ch
== 0) { // break out
1315 } else if(ch
== decimalChar
) {
1316 parsedNum
.append((char)('.'), err
);
1317 decimalChar
=0; // no more decimals.
1318 // fastParseHadDecimal=TRUE;
1319 } else if(ch
== lookForGroup
) {
1320 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
1321 } else if(intOnly
&& (lookForGroup
!=0) && !u_isdigit(ch
)) {
1322 // parsing integer only and can fall through
1324 digitCount
=-1; // fail - fall through to slow parse
1328 ch
= text
.char32At(j
); // for next
1331 ((j
==l
)||intOnly
) // end OR only parsing integer
1332 && (digitCount
>0)) { // and have at least one digit
1333 fastParseOk
=true; // Fast parse OK!
1337 /* for testing, try it the slow way. also */
1341 parsePosition
.setIndex(position
=j
);
1342 status
[fgStatusInfinite
]=false;
1345 // was not OK. reset, retry
1347 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j
, l
, digitCount
);
1353 printf("Could not fastpath parse. ");
1354 printf("text.length()=%d ", text
.length());
1355 printf("posPrefix=%p posSuffix=%p ", posPrefix
, posSuffix
);
1361 UnicodeString formatPattern
;
1362 toPattern(formatPattern
);
1365 #if UCONFIG_HAVE_PARSEALLINPUT
1366 && fParseAllInput
!=UNUM_YES
1370 int32_t formatWidth
= fImpl
->getOldFormatWidth();
1371 // Match padding before prefix
1372 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforePrefix
) {
1373 position
= skipPadding(text
, position
);
1376 // Match positive and negative prefixes; prefer longest match.
1377 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, posPrefix
, complexCurrencyParsing
, type
, currency
);
1378 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, negPrefix
, complexCurrencyParsing
, type
, currency
);
1379 if (posMatch
>= 0 && negMatch
>= 0) {
1380 if (posMatch
> negMatch
) {
1382 } else if (negMatch
> posMatch
) {
1386 if (posMatch
>= 0) {
1387 position
+= posMatch
;
1388 parsedNum
.append('+', err
);
1389 } else if (negMatch
>= 0) {
1390 position
+= negMatch
;
1391 parsedNum
.append('-', err
);
1392 } else if (strictParse
){
1393 parsePosition
.setErrorIndex(position
);
1396 // Temporary set positive. This might be changed after checking suffix
1397 parsedNum
.append('+', err
);
1400 // Match padding before prefix
1401 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterPrefix
) {
1402 position
= skipPadding(text
, position
);
1405 if (! strictParse
) {
1406 position
= skipUWhiteSpace(text
, position
);
1409 // process digits or Inf, find decimal position
1410 const UnicodeString
*inf
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1411 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
1412 ? 0 : inf
->length());
1413 position
+= infLen
; // infLen is non-zero when it does equal to infinity
1414 status
[fgStatusInfinite
] = infLen
!= 0;
1417 parsedNum
.append("Infinity", err
);
1419 // We now have a string of digits, possibly with grouping symbols,
1420 // and decimal points. We want to process these into a DigitList.
1421 // We don't want to put a bunch of leading zeros into the DigitList
1422 // though, so we keep track of the location of the decimal point,
1423 // put only significant digits into the DigitList, and adjust the
1424 // exponent as needed.
1427 UBool strictFail
= FALSE
; // did we exit with a strict parse failure?
1428 int32_t lastGroup
= -1; // after which digit index did we last see a grouping separator?
1429 int32_t currGroup
= -1; // for temporary storage the digit index of the current grouping separator
1430 int32_t gs2
= fImpl
->fEffGrouping
.fGrouping2
== 0 ? fImpl
->fEffGrouping
.fGrouping
: fImpl
->fEffGrouping
.fGrouping2
;
1432 const UnicodeString
*decimalString
;
1433 if (fImpl
->fMonetary
) {
1434 decimalString
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1436 decimalString
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1438 UChar32 decimalChar
= decimalString
->char32At(0);
1439 int32_t decimalStringLength
= decimalString
->length();
1440 int32_t decimalCharLength
= U16_LENGTH(decimalChar
);
1442 UBool sawDecimal
= FALSE
;
1443 UChar32 sawDecimalChar
= 0xFFFF;
1444 UBool sawGrouping
= FALSE
;
1445 UChar32 sawGroupingChar
= 0xFFFF;
1446 UBool sawDigit
= FALSE
;
1447 int32_t backup
= -1;
1450 // equivalent grouping and decimal support
1451 const UnicodeSet
*decimalSet
= NULL
;
1452 const UnicodeSet
*groupingSet
= NULL
;
1454 if (decimalCharLength
== decimalStringLength
) {
1455 decimalSet
= DecimalFormatStaticSets::getSimilarDecimals(decimalChar
, strictParse
);
1458 if (groupingCharLength
== groupingStringLength
) {
1460 groupingSet
= fStaticSets
->fStrictDefaultGroupingSeparators
;
1462 groupingSet
= fStaticSets
->fDefaultGroupingSeparators
;
1466 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
1467 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
1468 // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
1470 // We have to track digitCount ourselves, because digits.fCount will
1471 // pin when the maximum allowable digits is reached.
1472 int32_t digitCount
= 0;
1473 int32_t integerDigitCount
= 0;
1474 int32_t allDigitCount
= 0; // digits including leading zeros
1476 for (; position
< textLength
; )
1478 UChar32 ch
= text
.char32At(position
);
1480 /* We recognize all digit ranges, not only the Latin digit range
1481 * '0'..'9'. We do so by using the Character.digit() method,
1482 * which converts a valid Unicode digit to the range 0..9.
1484 * The character 'ch' may be a digit. If so, place its value
1485 * from 0 to 9 in 'digit'. First try using the locale digit,
1486 * which may or MAY NOT be a standard Unicode digit range. If
1487 * this fails, try using the standard Unicode digit ranges by
1488 * calling Character.digit(). If this also fails, digit will
1489 * have a value outside the range 0..9.
1492 if (digit
< 0 || digit
> 9)
1494 digit
= u_charDigitValue(ch
);
1497 // As a last resort, look through the localized digits if the zero digit
1498 // is not a "standard" Unicode digit.
1499 if ( (digit
< 0 || digit
> 9) && u_charDigitValue(zero
) != 0) {
1501 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is:
1502 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits.
1503 if ( zero
!=0x3007 || ch
!=0x96F6 ) {
1504 for (digit
= 1 ; digit
< 10 ; digit
++ ) {
1505 if ( fImpl
->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)(DecimalFormatSymbols::kOneDigitSymbol
+digit
-1)).char32At(0) == ch
) {
1512 if (digit
>= 0 && digit
<= 9)
1514 if (strictParse
&& backup
!= -1) {
1515 // comma followed by digit, so group before comma is a
1516 // secondary group. If there was a group separator
1517 // before that, the group must == the secondary group
1518 // length, else it can be <= the the secondary group
1520 if ((lastGroup
!= -1 && currGroup
- lastGroup
!= gs2
) ||
1521 (lastGroup
== -1 && allDigitCount
- 1 > gs2
)) {
1526 lastGroup
= currGroup
;
1529 // Cancel out backup setting (see grouping handler below)
1534 // Note: this will append leading zeros
1535 parsedNum
.append((char)(digit
+ '0'), err
);
1538 // count any digit that's not a leading zero
1539 if (digit
> 0 || digitCount
> 0 || sawDecimal
) {
1542 // count any integer digit that's not a leading zero
1544 integerDigitCount
+= 1;
1548 position
+= U16_LENGTH(ch
);
1550 else if (groupingStringLength
> 0 &&
1551 matchGrouping(groupingChar
, sawGrouping
, sawGroupingChar
, groupingSet
,
1552 decimalChar
, decimalSet
,
1553 ch
) && groupingUsed
)
1560 if ( (!sawDigit
&& groupingSet
!=NULL
&& u_isWhitespace(ch
)) || backup
!= -1 ) {
1561 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for
1562 // backward compatibility) as long as it is not one of the breaking whitespace characters
1563 // that is only treated as a group separator because of the equivalence set. If we get
1564 // here it is because the leading sep was such a breaking space, or there were multiple
1565 // group separators in a row. Note that the DecimalFormat documentation says
1566 // "During parsing, grouping separators are ignored" and that was for strict parsing,
1567 // so we may need to further revisit this strictParse restriction to ensure compatibility.
1568 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F.
1569 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP).
1575 // Ignore grouping characters, if we are using them, but require
1576 // that they be followed by a digit. Otherwise we backup and
1578 currGroup
= allDigitCount
;
1580 position
+= groupingStringLength
;
1582 // Once we see a grouping character, we only accept that grouping character from then on.
1585 else if (matchDecimal(decimalChar
,sawDecimal
,sawDecimalChar
, decimalSet
, ch
))
1589 (lastGroup
!= -1 && allDigitCount
- lastGroup
!= fImpl
->fEffGrouping
.fGrouping
)) {
1595 // If we're only parsing integers, or if we ALREADY saw the
1596 // decimal, then don't parse this one.
1597 if (isParseIntegerOnly() || sawDecimal
) {
1601 parsedNum
.append('.', err
);
1602 position
+= decimalStringLength
;
1604 // Once we see a decimal character, we only accept that decimal character from then on.
1606 // decimalSet is considered to consist of (ch,ch)
1610 if(!fBoolFlags
.contains(UNUM_PARSE_NO_EXPONENT
) || // don't parse if this is set unless..
1611 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
1612 const UnicodeString
*tmp
;
1613 tmp
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1615 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
1617 // Parse sign, if present
1618 int32_t pos
= position
+ tmp
->length();
1619 char exponentSign
= '+';
1621 if (pos
< textLength
)
1623 tmp
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1624 if (!text
.compare(pos
, tmp
->length(), *tmp
))
1626 pos
+= tmp
->length();
1629 tmp
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1630 if (!text
.compare(pos
, tmp
->length(), *tmp
))
1633 pos
+= tmp
->length();
1638 UBool sawExponentDigit
= FALSE
;
1639 while (pos
< textLength
) {
1640 ch
= text
.char32At(pos
);
1643 if (digit
< 0 || digit
> 9) {
1644 digit
= u_charDigitValue(ch
);
1646 if (0 <= digit
&& digit
<= 9) {
1647 if (!sawExponentDigit
) {
1648 parsedNum
.append('E', err
);
1649 parsedNum
.append(exponentSign
, err
);
1650 sawExponentDigit
= TRUE
;
1652 pos
+= U16_LENGTH(ch
);
1653 parsedNum
.append((char)(digit
+ '0'), err
);
1659 if (sawExponentDigit
) {
1660 position
= pos
; // Advance past the exponent
1663 break; // Whether we fail or succeed, we exit this loop
1667 } else { // not parsing exponent
1673 // if we didn't see a decimal and it is required, check to see if the pattern had one
1674 if(!sawDecimal
&& isDecimalPatternMatchRequired())
1676 if(formatPattern
.indexOf(kPatternDecimalSeparator
) != -1)
1678 parsePosition
.setIndex(oldStart
);
1679 parsePosition
.setErrorIndex(position
);
1680 debug("decimal point match required fail!");
1690 if (strictParse
&& !sawDecimal
) {
1691 if (lastGroup
!= -1 && allDigitCount
- lastGroup
!= fImpl
->fEffGrouping
.fGrouping
) {
1697 // only set with strictParse and a grouping separator error
1699 parsePosition
.setIndex(oldStart
);
1700 parsePosition
.setErrorIndex(position
);
1701 debug("strictFail!");
1705 // If there was no decimal point we have an integer
1707 // If none of the text string was recognized. For example, parse
1708 // "x" with pattern "#0.00" (return index and error index both 0)
1709 // parse "$" with pattern "$#0.00". (return index 0 and error index
1711 if (!sawDigit
&& digitCount
== 0) {
1713 debug("none of text rec");
1714 printf("position=%d\n",position
);
1716 parsePosition
.setIndex(oldStart
);
1717 parsePosition
.setErrorIndex(oldStart
);
1722 // Match padding before suffix
1723 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforeSuffix
) {
1724 position
= skipPadding(text
, position
);
1727 int32_t posSuffixMatch
= -1, negSuffixMatch
= -1;
1729 // Match positive and negative suffixes; prefer longest match.
1730 if (posMatch
>= 0 || (!strictParse
&& negMatch
< 0)) {
1731 posSuffixMatch
= compareAffix(text
, position
, FALSE
, FALSE
, posSuffix
, complexCurrencyParsing
, type
, currency
);
1733 if (negMatch
>= 0) {
1734 negSuffixMatch
= compareAffix(text
, position
, TRUE
, FALSE
, negSuffix
, complexCurrencyParsing
, type
, currency
);
1736 if (posSuffixMatch
>= 0 && negSuffixMatch
>= 0) {
1737 if (posSuffixMatch
> negSuffixMatch
) {
1738 negSuffixMatch
= -1;
1739 } else if (negSuffixMatch
> posSuffixMatch
) {
1740 posSuffixMatch
= -1;
1744 // Fail if neither or both
1745 if (strictParse
&& ((posSuffixMatch
>= 0) == (negSuffixMatch
>= 0))) {
1746 parsePosition
.setErrorIndex(position
);
1747 debug("neither or both");
1751 position
+= (posSuffixMatch
>= 0 ? posSuffixMatch
: (negSuffixMatch
>= 0 ? negSuffixMatch
: 0));
1753 // Match padding before suffix
1754 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterSuffix
) {
1755 position
= skipPadding(text
, position
);
1758 parsePosition
.setIndex(position
);
1760 parsedNum
.data()[0] = (posSuffixMatch
>= 0 || (!strictParse
&& negMatch
< 0 && negSuffixMatch
< 0)) ? '+' : '-';
1762 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position
, parsedNum
.data(), parsePosition
.getIndex(),oldStart
,u_errorName(err
));
1764 } /* end SLOW parse */
1765 if(parsePosition
.getIndex() == oldStart
)
1768 printf(" PP didnt move, err\n");
1770 parsePosition
.setErrorIndex(position
);
1773 #if UCONFIG_HAVE_PARSEALLINPUT
1774 else if (fParseAllInput
==UNUM_YES
&&parsePosition
.getIndex()!=textLength
)
1777 printf(" PP didnt consume all (UNUM_YES), err\n");
1779 parsePosition
.setErrorIndex(position
);
1783 // uint32_t bits = (fastParseOk?kFastpathOk:0) |
1784 // (fastParseHadDecimal?0:kNoDecimal);
1785 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
1786 digits
.set(parsedNum
.toStringPiece(),
1791 if (U_FAILURE(err
)) {
1793 printf(" err setting %s\n", u_errorName(err
));
1795 parsePosition
.setErrorIndex(position
);
1799 // check if we missed a required decimal point
1800 if(fastParseOk
&& isDecimalPatternMatchRequired())
1802 if(formatPattern
.indexOf(kPatternDecimalSeparator
) != -1)
1804 parsePosition
.setIndex(oldStart
);
1805 parsePosition
.setErrorIndex(position
);
1806 debug("decimal point match required fail!");
1816 * Starting at position, advance past a run of pad characters, if any.
1817 * Return the index of the first character after position that is not a pad
1818 * character. Result is >= position.
1820 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
1821 int32_t padLen
= U16_LENGTH(fImpl
->fAffixes
.fPadChar
);
1822 while (position
< text
.length() &&
1823 text
.char32At(position
) == fImpl
->fAffixes
.fPadChar
) {
1830 * Return the length matched by the given affix, or -1 if none.
1831 * Runs of white space in the affix, match runs of white space in
1832 * the input. Pattern white space and input white space are
1833 * determined differently; see code.
1834 * @param text input text
1835 * @param pos offset into input at which to begin matching
1838 * @param affixPat affix pattern used for currency affix comparison.
1839 * @param complexCurrencyParsing whether it is currency parsing or not
1840 * @param type the currency type to parse against, LONG_NAME only or not.
1841 * @param currency return value for parsed currency, for generic
1842 * currency parsing mode, or null for normal parsing. In generic
1843 * currency parsing mode, any currency is parsed, not just the
1844 * currency that this formatter is set to.
1845 * @return length of input that matches, or -1 if match failure
1847 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
1851 const UnicodeString
* affixPat
,
1852 UBool complexCurrencyParsing
,
1854 UChar
* currency
) const
1856 const UnicodeString
*patternToCompare
;
1857 if (currency
!= NULL
||
1858 (fImpl
->fMonetary
&& complexCurrencyParsing
)) {
1860 if (affixPat
!= NULL
) {
1861 return compareComplexAffix(*affixPat
, text
, pos
, type
, currency
);
1867 patternToCompare
= &fImpl
->fAffixes
.fNegativePrefix
.getOtherVariant().toString();
1870 patternToCompare
= &fImpl
->fAffixes
.fNegativeSuffix
.getOtherVariant().toString();
1875 patternToCompare
= &fImpl
->fAffixes
.fPositivePrefix
.getOtherVariant().toString();
1878 patternToCompare
= &fImpl
->fAffixes
.fPositiveSuffix
.getOtherVariant().toString();
1881 return compareSimpleAffix(*patternToCompare
, text
, pos
, isLenient());
1884 UBool
DecimalFormat::equalWithSignCompatibility(UChar32 lhs
, UChar32 rhs
) const {
1888 U_ASSERT(fStaticSets
!= NULL
); // should already be loaded
1889 const UnicodeSet
*minusSigns
= fStaticSets
->fMinusSigns
;
1890 const UnicodeSet
*plusSigns
= fStaticSets
->fPlusSigns
;
1891 return (minusSigns
->contains(lhs
) && minusSigns
->contains(rhs
)) ||
1892 (plusSigns
->contains(lhs
) && plusSigns
->contains(rhs
));
1895 // check for LRM 0x200E, RLM 0x200F, ALM 0x061C
1896 #define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C)
1898 #define TRIM_BUFLEN 32
1899 UnicodeString
& DecimalFormat::trimMarksFromAffix(const UnicodeString
& affix
, UnicodeString
& trimmedAffix
) {
1900 UChar trimBuf
[TRIM_BUFLEN
];
1901 int32_t affixLen
= affix
.length();
1902 int32_t affixPos
, trimLen
= 0;
1904 for (affixPos
= 0; affixPos
< affixLen
; affixPos
++) {
1905 UChar c
= affix
.charAt(affixPos
);
1906 if (!IS_BIDI_MARK(c
)) {
1907 if (trimLen
< TRIM_BUFLEN
) {
1908 trimBuf
[trimLen
++] = c
;
1915 return (trimLen
> 0)? trimmedAffix
.setTo(trimBuf
, trimLen
): trimmedAffix
.setTo(affix
);
1919 * Return the length matched by the given affix, or -1 if none.
1920 * Runs of white space in the affix, match runs of white space in
1921 * the input. Pattern white space and input white space are
1922 * determined differently; see code.
1923 * @param affix pattern string, taken as a literal
1924 * @param input input text
1925 * @param pos offset into input at which to begin matching
1926 * @return length of input that matches, or -1 if match failure
1928 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
1929 const UnicodeString
& input
,
1931 UBool lenient
) const {
1932 int32_t start
= pos
;
1933 UnicodeString trimmedAffix
;
1934 // For more efficiency we should keep lazily-created trimmed affixes around in
1935 // instance variables instead of trimming each time they are used (the next step)
1936 trimMarksFromAffix(affix
, trimmedAffix
);
1937 UChar32 affixChar
= trimmedAffix
.char32At(0);
1938 int32_t affixLength
= trimmedAffix
.length();
1939 int32_t inputLength
= input
.length();
1940 int32_t affixCharLength
= U16_LENGTH(affixChar
);
1941 UnicodeSet
*affixSet
;
1942 UErrorCode status
= U_ZERO_ERROR
;
1944 U_ASSERT(fStaticSets
!= NULL
); // should already be loaded
1946 if (U_FAILURE(status
)) {
1950 affixSet
= fStaticSets
->fStrictDashEquivalents
;
1952 // If the trimmedAffix is exactly one character long and that character
1953 // is in the dash set and the very next input character is also
1954 // in the dash set, return a match.
1955 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
1956 UChar32 ic
= input
.char32At(pos
);
1957 if (affixSet
->contains(ic
)) {
1958 pos
+= U16_LENGTH(ic
);
1959 pos
= skipBidiMarks(input
, pos
); // skip any trailing bidi marks
1964 for (int32_t i
= 0; i
< affixLength
; ) {
1965 UChar32 c
= trimmedAffix
.char32At(i
);
1966 int32_t len
= U16_LENGTH(c
);
1967 if (PatternProps::isWhiteSpace(c
)) {
1968 // We may have a pattern like: \u200F \u0020
1969 // and input text like: \u200F \u0020
1970 // Note that U+200F and U+0020 are Pattern_White_Space but only
1971 // U+0020 is UWhiteSpace. So we have to first do a direct
1972 // match of the run of Pattern_White_Space in the pattern,
1973 // then match any extra characters.
1974 UBool literalMatch
= FALSE
;
1975 while (pos
< inputLength
) {
1976 UChar32 ic
= input
.char32At(pos
);
1978 literalMatch
= TRUE
;
1981 if (i
== affixLength
) {
1984 c
= trimmedAffix
.char32At(i
);
1985 len
= U16_LENGTH(c
);
1986 if (!PatternProps::isWhiteSpace(c
)) {
1989 } else if (IS_BIDI_MARK(ic
)) {
1990 pos
++; // just skip over this input text
1996 // Advance over run in pattern
1997 i
= skipPatternWhiteSpace(trimmedAffix
, i
);
1999 // Advance over run in input text
2000 // Must see at least one white space char in input,
2001 // unless we've already matched some characters literally.
2003 pos
= skipUWhiteSpace(input
, pos
);
2004 if (pos
== s
&& !literalMatch
) {
2008 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2009 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2010 // is also in the trimmedAffix.
2011 i
= skipUWhiteSpace(trimmedAffix
, i
);
2013 UBool match
= FALSE
;
2014 while (pos
< inputLength
) {
2015 UChar32 ic
= input
.char32At(pos
);
2016 if (!match
&& ic
== c
) {
2020 } else if (IS_BIDI_MARK(ic
)) {
2021 pos
++; // just skip over this input text
2032 UBool match
= FALSE
;
2034 affixSet
= fStaticSets
->fDashEquivalents
;
2036 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2037 pos
= skipUWhiteSpaceAndMarks(input
, pos
);
2038 UChar32 ic
= input
.char32At(pos
);
2040 if (affixSet
->contains(ic
)) {
2041 pos
+= U16_LENGTH(ic
);
2042 pos
= skipBidiMarks(input
, pos
);
2047 for (int32_t i
= 0; i
< affixLength
; )
2049 //i = skipRuleWhiteSpace(trimmedAffix, i);
2050 i
= skipUWhiteSpace(trimmedAffix
, i
);
2051 pos
= skipUWhiteSpaceAndMarks(input
, pos
);
2053 if (i
>= affixLength
|| pos
>= inputLength
) {
2057 UChar32 c
= trimmedAffix
.char32At(i
);
2058 UChar32 ic
= input
.char32At(pos
);
2060 if (!equalWithSignCompatibility(ic
, c
)) {
2066 pos
+= U16_LENGTH(ic
);
2067 pos
= skipBidiMarks(input
, pos
);
2070 if (affixLength
> 0 && ! match
) {
2078 * Skip over a run of zero or more Pattern_White_Space characters at
2081 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2082 const UChar
* s
= text
.getBuffer();
2083 return (int32_t)(PatternProps::skipWhiteSpace(s
+ pos
, text
.length() - pos
) - s
);
2087 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2090 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2091 while (pos
< text
.length()) {
2092 UChar32 c
= text
.char32At(pos
);
2093 if (!u_isUWhiteSpace(c
)) {
2096 pos
+= U16_LENGTH(c
);
2102 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos
2105 int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString
& text
, int32_t pos
) {
2106 while (pos
< text
.length()) {
2107 UChar32 c
= text
.char32At(pos
);
2108 if (!u_isUWhiteSpace(c
) && !IS_BIDI_MARK(c
)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM
2111 pos
+= U16_LENGTH(c
);
2117 * Skip over a run of zero or more bidi marks at pos in text.
2119 int32_t DecimalFormat::skipBidiMarks(const UnicodeString
& text
, int32_t pos
) {
2120 while (pos
< text
.length()) {
2121 UChar c
= text
.charAt(pos
);
2122 if (!IS_BIDI_MARK(c
)) {
2131 * Return the length matched by the given affix, or -1 if none.
2132 * @param affixPat pattern string
2133 * @param input input text
2134 * @param pos offset into input at which to begin matching
2135 * @param type the currency type to parse against, LONG_NAME only or not.
2136 * @param currency return value for parsed currency, for generic
2137 * currency parsing mode, or null for normal parsing. In generic
2138 * currency parsing mode, any currency is parsed, not just the
2139 * currency that this formatter is set to.
2140 * @return length of input that matches, or -1 if match failure
2142 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
2143 const UnicodeString
& text
,
2146 UChar
* currency
) const
2148 int32_t start
= pos
;
2149 U_ASSERT(currency
!= NULL
|| fImpl
->fMonetary
);
2152 i
<affixPat
.length() && pos
>= 0; ) {
2153 UChar32 c
= affixPat
.char32At(i
);
2157 U_ASSERT(i
<= affixPat
.length());
2158 c
= affixPat
.char32At(i
);
2161 const UnicodeString
* affix
= NULL
;
2164 case kCurrencySign
: {
2165 // since the currency names in choice format is saved
2166 // the same way as other currency names,
2167 // do not need to do currency choice parsing here.
2168 // the general currency parsing parse against all names,
2169 // including names in choice format.
2170 UBool intl
= i
<affixPat
.length() &&
2171 affixPat
.char32At(i
) == kCurrencySign
;
2175 UBool plural
= i
<affixPat
.length() &&
2176 affixPat
.char32At(i
) == kCurrencySign
;
2181 // Parse generic currency -- anything for which we
2182 // have a display name, or any 3-letter ISO code.
2183 // Try to parse display name for our locale; first
2184 // determine our locale.
2185 const char* loc
= fCurrencyPluralInfo
->getLocale().getName();
2186 ParsePosition
ppos(pos
);
2188 UErrorCode ec
= U_ZERO_ERROR
;
2189 // Delegate parse of display name => ISO code to Currency
2190 int32_t partialMatchLen
= 0; // to match ICU 62 version of the following
2191 uprv_parseCurrency(loc
, text
, ppos
, type
, &partialMatchLen
, curr
, ec
);
2193 // If parse succeeds, populate currency[0]
2194 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
2196 u_strcpy(currency
, curr
);
2198 // The formatter is currency-style but the client has not requested
2199 // the value of the parsed currency. In this case, if that value does
2200 // not match the formatter's current value, then the parse fails.
2201 UChar effectiveCurr
[4];
2202 getEffectiveCurrency(effectiveCurr
, ec
);
2203 if ( U_FAILURE(ec
) || u_strncmp(curr
,effectiveCurr
,4) != 0 ) {
2208 pos
= ppos
.getIndex();
2209 } else if (!isLenient()){
2214 case kPatternPercent
:
2215 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
2217 case kPatternPerMill
:
2218 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
2221 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2224 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2227 // fall through to affix!=0 test, which will fail
2231 if (affix
!= NULL
) {
2232 pos
= match(text
, pos
, *affix
);
2237 pos
= match(text
, pos
, c
);
2238 if (PatternProps::isWhiteSpace(c
)) {
2239 i
= skipPatternWhiteSpace(affixPat
, i
);
2246 * Match a single character at text[pos] and return the index of the
2247 * next character upon success. Return -1 on failure. If
2248 * ch is a Pattern_White_Space then match a run of white space in text.
2250 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
2251 if (PatternProps::isWhiteSpace(ch
)) {
2252 // Advance over run of white space in input text
2253 // Must see at least one white space char in input
2255 pos
= skipPatternWhiteSpace(text
, pos
);
2261 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
2262 (pos
+ U16_LENGTH(ch
)) : -1;
2266 * Match a string at text[pos] and return the index of the next
2267 * character upon success. Return -1 on failure. Match a run of
2268 * white space in str with a run of white space in text.
2270 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
2271 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
2272 UChar32 ch
= str
.char32At(i
);
2273 i
+= U16_LENGTH(ch
);
2274 if (PatternProps::isWhiteSpace(ch
)) {
2275 i
= skipPatternWhiteSpace(str
, i
);
2277 pos
= match(text
, pos
, ch
);
2282 UBool
DecimalFormat::matchSymbol(const UnicodeString
&text
, int32_t position
, int32_t length
, const UnicodeString
&symbol
,
2283 UnicodeSet
*sset
, UChar32 schar
)
2286 return sset
->contains(schar
);
2289 return text
.compare(position
, length
, symbol
) == 0;
2292 UBool
DecimalFormat::matchDecimal(UChar32 symbolChar
,
2293 UBool sawDecimal
, UChar32 sawDecimalChar
,
2294 const UnicodeSet
*sset
, UChar32 schar
) {
2296 return schar
==sawDecimalChar
;
2297 } else if(schar
==symbolChar
) {
2299 } else if(sset
!=NULL
) {
2300 return sset
->contains(schar
);
2306 UBool
DecimalFormat::matchGrouping(UChar32 groupingChar
,
2307 UBool sawGrouping
, UChar32 sawGroupingChar
,
2308 const UnicodeSet
*sset
,
2309 UChar32
/*decimalChar*/, const UnicodeSet
*decimalSet
,
2312 return schar
==sawGroupingChar
; // previously found
2313 } else if(schar
==groupingChar
) {
2314 return TRUE
; // char from symbols
2315 } else if(sset
!=NULL
) {
2316 return sset
->contains(schar
) && // in groupingSet but...
2317 ((decimalSet
==NULL
) || !decimalSet
->contains(schar
)); // Exclude decimalSet from groupingSet
2325 //------------------------------------------------------------------------------
2326 // Gets the pointer to the localized decimal format symbols
2328 const DecimalFormatSymbols
*
2329 DecimalFormat::getDecimalFormatSymbols() const
2331 return &fImpl
->getDecimalFormatSymbols();
2334 //------------------------------------------------------------------------------
2335 // De-owning the current localized symbols and adopt the new symbols.
2338 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
2340 if (symbolsToAdopt
== NULL
) {
2341 return; // do not allow caller to set fSymbols to NULL
2343 fImpl
->adoptDecimalFormatSymbols(symbolsToAdopt
);
2345 //------------------------------------------------------------------------------
2346 // Setting the symbols is equlivalent to adopting a newly created localized
2350 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
2352 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
2356 const CurrencyPluralInfo
*
2357 DecimalFormat::getCurrencyPluralInfo(void) const
2359 return fCurrencyPluralInfo
;
2364 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo
* toAdopt
)
2366 if (toAdopt
!= NULL
) {
2367 delete fCurrencyPluralInfo
;
2368 fCurrencyPluralInfo
= toAdopt
;
2369 // re-set currency affix patterns and currency affixes.
2370 if (fImpl
->fMonetary
) {
2371 UErrorCode status
= U_ZERO_ERROR
;
2372 if (fAffixPatternsForCurrency
) {
2373 deleteHashForAffixPattern();
2375 setupCurrencyAffixPatterns(status
);
2381 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo
& info
)
2383 adoptCurrencyPluralInfo(info
.clone());
2387 //------------------------------------------------------------------------------
2388 // Gets the positive prefix of the number pattern.
2391 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
2393 return fImpl
->getPositivePrefix(result
);
2396 //------------------------------------------------------------------------------
2397 // Sets the positive prefix of the number pattern.
2400 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
2402 fImpl
->setPositivePrefix(newValue
);
2405 //------------------------------------------------------------------------------
2406 // Gets the negative prefix of the number pattern.
2409 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
2411 return fImpl
->getNegativePrefix(result
);
2414 //------------------------------------------------------------------------------
2415 // Gets the negative prefix of the number pattern.
2418 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
2420 fImpl
->setNegativePrefix(newValue
);
2423 //------------------------------------------------------------------------------
2424 // Gets the positive suffix of the number pattern.
2427 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
2429 return fImpl
->getPositiveSuffix(result
);
2432 //------------------------------------------------------------------------------
2433 // Sets the positive suffix of the number pattern.
2436 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
2438 fImpl
->setPositiveSuffix(newValue
);
2441 //------------------------------------------------------------------------------
2442 // Gets the negative suffix of the number pattern.
2445 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
2447 return fImpl
->getNegativeSuffix(result
);
2450 //------------------------------------------------------------------------------
2451 // Sets the negative suffix of the number pattern.
2454 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
2456 fImpl
->setNegativeSuffix(newValue
);
2459 //------------------------------------------------------------------------------
2460 // Gets the multiplier of the number pattern.
2461 // Multipliers are stored as decimal numbers (DigitLists) because that
2462 // is the most convenient for muliplying or dividing the numbers to be formatted.
2463 // A NULL multiplier implies one, and the scaling operations are skipped.
2466 DecimalFormat::getMultiplier() const
2468 return fImpl
->getMultiplier();
2471 //------------------------------------------------------------------------------
2472 // Sets the multiplier of the number pattern.
2474 DecimalFormat::setMultiplier(int32_t newValue
)
2476 fImpl
->setMultiplier(newValue
);
2480 * Get the rounding increment.
2481 * @return A positive rounding increment, or 0.0 if rounding
2483 * @see #setRoundingIncrement
2484 * @see #getRoundingMode
2485 * @see #setRoundingMode
2487 double DecimalFormat::getRoundingIncrement() const {
2488 return fImpl
->getRoundingIncrement();
2492 * Set the rounding increment. This method also controls whether
2493 * rounding is enabled.
2494 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2495 * Negative increments are equivalent to 0.0.
2496 * @see #getRoundingIncrement
2497 * @see #getRoundingMode
2498 * @see #setRoundingMode
2500 void DecimalFormat::setRoundingIncrement(double newValue
) {
2501 fImpl
->setRoundingIncrement(newValue
);
2505 * Get the rounding mode.
2506 * @return A rounding mode
2507 * @see #setRoundingIncrement
2508 * @see #getRoundingIncrement
2509 * @see #setRoundingMode
2511 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
2512 return fImpl
->getRoundingMode();
2516 * Set the rounding mode. This has no effect unless the rounding
2517 * increment is greater than zero.
2518 * @param roundingMode A rounding mode
2519 * @see #setRoundingIncrement
2520 * @see #getRoundingIncrement
2521 * @see #getRoundingMode
2523 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
2524 fImpl
->setRoundingMode(roundingMode
);
2528 * Get the width to which the output of <code>format()</code> is padded.
2529 * @return the format width, or zero if no padding is in effect
2530 * @see #setFormatWidth
2531 * @see #getPadCharacter
2532 * @see #setPadCharacter
2533 * @see #getPadPosition
2534 * @see #setPadPosition
2536 int32_t DecimalFormat::getFormatWidth() const {
2537 return fImpl
->getFormatWidth();
2541 * Set the width to which the output of <code>format()</code> is padded.
2542 * This method also controls whether padding is enabled.
2543 * @param width the width to which to pad the result of
2544 * <code>format()</code>, or zero to disable padding. A negative
2545 * width is equivalent to 0.
2546 * @see #getFormatWidth
2547 * @see #getPadCharacter
2548 * @see #setPadCharacter
2549 * @see #getPadPosition
2550 * @see #setPadPosition
2552 void DecimalFormat::setFormatWidth(int32_t width
) {
2553 int32_t formatWidth
= (width
> 0) ? width
: 0;
2554 fImpl
->setFormatWidth(formatWidth
);
2557 UnicodeString
DecimalFormat::getPadCharacterString() const {
2558 return UnicodeString(fImpl
->getPadCharacter());
2561 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
2563 if (padChar
.length() > 0) {
2564 pad
= padChar
.char32At(0);
2569 fImpl
->setPadCharacter(pad
);
2572 static DecimalFormat::EPadPosition
fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos
) {
2574 case DigitAffixesAndPadding::kPadBeforePrefix
:
2575 return DecimalFormat::kPadBeforePrefix
;
2576 case DigitAffixesAndPadding::kPadAfterPrefix
:
2577 return DecimalFormat::kPadAfterPrefix
;
2578 case DigitAffixesAndPadding::kPadBeforeSuffix
:
2579 return DecimalFormat::kPadBeforeSuffix
;
2580 case DigitAffixesAndPadding::kPadAfterSuffix
:
2581 return DecimalFormat::kPadAfterSuffix
;
2586 return DecimalFormat::kPadBeforePrefix
;
2590 * Get the position at which padding will take place. This is the location
2591 * at which padding will be inserted if the result of <code>format()</code>
2592 * is shorter than the format width.
2593 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2594 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2595 * <code>kPadAfterSuffix</code>.
2596 * @see #setFormatWidth
2597 * @see #getFormatWidth
2598 * @see #setPadCharacter
2599 * @see #getPadCharacter
2600 * @see #setPadPosition
2601 * @see #kPadBeforePrefix
2602 * @see #kPadAfterPrefix
2603 * @see #kPadBeforeSuffix
2604 * @see #kPadAfterSuffix
2606 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
2607 return fromPadPosition(fImpl
->getPadPosition());
2610 static DigitAffixesAndPadding::EPadPosition
toPadPosition(DecimalFormat::EPadPosition padPos
) {
2612 case DecimalFormat::kPadBeforePrefix
:
2613 return DigitAffixesAndPadding::kPadBeforePrefix
;
2614 case DecimalFormat::kPadAfterPrefix
:
2615 return DigitAffixesAndPadding::kPadAfterPrefix
;
2616 case DecimalFormat::kPadBeforeSuffix
:
2617 return DigitAffixesAndPadding::kPadBeforeSuffix
;
2618 case DecimalFormat::kPadAfterSuffix
:
2619 return DigitAffixesAndPadding::kPadAfterSuffix
;
2624 return DigitAffixesAndPadding::kPadBeforePrefix
;
2628 * <strong><font face=helvetica color=red>NEW</font></strong>
2629 * Set the position at which padding will take place. This is the location
2630 * at which padding will be inserted if the result of <code>format()</code>
2631 * is shorter than the format width. This has no effect unless padding is
2633 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2634 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2635 * <code>kPadAfterSuffix</code>.
2636 * @see #setFormatWidth
2637 * @see #getFormatWidth
2638 * @see #setPadCharacter
2639 * @see #getPadCharacter
2640 * @see #getPadPosition
2641 * @see #kPadBeforePrefix
2642 * @see #kPadAfterPrefix
2643 * @see #kPadBeforeSuffix
2644 * @see #kPadAfterSuffix
2646 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
2647 fImpl
->setPadPosition(toPadPosition(padPos
));
2651 * Return whether or not scientific notation is used.
2652 * @return TRUE if this object formats and parses scientific notation
2653 * @see #setScientificNotation
2654 * @see #getMinimumExponentDigits
2655 * @see #setMinimumExponentDigits
2656 * @see #isExponentSignAlwaysShown
2657 * @see #setExponentSignAlwaysShown
2659 UBool
DecimalFormat::isScientificNotation() const {
2660 return fImpl
->isScientificNotation();
2664 * Set whether or not scientific notation is used.
2665 * @param useScientific TRUE if this object formats and parses scientific
2667 * @see #isScientificNotation
2668 * @see #getMinimumExponentDigits
2669 * @see #setMinimumExponentDigits
2670 * @see #isExponentSignAlwaysShown
2671 * @see #setExponentSignAlwaysShown
2673 void DecimalFormat::setScientificNotation(UBool useScientific
) {
2674 fImpl
->setScientificNotation(useScientific
);
2678 * Return the minimum exponent digits that will be shown.
2679 * @return the minimum exponent digits that will be shown
2680 * @see #setScientificNotation
2681 * @see #isScientificNotation
2682 * @see #setMinimumExponentDigits
2683 * @see #isExponentSignAlwaysShown
2684 * @see #setExponentSignAlwaysShown
2686 int8_t DecimalFormat::getMinimumExponentDigits() const {
2687 return fImpl
->getMinimumExponentDigits();
2691 * Set the minimum exponent digits that will be shown. This has no
2692 * effect unless scientific notation is in use.
2693 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2694 * that will be shown. Values less than 1 will be treated as 1.
2695 * @see #setScientificNotation
2696 * @see #isScientificNotation
2697 * @see #getMinimumExponentDigits
2698 * @see #isExponentSignAlwaysShown
2699 * @see #setExponentSignAlwaysShown
2701 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
2702 int32_t minExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
2703 fImpl
->setMinimumExponentDigits(minExponentDigits
);
2707 * Return whether the exponent sign is always shown.
2708 * @return TRUE if the exponent is always prefixed with either the
2709 * localized minus sign or the localized plus sign, false if only negative
2710 * exponents are prefixed with the localized minus sign.
2711 * @see #setScientificNotation
2712 * @see #isScientificNotation
2713 * @see #setMinimumExponentDigits
2714 * @see #getMinimumExponentDigits
2715 * @see #setExponentSignAlwaysShown
2717 UBool
DecimalFormat::isExponentSignAlwaysShown() const {
2718 return fImpl
->isExponentSignAlwaysShown();
2722 * Set whether the exponent sign is always shown. This has no effect
2723 * unless scientific notation is in use.
2724 * @param expSignAlways TRUE if the exponent is always prefixed with either
2725 * the localized minus sign or the localized plus sign, false if only
2726 * negative exponents are prefixed with the localized minus sign.
2727 * @see #setScientificNotation
2728 * @see #isScientificNotation
2729 * @see #setMinimumExponentDigits
2730 * @see #getMinimumExponentDigits
2731 * @see #isExponentSignAlwaysShown
2733 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
2734 fImpl
->setExponentSignAlwaysShown(expSignAlways
);
2737 //------------------------------------------------------------------------------
2738 // Gets the grouping size of the number pattern. For example, thousand or 10
2739 // thousand groupings.
2742 DecimalFormat::getGroupingSize() const
2744 return fImpl
->getGroupingSize();
2747 //------------------------------------------------------------------------------
2748 // Gets the grouping size of the number pattern.
2751 DecimalFormat::setGroupingSize(int32_t newValue
)
2753 fImpl
->setGroupingSize(newValue
);
2756 //------------------------------------------------------------------------------
2759 DecimalFormat::getSecondaryGroupingSize() const
2761 return fImpl
->getSecondaryGroupingSize();
2764 //------------------------------------------------------------------------------
2767 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
2769 fImpl
->setSecondaryGroupingSize(newValue
);
2772 //------------------------------------------------------------------------------
2775 DecimalFormat::getMinimumGroupingDigits() const
2777 return fImpl
->getMinimumGroupingDigits();
2780 //------------------------------------------------------------------------------
2783 DecimalFormat::setMinimumGroupingDigits(int32_t newValue
)
2785 fImpl
->setMinimumGroupingDigits(newValue
);
2788 //------------------------------------------------------------------------------
2789 // Checks if to show the decimal separator.
2792 DecimalFormat::isDecimalSeparatorAlwaysShown() const
2794 return fImpl
->isDecimalSeparatorAlwaysShown();
2797 //------------------------------------------------------------------------------
2798 // Sets to always show the decimal separator.
2801 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
2803 fImpl
->setDecimalSeparatorAlwaysShown(newValue
);
2806 //------------------------------------------------------------------------------
2807 // Checks if decimal point pattern match is required
2809 DecimalFormat::isDecimalPatternMatchRequired(void) const
2811 return static_cast<UBool
>(fBoolFlags
.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED
));
2814 //------------------------------------------------------------------------------
2815 // Checks if decimal point pattern match is required
2818 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue
)
2820 fBoolFlags
.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED
, newValue
);
2824 //------------------------------------------------------------------------------
2825 // Emits the pattern of this DecimalFormat instance.
2828 DecimalFormat::toPattern(UnicodeString
& result
) const
2830 return fImpl
->toPattern(result
);
2833 //------------------------------------------------------------------------------
2834 // Emits the localized pattern this DecimalFormat instance.
2837 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
2839 // toLocalizedPattern is deprecated, so we just make it the same as
2841 return fImpl
->toPattern(result
);
2844 //------------------------------------------------------------------------------
2847 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
2849 if (pattern
.indexOf(kCurrencySign
) != -1) {
2850 handleCurrencySignInPattern(status
);
2852 fImpl
->applyPattern(pattern
, status
);
2855 //------------------------------------------------------------------------------
2858 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
2859 UParseError
& parseError
,
2862 if (pattern
.indexOf(kCurrencySign
) != -1) {
2863 handleCurrencySignInPattern(status
);
2865 fImpl
->applyPattern(pattern
, parseError
, status
);
2867 //------------------------------------------------------------------------------
2870 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
2872 if (U_SUCCESS(status
)) {
2873 if (pattern
.indexOf(kCurrencySign
) != -1) {
2874 handleCurrencySignInPattern(status
);
2876 fImpl
->applyLocalizedPattern(pattern
, status
);
2880 //------------------------------------------------------------------------------
2883 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
2884 UParseError
& parseError
,
2887 if (pattern
.indexOf(kCurrencySign
) != -1) {
2888 handleCurrencySignInPattern(status
);
2890 fImpl
->applyLocalizedPattern(pattern
, parseError
, status
);
2893 //------------------------------------------------------------------------------
2896 * Sets the maximum number of digits allowed in the integer portion of a
2898 * @see NumberFormat#setMaximumIntegerDigits
2900 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
2901 newValue
= _min(newValue
, gDefaultMaxIntegerDigits
);
2902 NumberFormat::setMaximumIntegerDigits(newValue
);
2903 fImpl
->updatePrecision();
2907 * Sets the minimum number of digits allowed in the integer portion of a
2908 * number. This override limits the integer digit count to 309.
2909 * @see NumberFormat#setMinimumIntegerDigits
2911 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
2912 newValue
= _min(newValue
, kDoubleIntegerDigits
);
2913 NumberFormat::setMinimumIntegerDigits(newValue
);
2914 fImpl
->updatePrecision();
2918 * Sets the maximum number of digits allowed in the fraction portion of a
2919 * number. This override limits the fraction digit count to 340.
2920 * @see NumberFormat#setMaximumFractionDigits
2922 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
2923 newValue
= _min(newValue
, kDoubleFractionDigits
);
2924 NumberFormat::setMaximumFractionDigits(newValue
);
2925 fImpl
->updatePrecision();
2929 * Sets the minimum number of digits allowed in the fraction portion of a
2930 * number. This override limits the fraction digit count to 340.
2931 * @see NumberFormat#setMinimumFractionDigits
2933 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
2934 newValue
= _min(newValue
, kDoubleFractionDigits
);
2935 NumberFormat::setMinimumFractionDigits(newValue
);
2936 fImpl
->updatePrecision();
2939 int32_t DecimalFormat::getMinimumSignificantDigits() const {
2940 return fImpl
->getMinimumSignificantDigits();
2943 int32_t DecimalFormat::getMaximumSignificantDigits() const {
2944 return fImpl
->getMaximumSignificantDigits();
2947 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
2951 // pin max sig dig to >= min
2952 int32_t max
= _max(fImpl
->fMaxSigDigits
, min
);
2953 fImpl
->setMinMaxSignificantDigits(min
, max
);
2956 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
2960 // pin min sig dig to 1..max
2961 U_ASSERT(fImpl
->fMinSigDigits
>= 1);
2962 int32_t min
= _min(fImpl
->fMinSigDigits
, max
);
2963 fImpl
->setMinMaxSignificantDigits(min
, max
);
2966 UBool
DecimalFormat::areSignificantDigitsUsed() const {
2967 return fImpl
->areSignificantDigitsUsed();
2970 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
2971 fImpl
->setSignificantDigitsUsed(useSignificantDigits
);
2974 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
2975 // set the currency before compute affixes to get the right currency names
2976 NumberFormat::setCurrency(theCurrency
, ec
);
2977 fImpl
->updateCurrency(ec
);
2980 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext
, UErrorCode
* ec
){
2981 if (U_FAILURE(*ec
)) {
2984 fImpl
->setCurrencyUsage(newContext
, *ec
);
2987 UCurrencyUsage
DecimalFormat::getCurrencyUsage() const {
2988 return fImpl
->getCurrencyUsage();
2991 // Deprecated variant with no UErrorCode parameter
2992 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
2993 UErrorCode ec
= U_ZERO_ERROR
;
2994 setCurrency(theCurrency
, ec
);
2997 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
2998 if (fImpl
->fSymbols
== NULL
) {
2999 ec
= U_MEMORY_ALLOCATION_ERROR
;
3003 const UChar
* c
= getCurrency();
3005 const UnicodeString
&intl
=
3006 fImpl
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
3007 c
= intl
.getBuffer(); // ok for intl to go out of scope
3009 u_strncpy(result
, c
, 3);
3014 DecimalFormat::initHashForAffixPattern(UErrorCode
& status
) {
3015 if ( U_FAILURE(status
) ) {
3019 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
3020 status
= U_MEMORY_ALLOCATION_ERROR
;
3023 if ( U_FAILURE(status
) ) {
3027 hTable
->setValueComparator(decimfmtAffixPatternValueComparator
);
3032 DecimalFormat::deleteHashForAffixPattern()
3034 if ( fAffixPatternsForCurrency
== NULL
) {
3037 int32_t pos
= UHASH_FIRST
;
3038 const UHashElement
* element
= NULL
;
3039 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
3040 const UHashTok valueTok
= element
->value
;
3041 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
3044 delete fAffixPatternsForCurrency
;
3045 fAffixPatternsForCurrency
= NULL
;
3050 DecimalFormat::copyHashForAffixPattern(const Hashtable
* source
,
3052 UErrorCode
& status
) {
3053 if ( U_FAILURE(status
) ) {
3056 int32_t pos
= UHASH_FIRST
;
3057 const UHashElement
* element
= NULL
;
3059 while ( (element
= source
->nextElement(pos
)) != NULL
) {
3060 const UHashTok keyTok
= element
->key
;
3061 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
3062 const UHashTok valueTok
= element
->value
;
3063 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
3064 AffixPatternsForCurrency
* copy
= new AffixPatternsForCurrency(
3065 value
->negPrefixPatternForCurrency
,
3066 value
->negSuffixPatternForCurrency
,
3067 value
->posPrefixPatternForCurrency
,
3068 value
->posSuffixPatternForCurrency
,
3069 value
->patternType
);
3070 target
->put(UnicodeString(*key
), copy
, status
);
3071 if ( U_FAILURE(status
) ) {
3079 DecimalFormat::setGroupingUsed(UBool newValue
) {
3080 NumberFormat::setGroupingUsed(newValue
);
3081 fImpl
->updateGrouping();
3085 DecimalFormat::setParseIntegerOnly(UBool newValue
) {
3086 NumberFormat::setParseIntegerOnly(newValue
);
3090 DecimalFormat::setContext(UDisplayContext value
, UErrorCode
& status
) {
3091 NumberFormat::setContext(value
, status
);
3094 DecimalFormat
& DecimalFormat::setAttribute( UNumberFormatAttribute attr
,
3096 UErrorCode
&status
) {
3097 if(U_FAILURE(status
)) return *this;
3100 case UNUM_LENIENT_PARSE
:
3101 setLenient(newValue
!=0);
3104 case UNUM_PARSE_INT_ONLY
:
3105 setParseIntegerOnly(newValue
!=0);
3108 case UNUM_GROUPING_USED
:
3109 setGroupingUsed(newValue
!=0);
3112 case UNUM_DECIMAL_ALWAYS_SHOWN
:
3113 setDecimalSeparatorAlwaysShown(newValue
!=0);
3116 case UNUM_MAX_INTEGER_DIGITS
:
3117 setMaximumIntegerDigits(newValue
);
3120 case UNUM_MIN_INTEGER_DIGITS
:
3121 setMinimumIntegerDigits(newValue
);
3124 case UNUM_INTEGER_DIGITS
:
3125 setMinimumIntegerDigits(newValue
);
3126 setMaximumIntegerDigits(newValue
);
3129 case UNUM_MAX_FRACTION_DIGITS
:
3130 setMaximumFractionDigits(newValue
);
3133 case UNUM_MIN_FRACTION_DIGITS
:
3134 setMinimumFractionDigits(newValue
);
3137 case UNUM_FRACTION_DIGITS
:
3138 setMinimumFractionDigits(newValue
);
3139 setMaximumFractionDigits(newValue
);
3142 case UNUM_SIGNIFICANT_DIGITS_USED
:
3143 setSignificantDigitsUsed(newValue
!=0);
3146 case UNUM_MAX_SIGNIFICANT_DIGITS
:
3147 setMaximumSignificantDigits(newValue
);
3150 case UNUM_MIN_SIGNIFICANT_DIGITS
:
3151 setMinimumSignificantDigits(newValue
);
3154 case UNUM_MULTIPLIER
:
3155 setMultiplier(newValue
);
3158 case UNUM_GROUPING_SIZE
:
3159 setGroupingSize(newValue
);
3162 case UNUM_ROUNDING_MODE
:
3163 setRoundingMode((DecimalFormat::ERoundingMode
)newValue
);
3166 case UNUM_FORMAT_WIDTH
:
3167 setFormatWidth(newValue
);
3170 case UNUM_PADDING_POSITION
:
3171 /** The position at which padding will take place. */
3172 setPadPosition((DecimalFormat::EPadPosition
)newValue
);
3175 case UNUM_SECONDARY_GROUPING_SIZE
:
3176 setSecondaryGroupingSize(newValue
);
3179 #if UCONFIG_HAVE_PARSEALLINPUT
3180 case UNUM_PARSE_ALL_INPUT
:
3181 setParseAllInput((UNumberFormatAttributeValue
)newValue
);
3185 /* These are stored in fBoolFlags */
3186 case UNUM_PARSE_NO_EXPONENT
:
3187 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
3188 case UNUM_PARSE_DECIMAL_MARK_REQUIRED
:
3189 if(!fBoolFlags
.isValidValue(newValue
)) {
3190 status
= U_ILLEGAL_ARGUMENT_ERROR
;
3192 if (attr
== UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
) {
3193 fImpl
->setFailIfMoreThanMaxDigits((UBool
) newValue
);
3195 fBoolFlags
.set(attr
, newValue
);
3200 fImpl
->setScale(newValue
);
3203 case UNUM_CURRENCY_USAGE
:
3204 setCurrencyUsage((UCurrencyUsage
)newValue
, &status
);
3207 case UNUM_MINIMUM_GROUPING_DIGITS
:
3208 setMinimumGroupingDigits(newValue
);
3211 case UNUM_FORMAT_WITH_FULL_PRECISION
: // Apple-specific
3212 fImpl
->setFormatFullPrecision(newValue
);
3216 status
= U_UNSUPPORTED_ERROR
;
3222 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr
,
3223 UErrorCode
&status
) const {
3224 if(U_FAILURE(status
)) return -1;
3226 case UNUM_LENIENT_PARSE
:
3229 case UNUM_PARSE_INT_ONLY
:
3230 return isParseIntegerOnly();
3232 case UNUM_GROUPING_USED
:
3233 return isGroupingUsed();
3235 case UNUM_DECIMAL_ALWAYS_SHOWN
:
3236 return isDecimalSeparatorAlwaysShown();
3238 case UNUM_MAX_INTEGER_DIGITS
:
3239 return getMaximumIntegerDigits();
3241 case UNUM_MIN_INTEGER_DIGITS
:
3242 return getMinimumIntegerDigits();
3244 case UNUM_INTEGER_DIGITS
:
3245 // TBD: what should this return?
3246 return getMinimumIntegerDigits();
3248 case UNUM_MAX_FRACTION_DIGITS
:
3249 return getMaximumFractionDigits();
3251 case UNUM_MIN_FRACTION_DIGITS
:
3252 return getMinimumFractionDigits();
3254 case UNUM_FRACTION_DIGITS
:
3255 // TBD: what should this return?
3256 return getMinimumFractionDigits();
3258 case UNUM_SIGNIFICANT_DIGITS_USED
:
3259 return areSignificantDigitsUsed();
3261 case UNUM_MAX_SIGNIFICANT_DIGITS
:
3262 return getMaximumSignificantDigits();
3264 case UNUM_MIN_SIGNIFICANT_DIGITS
:
3265 return getMinimumSignificantDigits();
3267 case UNUM_MULTIPLIER
:
3268 return getMultiplier();
3270 case UNUM_GROUPING_SIZE
:
3271 return getGroupingSize();
3273 case UNUM_ROUNDING_MODE
:
3274 return getRoundingMode();
3276 case UNUM_FORMAT_WIDTH
:
3277 return getFormatWidth();
3279 case UNUM_PADDING_POSITION
:
3280 return getPadPosition();
3282 case UNUM_SECONDARY_GROUPING_SIZE
:
3283 return getSecondaryGroupingSize();
3285 /* These are stored in fBoolFlags */
3286 case UNUM_PARSE_NO_EXPONENT
:
3287 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
3288 case UNUM_PARSE_DECIMAL_MARK_REQUIRED
:
3289 return fBoolFlags
.get(attr
);
3292 return fImpl
->fScale
;
3294 case UNUM_CURRENCY_USAGE
:
3295 return fImpl
->getCurrencyUsage();
3297 case UNUM_MINIMUM_GROUPING_DIGITS
:
3298 return getMinimumGroupingDigits();
3300 case UNUM_FORMAT_WITH_FULL_PRECISION
: // Apple-specific
3301 return fImpl
->getFormatFullPrecision();
3304 status
= U_UNSUPPORTED_ERROR
;
3308 return -1; /* undefined */
3311 #if UCONFIG_HAVE_PARSEALLINPUT
3312 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value
) {
3313 fParseAllInput
= value
;
3319 #endif /* #if !UCONFIG_NO_FORMATTING */