2 *******************************************************************************
3 * Copyright (C) 1997-2015, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
9 * Modification History:
11 * Date Name Description
12 * 02/19/97 aliu Converted from java.
13 * 03/20/97 clhuang Implemented with new APIs.
14 * 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it.
15 * 04/3/97 aliu Rewrote parsing and formatting completely, and
16 * cleaned up and debugged. Actually works now.
17 * Implemented NAN and INF handling, for both parsing
18 * and formatting. Extensive testing & debugging.
19 * 04/10/97 aliu Modified to compile on AIX.
20 * 04/16/97 aliu Rewrote to use DigitList, which has been resurrected.
21 * Changed DigitCount to int per code review.
22 * 07/09/97 helena Made ParsePosition into a class.
23 * 08/26/97 aliu Extensive changes to applyPattern; completely
24 * rewritten from the Java.
25 * 09/09/97 aliu Ported over support for exponential formats.
26 * 07/20/98 stephen JDK 1.2 sync up.
27 * Various instances of '0' replaced with 'NULL'
28 * Check for grouping size in subFormat()
29 * Brought subParse() in line with Java 1.2
30 * Added method appendAffix()
31 * 08/24/1998 srl Removed Mutex calls. This is not a thread safe class!
32 * 02/22/99 stephen Removed character literals for EBCDIC safety
33 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
34 * 06/28/99 stephen Fixed bugs in toPattern().
35 * 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad,
37 ********************************************************************************
40 #include "unicode/utypes.h"
42 #if !UCONFIG_NO_FORMATTING
44 #include "unicode/uniset.h"
45 #include "unicode/currpinf.h"
46 #include "unicode/plurrule.h"
47 #include "unicode/utf16.h"
48 #include "unicode/numsys.h"
49 #include "unicode/localpointer.h"
53 #include "patternprops.h"
58 #include "plurrule_impl.h"
59 #include "decimalformatpattern.h"
60 #include "fmtableimp.h"
61 #include "decimfmtimpl.h"
62 #include "visibledigits.h"
65 * On certain platforms, round is a macro defined in math.h
66 * This undefine is to avoid conflict between the macro and
67 * the function defined below.
78 static void _debugout(const char *f
, int l
, const UnicodeString
& s
) {
80 s
.extract((int32_t) 0, s
.length(), buf
, "utf-8");
81 printf("%s:%d: %s\n", f
,l
, buf
);
83 #define debugout(x) _debugout(__FILE__,__LINE__,x)
84 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x);
85 static const UnicodeString
dbg_null("<NULL>","");
86 #define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null))
93 /* For currency parsing purose,
94 * Need to remember all prefix patterns and suffix patterns of
95 * every currency format pattern,
96 * including the pattern of default currecny style
97 * and plural currency style. And the patterns are set through applyPattern.
99 struct AffixPatternsForCurrency
: public UMemory
{
100 // negative prefix pattern
101 UnicodeString negPrefixPatternForCurrency
;
102 // negative suffix pattern
103 UnicodeString negSuffixPatternForCurrency
;
104 // positive prefix pattern
105 UnicodeString posPrefixPatternForCurrency
;
106 // positive suffix pattern
107 UnicodeString posSuffixPatternForCurrency
;
110 AffixPatternsForCurrency(const UnicodeString
& negPrefix
,
111 const UnicodeString
& negSuffix
,
112 const UnicodeString
& posPrefix
,
113 const UnicodeString
& posSuffix
,
115 negPrefixPatternForCurrency
= negPrefix
;
116 negSuffixPatternForCurrency
= negSuffix
;
117 posPrefixPatternForCurrency
= posPrefix
;
118 posSuffixPatternForCurrency
= posSuffix
;
123 debugout( UnicodeString("AffixPatternsForCurrency( -=\"") +
124 negPrefixPatternForCurrency
+ (UnicodeString
)"\"/\"" +
125 negSuffixPatternForCurrency
+ (UnicodeString
)"\" +=\"" +
126 posPrefixPatternForCurrency
+ (UnicodeString
)"\"/\"" +
127 posSuffixPatternForCurrency
+ (UnicodeString
)"\" )");
132 /* affix for currency formatting when the currency sign in the pattern
133 * equals to 3, such as the pattern contains 3 currency sign or
134 * the formatter style is currency plural format style.
136 struct AffixesForCurrency
: public UMemory
{
138 UnicodeString negPrefixForCurrency
;
140 UnicodeString negSuffixForCurrency
;
142 UnicodeString posPrefixForCurrency
;
144 UnicodeString posSuffixForCurrency
;
148 AffixesForCurrency(const UnicodeString
& negPrefix
,
149 const UnicodeString
& negSuffix
,
150 const UnicodeString
& posPrefix
,
151 const UnicodeString
& posSuffix
) {
152 negPrefixForCurrency
= negPrefix
;
153 negSuffixForCurrency
= negSuffix
;
154 posPrefixForCurrency
= posPrefix
;
155 posSuffixForCurrency
= posSuffix
;
159 debugout( UnicodeString("AffixesForCurrency( -=\"") +
160 negPrefixForCurrency
+ (UnicodeString
)"\"/\"" +
161 negSuffixForCurrency
+ (UnicodeString
)"\" +=\"" +
162 posPrefixForCurrency
+ (UnicodeString
)"\"/\"" +
163 posSuffixForCurrency
+ (UnicodeString
)"\" )");
173 static UBool U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
);
177 U_CALLCONV
decimfmtAffixPatternValueComparator(UHashTok val1
, UHashTok val2
) {
178 const AffixPatternsForCurrency
* affix_1
=
179 (AffixPatternsForCurrency
*)val1
.pointer
;
180 const AffixPatternsForCurrency
* affix_2
=
181 (AffixPatternsForCurrency
*)val2
.pointer
;
182 return affix_1
->negPrefixPatternForCurrency
==
183 affix_2
->negPrefixPatternForCurrency
&&
184 affix_1
->negSuffixPatternForCurrency
==
185 affix_2
->negSuffixPatternForCurrency
&&
186 affix_1
->posPrefixPatternForCurrency
==
187 affix_2
->posPrefixPatternForCurrency
&&
188 affix_1
->posSuffixPatternForCurrency
==
189 affix_2
->posSuffixPatternForCurrency
&&
190 affix_1
->patternType
== affix_2
->patternType
;
198 // *****************************************************************************
199 // class DecimalFormat
200 // *****************************************************************************
202 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat
)
204 // Constants for characters used in programmatic (unlocalized) patterns.
205 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/
206 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/
207 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/
208 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/
209 #define kPatternPerMill ((UChar)0x2030)
210 #define kPatternPercent ((UChar)0x0025) /*'%'*/
211 #define kPatternDigit ((UChar)0x0023) /*'#'*/
212 #define kPatternSeparator ((UChar)0x003B) /*';'*/
213 #define kPatternExponent ((UChar)0x0045) /*'E'*/
214 #define kPatternPlus ((UChar)0x002B) /*'+'*/
215 #define kPatternMinus ((UChar)0x002D) /*'-'*/
216 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/
217 #define kQuote ((UChar)0x0027) /*'\''*/
219 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
220 * is used in patterns and substitued with either the currency symbol,
221 * or if it is doubled, with the international currency symbol. If the
222 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
223 * replaced with the monetary decimal separator.
225 #define kCurrencySign ((UChar)0x00A4)
226 #define kDefaultPad ((UChar)0x0020) /* */
228 const int32_t DecimalFormat::kDoubleIntegerDigits
= 309;
229 const int32_t DecimalFormat::kDoubleFractionDigits
= 340;
231 const int32_t DecimalFormat::kMaxScientificIntegerDigits
= 8;
234 * These are the tags we expect to see in normal resource bundle files associated
237 const char DecimalFormat::fgNumberPatterns
[]="NumberPatterns"; // Deprecated - not used
238 static const char fgNumberElements
[]="NumberElements";
239 static const char fgLatn
[]="latn";
240 static const char fgPatterns
[]="patterns";
241 static const char fgDecimalFormat
[]="decimalFormat";
242 static const char fgCurrencyFormat
[]="currencyFormat";
244 inline int32_t _min(int32_t a
, int32_t b
) { return (a
<b
) ? a
: b
; }
245 inline int32_t _max(int32_t a
, int32_t b
) { return (a
<b
) ? b
: a
; }
247 //------------------------------------------------------------------------------
248 // Constructs a DecimalFormat instance in the default locale.
250 DecimalFormat::DecimalFormat(UErrorCode
& status
) {
252 UParseError parseError
;
253 construct(status
, parseError
);
256 //------------------------------------------------------------------------------
257 // Constructs a DecimalFormat instance with the specified number format
258 // pattern in the default locale.
260 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
261 UErrorCode
& status
) {
263 UParseError parseError
;
264 construct(status
, parseError
, &pattern
);
267 //------------------------------------------------------------------------------
268 // Constructs a DecimalFormat instance with the specified number format
269 // pattern and the number format symbols in the default locale. The
270 // created instance owns the symbols.
272 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
273 DecimalFormatSymbols
* symbolsToAdopt
,
274 UErrorCode
& status
) {
276 UParseError parseError
;
277 if (symbolsToAdopt
== NULL
)
278 status
= U_ILLEGAL_ARGUMENT_ERROR
;
279 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
282 DecimalFormat::DecimalFormat( const UnicodeString
& pattern
,
283 DecimalFormatSymbols
* symbolsToAdopt
,
284 UParseError
& parseErr
,
285 UErrorCode
& status
) {
287 if (symbolsToAdopt
== NULL
)
288 status
= U_ILLEGAL_ARGUMENT_ERROR
;
289 construct(status
,parseErr
, &pattern
, symbolsToAdopt
);
292 //------------------------------------------------------------------------------
293 // Constructs a DecimalFormat instance with the specified number format
294 // pattern and the number format symbols in the default locale. The
295 // created instance owns the clone of the symbols.
297 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
298 const DecimalFormatSymbols
& symbols
,
299 UErrorCode
& status
) {
301 UParseError parseError
;
302 construct(status
, parseError
, &pattern
, new DecimalFormatSymbols(symbols
));
305 //------------------------------------------------------------------------------
306 // Constructs a DecimalFormat instance with the specified number format
307 // pattern, the number format symbols, and the number format style.
308 // The created instance owns the clone of the symbols.
310 DecimalFormat::DecimalFormat(const UnicodeString
& pattern
,
311 DecimalFormatSymbols
* symbolsToAdopt
,
312 UNumberFormatStyle style
,
313 UErrorCode
& status
) {
316 UParseError parseError
;
317 construct(status
, parseError
, &pattern
, symbolsToAdopt
);
320 //-----------------------------------------------------------------------------
321 // Common DecimalFormat initialization.
322 // Put all fields of an uninitialized object into a known state.
323 // Common code, shared by all constructors.
324 // Can not fail. Leave the object in good enough shape that the destructor
325 // or assignment operator can run successfully.
327 DecimalFormat::init() {
329 fStyle
= UNUM_DECIMAL
;
330 fAffixPatternsForCurrency
= NULL
;
331 fCurrencyPluralInfo
= NULL
;
332 #if UCONFIG_HAVE_PARSEALLINPUT
333 fParseAllInput
= UNUM_MAYBE
;
340 //------------------------------------------------------------------------------
341 // Constructs a DecimalFormat instance with the specified number format
342 // pattern and the number format symbols in the desired locale. The
343 // created instance owns the symbols.
346 DecimalFormat::construct(UErrorCode
& status
,
347 UParseError
& parseErr
,
348 const UnicodeString
* pattern
,
349 DecimalFormatSymbols
* symbolsToAdopt
)
351 LocalPointer
<DecimalFormatSymbols
> adoptedSymbols(symbolsToAdopt
);
352 if (U_FAILURE(status
))
355 if (adoptedSymbols
.isNull())
357 adoptedSymbols
.adoptInstead(
358 new DecimalFormatSymbols(Locale::getDefault(), status
));
359 if (adoptedSymbols
.isNull() && U_SUCCESS(status
)) {
360 status
= U_MEMORY_ALLOCATION_ERROR
;
362 if (U_FAILURE(status
)) {
366 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
367 if (U_FAILURE(status
)) {
372 // Uses the default locale's number format pattern if there isn't
376 UErrorCode nsStatus
= U_ZERO_ERROR
;
377 LocalPointer
<NumberingSystem
> ns(
378 NumberingSystem::createInstance(nsStatus
));
379 if (U_FAILURE(nsStatus
)) {
385 UResourceBundle
*top
= ures_open(NULL
, Locale::getDefault().getName(), &status
);
387 UResourceBundle
*resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, NULL
, &status
);
388 resource
= ures_getByKeyWithFallback(resource
, ns
->getName(), resource
, &status
);
389 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
390 const UChar
*resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
391 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(fgLatn
,ns
->getName())) {
392 status
= U_ZERO_ERROR
;
393 resource
= ures_getByKeyWithFallback(top
, fgNumberElements
, resource
, &status
);
394 resource
= ures_getByKeyWithFallback(resource
, fgLatn
, resource
, &status
);
395 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &status
);
396 resStr
= ures_getStringByKeyWithFallback(resource
, fgDecimalFormat
, &len
, &status
);
398 str
.setTo(TRUE
, resStr
, len
);
400 ures_close(resource
);
404 fImpl
= new DecimalFormatImpl(this, *pattern
, adoptedSymbols
.getAlias(), parseErr
, status
);
406 adoptedSymbols
.orphan();
407 } else if (U_SUCCESS(status
)) {
408 status
= U_MEMORY_ALLOCATION_ERROR
;
410 if (U_FAILURE(status
)) {
414 if (U_FAILURE(status
))
419 const UnicodeString
* patternUsed
;
420 UnicodeString currencyPluralPatternForOther
;
422 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
423 fCurrencyPluralInfo
= new CurrencyPluralInfo(fImpl
->fSymbols
->getLocale(), status
);
424 if (U_FAILURE(status
)) {
428 // the pattern used in format is not fixed until formatting,
429 // in which, the number is known and
430 // will be used to pick the right pattern based on plural count.
431 // Here, set the pattern as the pattern of plural count == "other".
432 // For most locale, the patterns are probably the same for all
433 // plural count. If not, the right pattern need to be re-applied
435 fCurrencyPluralInfo
->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther
);
436 // TODO(refactor): Revisit, we are setting the pattern twice.
437 fImpl
->applyPatternFavorCurrencyPrecision(
438 currencyPluralPatternForOther
, status
);
439 patternUsed
= ¤cyPluralPatternForOther
;
442 patternUsed
= pattern
;
445 if (patternUsed
->indexOf(kCurrencySign
) != -1) {
446 // initialize for currency, not only for plural format,
447 // but also for mix parsing
448 handleCurrencySignInPattern(status
);
453 DecimalFormat::handleCurrencySignInPattern(UErrorCode
& status
) {
454 // initialize for currency, not only for plural format,
455 // but also for mix parsing
456 if (U_FAILURE(status
)) {
459 if (fCurrencyPluralInfo
== NULL
) {
460 fCurrencyPluralInfo
= new CurrencyPluralInfo(fImpl
->fSymbols
->getLocale(), status
);
461 if (U_FAILURE(status
)) {
465 // need it for mix parsing
466 if (fAffixPatternsForCurrency
== NULL
) {
467 setupCurrencyAffixPatterns(status
);
472 applyPatternWithNoSideEffects(
473 const UnicodeString
& pattern
,
474 UParseError
& parseError
,
475 UnicodeString
&negPrefix
,
476 UnicodeString
&negSuffix
,
477 UnicodeString
&posPrefix
,
478 UnicodeString
&posSuffix
,
479 UErrorCode
& status
) {
480 if (U_FAILURE(status
))
484 DecimalFormatPatternParser patternParser
;
485 DecimalFormatPattern out
;
486 patternParser
.applyPatternWithoutExpandAffix(
491 if (U_FAILURE(status
)) {
494 negPrefix
= out
.fNegPrefixPattern
;
495 negSuffix
= out
.fNegSuffixPattern
;
496 posPrefix
= out
.fPosPrefixPattern
;
497 posSuffix
= out
.fPosSuffixPattern
;
501 DecimalFormat::setupCurrencyAffixPatterns(UErrorCode
& status
) {
502 if (U_FAILURE(status
)) {
505 UParseError parseErr
;
506 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
507 if (U_FAILURE(status
)) {
511 NumberingSystem
*ns
= NumberingSystem::createInstance(fImpl
->fSymbols
->getLocale(),status
);
512 if (U_FAILURE(status
)) {
516 // Save the default currency patterns of this locale.
517 // Here, chose onlyApplyPatternWithoutExpandAffix without
518 // expanding the affix patterns into affixes.
519 UnicodeString currencyPattern
;
520 UErrorCode error
= U_ZERO_ERROR
;
522 UResourceBundle
*resource
= ures_open(NULL
, fImpl
->fSymbols
->getLocale().getName(), &error
);
523 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, fgNumberElements
, NULL
, &error
);
524 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &error
);
525 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
527 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
528 if ( error
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(ns
->getName(),fgLatn
)) {
529 error
= U_ZERO_ERROR
;
530 resource
= ures_getByKeyWithFallback(numElements
, fgLatn
, resource
, &error
);
531 resource
= ures_getByKeyWithFallback(resource
, fgPatterns
, resource
, &error
);
532 patResStr
= ures_getStringByKeyWithFallback(resource
, fgCurrencyFormat
, &patLen
, &error
);
534 ures_close(numElements
);
535 ures_close(resource
);
538 if (U_SUCCESS(error
)) {
539 UnicodeString negPrefix
;
540 UnicodeString negSuffix
;
541 UnicodeString posPrefix
;
542 UnicodeString posSuffix
;
543 applyPatternWithNoSideEffects(UnicodeString(patResStr
, patLen
),
545 negPrefix
, negSuffix
, posPrefix
, posSuffix
, status
);
546 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
552 fAffixPatternsForCurrency
->put(UNICODE_STRING("default", 7), affixPtn
, status
);
555 // save the unique currency plural patterns of this locale.
556 Hashtable
* pluralPtn
= fCurrencyPluralInfo
->fPluralCountToCurrencyUnitPattern
;
557 const UHashElement
* element
= NULL
;
558 int32_t pos
= UHASH_FIRST
;
559 Hashtable pluralPatternSet
;
560 while ((element
= pluralPtn
->nextElement(pos
)) != NULL
) {
561 const UHashTok valueTok
= element
->value
;
562 const UnicodeString
* value
= (UnicodeString
*)valueTok
.pointer
;
563 const UHashTok keyTok
= element
->key
;
564 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
565 if (pluralPatternSet
.geti(*value
) != 1) {
566 UnicodeString negPrefix
;
567 UnicodeString negSuffix
;
568 UnicodeString posPrefix
;
569 UnicodeString posSuffix
;
570 pluralPatternSet
.puti(*value
, 1, status
);
571 applyPatternWithNoSideEffects(
573 negPrefix
, negSuffix
, posPrefix
, posSuffix
, status
);
574 AffixPatternsForCurrency
* affixPtn
= new AffixPatternsForCurrency(
580 fAffixPatternsForCurrency
->put(*key
, affixPtn
, status
);
586 //------------------------------------------------------------------------------
588 DecimalFormat::~DecimalFormat()
590 deleteHashForAffixPattern();
591 delete fCurrencyPluralInfo
;
595 //------------------------------------------------------------------------------
598 DecimalFormat::DecimalFormat(const DecimalFormat
&source
) :
599 NumberFormat(source
) {
604 //------------------------------------------------------------------------------
605 // assignment operator
608 static void _clone_ptr(T
** pdest
, const T
* source
) {
610 if (source
== NULL
) {
613 *pdest
= static_cast<T
*>(source
->clone());
618 DecimalFormat::operator=(const DecimalFormat
& rhs
)
621 UErrorCode status
= U_ZERO_ERROR
;
622 NumberFormat::operator=(rhs
);
624 fImpl
= new DecimalFormatImpl(this, *rhs
.fImpl
, status
);
626 fImpl
->assign(*rhs
.fImpl
, status
);
628 fStaticSets
= DecimalFormatStaticSets::getStaticSets(status
);
630 _clone_ptr(&fCurrencyPluralInfo
, rhs
.fCurrencyPluralInfo
);
631 deleteHashForAffixPattern();
632 if (rhs
.fAffixPatternsForCurrency
) {
633 UErrorCode status
= U_ZERO_ERROR
;
634 fAffixPatternsForCurrency
= initHashForAffixPattern(status
);
635 copyHashForAffixPattern(rhs
.fAffixPatternsForCurrency
,
636 fAffixPatternsForCurrency
, status
);
643 //------------------------------------------------------------------------------
646 DecimalFormat::operator==(const Format
& that
) const
651 // NumberFormat::operator== guarantees this cast is safe
652 const DecimalFormat
* other
= (DecimalFormat
*)&that
;
655 NumberFormat::operator==(that
) &&
656 fBoolFlags
.getAll() == other
->fBoolFlags
.getAll() &&
657 *fImpl
== *other
->fImpl
);
661 //------------------------------------------------------------------------------
664 DecimalFormat::clone() const
666 return new DecimalFormat(*this);
671 DecimalFormat::getFixedDecimal(double number
, UErrorCode
&status
) const {
672 VisibleDigitsWithExponent digits
;
673 initVisibleDigitsWithExponent(number
, digits
, status
);
674 if (U_FAILURE(status
)) {
675 return FixedDecimal();
677 return FixedDecimal(digits
.getMantissa());
680 VisibleDigitsWithExponent
&
681 DecimalFormat::initVisibleDigitsWithExponent(
683 VisibleDigitsWithExponent
&digits
,
684 UErrorCode
&status
) const {
685 return fImpl
->initVisibleDigitsWithExponent(number
, digits
, status
);
689 DecimalFormat::getFixedDecimal(const Formattable
&number
, UErrorCode
&status
) const {
690 VisibleDigitsWithExponent digits
;
691 initVisibleDigitsWithExponent(number
, digits
, status
);
692 if (U_FAILURE(status
)) {
693 return FixedDecimal();
695 return FixedDecimal(digits
.getMantissa());
698 VisibleDigitsWithExponent
&
699 DecimalFormat::initVisibleDigitsWithExponent(
700 const Formattable
&number
,
701 VisibleDigitsWithExponent
&digits
,
702 UErrorCode
&status
) const {
703 if (U_FAILURE(status
)) {
706 if (!number
.isNumeric()) {
707 status
= U_ILLEGAL_ARGUMENT_ERROR
;
711 DigitList
*dl
= number
.getDigitList();
713 DigitList
dlCopy(*dl
);
714 return fImpl
->initVisibleDigitsWithExponent(
715 dlCopy
, digits
, status
);
718 Formattable::Type type
= number
.getType();
719 if (type
== Formattable::kDouble
|| type
== Formattable::kLong
) {
720 return fImpl
->initVisibleDigitsWithExponent(
721 number
.getDouble(status
), digits
, status
);
723 return fImpl
->initVisibleDigitsWithExponent(
724 number
.getInt64(), digits
, status
);
728 // Create a fixed decimal from a DigitList.
729 // The digit list may be modified.
730 // Internal function only.
732 DecimalFormat::getFixedDecimal(DigitList
&number
, UErrorCode
&status
) const {
733 VisibleDigitsWithExponent digits
;
734 initVisibleDigitsWithExponent(number
, digits
, status
);
735 if (U_FAILURE(status
)) {
736 return FixedDecimal();
738 return FixedDecimal(digits
.getMantissa());
741 VisibleDigitsWithExponent
&
742 DecimalFormat::initVisibleDigitsWithExponent(
744 VisibleDigitsWithExponent
&digits
,
745 UErrorCode
&status
) const {
746 return fImpl
->initVisibleDigitsWithExponent(
747 number
, digits
, status
);
751 //------------------------------------------------------------------------------
754 DecimalFormat::format(int32_t number
,
755 UnicodeString
& appendTo
,
756 FieldPosition
& fieldPosition
) const
758 UErrorCode status
= U_ZERO_ERROR
;
759 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
763 DecimalFormat::format(int32_t number
,
764 UnicodeString
& appendTo
,
765 FieldPosition
& fieldPosition
,
766 UErrorCode
& status
) const
768 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
772 DecimalFormat::format(int32_t number
,
773 UnicodeString
& appendTo
,
774 FieldPositionIterator
* posIter
,
775 UErrorCode
& status
) const
777 return fImpl
->format(number
, appendTo
, posIter
, status
);
781 //------------------------------------------------------------------------------
784 DecimalFormat::format(int64_t number
,
785 UnicodeString
& appendTo
,
786 FieldPosition
& fieldPosition
) const
788 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
789 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
793 DecimalFormat::format(int64_t number
,
794 UnicodeString
& appendTo
,
795 FieldPosition
& fieldPosition
,
796 UErrorCode
& status
) const
798 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
802 DecimalFormat::format(int64_t number
,
803 UnicodeString
& appendTo
,
804 FieldPositionIterator
* posIter
,
805 UErrorCode
& status
) const
807 return fImpl
->format(number
, appendTo
, posIter
, status
);
810 //------------------------------------------------------------------------------
813 DecimalFormat::format( double number
,
814 UnicodeString
& appendTo
,
815 FieldPosition
& fieldPosition
) const
817 UErrorCode status
= U_ZERO_ERROR
; /* ignored */
818 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
822 DecimalFormat::format( double number
,
823 UnicodeString
& appendTo
,
824 FieldPosition
& fieldPosition
,
825 UErrorCode
& status
) const
827 return fImpl
->format(number
, appendTo
, fieldPosition
, status
);
831 DecimalFormat::format( double number
,
832 UnicodeString
& appendTo
,
833 FieldPositionIterator
* posIter
,
834 UErrorCode
& status
) const
836 return fImpl
->format(number
, appendTo
, posIter
, status
);
839 //------------------------------------------------------------------------------
843 DecimalFormat::format(const StringPiece
&number
,
844 UnicodeString
&toAppendTo
,
845 FieldPositionIterator
*posIter
,
846 UErrorCode
&status
) const
848 return fImpl
->format(number
, toAppendTo
, posIter
, status
);
853 DecimalFormat::format(const DigitList
&number
,
854 UnicodeString
&appendTo
,
855 FieldPositionIterator
*posIter
,
856 UErrorCode
&status
) const {
857 return fImpl
->format(number
, appendTo
, posIter
, status
);
862 DecimalFormat::format(const DigitList
&number
,
863 UnicodeString
& appendTo
,
865 UErrorCode
&status
) const {
866 return fImpl
->format(number
, appendTo
, pos
, status
);
870 DecimalFormat::format(const VisibleDigitsWithExponent
&number
,
871 UnicodeString
&appendTo
,
872 FieldPositionIterator
*posIter
,
873 UErrorCode
&status
) const {
874 return fImpl
->format(number
, appendTo
, posIter
, status
);
879 DecimalFormat::format(const VisibleDigitsWithExponent
&number
,
880 UnicodeString
& appendTo
,
882 UErrorCode
&status
) const {
883 return fImpl
->format(number
, appendTo
, pos
, status
);
887 DecimalFormat::_round(const DigitList
& number
, DigitList
& adjustedNum
, UBool
& isNegative
, UErrorCode
& status
) const {
888 adjustedNum
= number
;
889 fImpl
->round(adjustedNum
, status
);
890 isNegative
= !adjustedNum
.isPositive();
895 DecimalFormat::parse(const UnicodeString
& text
,
897 ParsePosition
& parsePosition
) const {
898 parse(text
, result
, parsePosition
, NULL
);
901 CurrencyAmount
* DecimalFormat::parseCurrency(const UnicodeString
& text
,
902 ParsePosition
& pos
) const {
903 Formattable parseResult
;
904 int32_t start
= pos
.getIndex();
905 UChar curbuf
[4] = {};
906 parse(text
, parseResult
, pos
, curbuf
);
907 if (pos
.getIndex() != start
) {
908 UErrorCode ec
= U_ZERO_ERROR
;
909 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curbuf
, ec
), ec
);
911 pos
.setIndex(start
); // indicate failure
913 return currAmt
.orphan();
920 * Parses the given text as a number, optionally providing a currency amount.
921 * @param text the string to parse
922 * @param result output parameter for the numeric result.
923 * @param parsePosition input-output position; on input, the
924 * position within text to match; must have 0 <= pos.getIndex() <
925 * text.length(); on output, the position after the last matched
926 * character. If the parse fails, the position in unchanged upon
928 * @param currency if non-NULL, it should point to a 4-UChar buffer.
929 * In this case the text is parsed as a currency format, and the
930 * ISO 4217 code for the parsed currency is put into the buffer.
931 * Otherwise the text is parsed as a non-currency format.
933 void DecimalFormat::parse(const UnicodeString
& text
,
935 ParsePosition
& parsePosition
,
936 UChar
* currency
) const {
937 int32_t startIdx
, backup
;
938 int32_t i
= startIdx
= backup
= parsePosition
.getIndex();
940 // clear any old contents in the result. In particular, clears any DigitList
941 // that it may be holding.
943 if (currency
!= NULL
) {
944 for (int32_t ci
=0; ci
<4; ci
++) {
949 // Handle NaN as a special case:
950 int32_t formatWidth
= fImpl
->getOldFormatWidth();
952 // Skip padding characters, if around prefix
953 if (formatWidth
> 0 && (
954 fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforePrefix
||
955 fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterPrefix
)) {
956 i
= skipPadding(text
, i
);
960 // skip any leading whitespace
961 i
= backup
= skipUWhiteSpace(text
, i
);
964 // If the text is composed of the representation of NaN, returns NaN.length
965 const UnicodeString
*nan
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kNaNSymbol
);
966 int32_t nanLen
= (text
.compare(i
, nan
->length(), *nan
)
967 ? 0 : nan
->length());
970 if (formatWidth
> 0 && (fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforeSuffix
|| fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterSuffix
)) {
971 i
= skipPadding(text
, i
);
973 parsePosition
.setIndex(i
);
974 result
.setDouble(uprv_getNaN());
978 // NaN parse failed; start over
980 parsePosition
.setIndex(i
);
982 // status is used to record whether a number is infinite.
983 UBool status
[fgStatusLength
];
985 DigitList
*digits
= result
.getInternalDigitList(); // get one from the stack buffer
986 if (digits
== NULL
) {
987 return; // no way to report error from here.
990 if (fImpl
->fMonetary
) {
991 if (!parseForCurrency(text
, parsePosition
, *digits
,
997 &fImpl
->fAffixes
.fNegativePrefix
.getOtherVariant().toString(),
998 &fImpl
->fAffixes
.fNegativeSuffix
.getOtherVariant().toString(),
999 &fImpl
->fAffixes
.fPositivePrefix
.getOtherVariant().toString(),
1000 &fImpl
->fAffixes
.fPositiveSuffix
.getOtherVariant().toString(),
1001 FALSE
, UCURR_SYMBOL_NAME
,
1002 parsePosition
, *digits
, status
, currency
)) {
1003 debug("!subparse(...) - rewind");
1004 parsePosition
.setIndex(startIdx
);
1010 if (status
[fgStatusInfinite
]) {
1011 double inf
= uprv_getInfinity();
1012 result
.setDouble(digits
->isPositive() ? inf
: -inf
);
1013 // TODO: set the dl to infinity, and let it fall into the code below.
1018 if (!fImpl
->fMultiplier
.isZero()) {
1019 UErrorCode ec
= U_ZERO_ERROR
;
1020 digits
->div(fImpl
->fMultiplier
, ec
);
1023 if (fImpl
->fScale
!= 0) {
1025 ten
.set((int32_t)10);
1026 if (fImpl
->fScale
> 0) {
1027 for (int32_t i
= fImpl
->fScale
; i
> 0; i
--) {
1028 UErrorCode ec
= U_ZERO_ERROR
;
1029 digits
->div(ten
,ec
);
1032 for (int32_t i
= fImpl
->fScale
; i
< 0; i
++) {
1033 UErrorCode ec
= U_ZERO_ERROR
;
1034 digits
->mult(ten
,ec
);
1039 // Negative zero special case:
1040 // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable.
1041 // if not parsing integerOnly, leave as -0, which a double can represent.
1042 if (digits
->isZero() && !digits
->isPositive() && isParseIntegerOnly()) {
1043 digits
->setPositive(TRUE
);
1045 result
.adoptDigitList(digits
);
1052 DecimalFormat::parseForCurrency(const UnicodeString
& text
,
1053 ParsePosition
& parsePosition
,
1056 UChar
* currency
) const {
1057 UnicodeString positivePrefix
;
1058 UnicodeString positiveSuffix
;
1059 UnicodeString negativePrefix
;
1060 UnicodeString negativeSuffix
;
1061 fImpl
->fPositivePrefixPattern
.toString(positivePrefix
);
1062 fImpl
->fPositiveSuffixPattern
.toString(positiveSuffix
);
1063 fImpl
->fNegativePrefixPattern
.toString(negativePrefix
);
1064 fImpl
->fNegativeSuffixPattern
.toString(negativeSuffix
);
1066 int origPos
= parsePosition
.getIndex();
1067 int maxPosIndex
= origPos
;
1068 int maxErrorPos
= -1;
1069 // First, parse against current pattern.
1070 // Since current pattern could be set by applyPattern(),
1071 // it could be an arbitrary pattern, and it may not be the one
1072 // defined in current locale.
1073 UBool tmpStatus
[fgStatusLength
];
1074 ParsePosition
tmpPos(origPos
);
1075 DigitList tmpDigitList
;
1077 if (fStyle
== UNUM_CURRENCY_PLURAL
) {
1078 found
= subparse(text
,
1079 &negativePrefix
, &negativeSuffix
,
1080 &positivePrefix
, &positiveSuffix
,
1081 TRUE
, UCURR_LONG_NAME
,
1082 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1084 found
= subparse(text
,
1085 &negativePrefix
, &negativeSuffix
,
1086 &positivePrefix
, &positiveSuffix
,
1087 TRUE
, UCURR_SYMBOL_NAME
,
1088 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1091 if (tmpPos
.getIndex() > maxPosIndex
) {
1092 maxPosIndex
= tmpPos
.getIndex();
1093 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1094 status
[i
] = tmpStatus
[i
];
1096 digits
= tmpDigitList
;
1099 maxErrorPos
= tmpPos
.getErrorIndex();
1101 // Then, parse against affix patterns.
1102 // Those are currency patterns and currency plural patterns.
1103 int32_t pos
= UHASH_FIRST
;
1104 const UHashElement
* element
= NULL
;
1105 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
1106 const UHashTok valueTok
= element
->value
;
1107 const AffixPatternsForCurrency
* affixPtn
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
1108 UBool tmpStatus
[fgStatusLength
];
1109 ParsePosition
tmpPos(origPos
);
1110 DigitList tmpDigitList
;
1113 debug("trying affix for currency..");
1117 UBool result
= subparse(text
,
1118 &affixPtn
->negPrefixPatternForCurrency
,
1119 &affixPtn
->negSuffixPatternForCurrency
,
1120 &affixPtn
->posPrefixPatternForCurrency
,
1121 &affixPtn
->posSuffixPatternForCurrency
,
1122 TRUE
, affixPtn
->patternType
,
1123 tmpPos
, tmpDigitList
, tmpStatus
, currency
);
1126 if (tmpPos
.getIndex() > maxPosIndex
) {
1127 maxPosIndex
= tmpPos
.getIndex();
1128 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1129 status
[i
] = tmpStatus
[i
];
1131 digits
= tmpDigitList
;
1134 maxErrorPos
= (tmpPos
.getErrorIndex() > maxErrorPos
) ?
1135 tmpPos
.getErrorIndex() : maxErrorPos
;
1138 // Finally, parse against simple affix to find the match.
1139 // For example, in TestMonster suite,
1140 // if the to-be-parsed text is "-\u00A40,00".
1141 // complexAffixCompare will not find match,
1142 // since there is no ISO code matches "\u00A4",
1143 // and the parse stops at "\u00A4".
1144 // We will just use simple affix comparison (look for exact match)
1147 // TODO: We should parse against simple affix first when
1148 // output currency is not requested. After the complex currency
1149 // parsing implementation was introduced, the default currency
1150 // instance parsing slowed down because of the new code flow.
1151 // I filed #10312 - Yoshito
1152 UBool tmpStatus_2
[fgStatusLength
];
1153 ParsePosition
tmpPos_2(origPos
);
1154 DigitList tmpDigitList_2
;
1156 // Disable complex currency parsing and try it again.
1157 UBool result
= subparse(text
,
1158 &fImpl
->fAffixes
.fNegativePrefix
.getOtherVariant().toString(),
1159 &fImpl
->fAffixes
.fNegativeSuffix
.getOtherVariant().toString(),
1160 &fImpl
->fAffixes
.fPositivePrefix
.getOtherVariant().toString(),
1161 &fImpl
->fAffixes
.fPositiveSuffix
.getOtherVariant().toString(),
1162 FALSE
/* disable complex currency parsing */, UCURR_SYMBOL_NAME
,
1163 tmpPos_2
, tmpDigitList_2
, tmpStatus_2
,
1166 if (tmpPos_2
.getIndex() > maxPosIndex
) {
1167 maxPosIndex
= tmpPos_2
.getIndex();
1168 for (int32_t i
= 0; i
< fgStatusLength
; ++i
) {
1169 status
[i
] = tmpStatus_2
[i
];
1171 digits
= tmpDigitList_2
;
1175 maxErrorPos
= (tmpPos_2
.getErrorIndex() > maxErrorPos
) ?
1176 tmpPos_2
.getErrorIndex() : maxErrorPos
;
1180 //parsePosition.setIndex(origPos);
1181 parsePosition
.setErrorIndex(maxErrorPos
);
1183 parsePosition
.setIndex(maxPosIndex
);
1184 parsePosition
.setErrorIndex(-1);
1191 * Parse the given text into a number. The text is parsed beginning at
1192 * parsePosition, until an unparseable character is seen.
1193 * @param text the string to parse.
1194 * @param negPrefix negative prefix.
1195 * @param negSuffix negative suffix.
1196 * @param posPrefix positive prefix.
1197 * @param posSuffix positive suffix.
1198 * @param complexCurrencyParsing whether it is complex currency parsing or not.
1199 * @param type the currency type to parse against, LONG_NAME only or not.
1200 * @param parsePosition The position at which to being parsing. Upon
1201 * return, the first unparsed character.
1202 * @param digits the DigitList to set to the parsed value.
1203 * @param status output param containing boolean status flags indicating
1204 * whether the value was infinite and whether it was positive.
1205 * @param currency return value for parsed currency, for generic
1206 * currency parsing mode, or NULL for normal parsing. In generic
1207 * currency parsing mode, any currency is parsed, not just the
1208 * currency that this formatter is set to.
1210 UBool
DecimalFormat::subparse(const UnicodeString
& text
,
1211 const UnicodeString
* negPrefix
,
1212 const UnicodeString
* negSuffix
,
1213 const UnicodeString
* posPrefix
,
1214 const UnicodeString
* posSuffix
,
1215 UBool complexCurrencyParsing
,
1217 ParsePosition
& parsePosition
,
1218 DigitList
& digits
, UBool
* status
,
1219 UChar
* currency
) const
1221 // The parsing process builds up the number as char string, in the neutral format that
1222 // will be acceptable to the decNumber library, then at the end passes that string
1223 // off for conversion to a decNumber.
1224 UErrorCode err
= U_ZERO_ERROR
;
1225 CharString parsedNum
;
1228 int32_t position
= parsePosition
.getIndex();
1229 int32_t oldStart
= position
;
1230 int32_t textLength
= text
.length(); // One less pointer to follow
1231 UBool strictParse
= !isLenient();
1232 UChar32 zero
= fImpl
->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol
).char32At(0);
1233 const UnicodeString
*groupingString
= &fImpl
->getConstSymbol(
1235 DecimalFormatSymbols::kGroupingSeparatorSymbol
: DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
);
1236 UChar32 groupingChar
= groupingString
->char32At(0);
1237 int32_t groupingStringLength
= groupingString
->length();
1238 int32_t groupingCharLength
= U16_LENGTH(groupingChar
);
1239 UBool groupingUsed
= isGroupingUsed();
1242 UnicodeString
s(dbgbuf
,0,300);;
1243 s
.append((UnicodeString
)"PARSE \"").append(text
.tempSubString(position
)).append((UnicodeString
)"\" " );
1244 #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 ")); }
1252 UBool fastParseOk
= false; /* TRUE iff fast parse is OK */
1253 // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
1254 if((fImpl
->isParseFastpath()) && !fImpl
->fMonetary
&&
1257 (posPrefix
==NULL
||posPrefix
->isEmpty()) &&
1258 (posSuffix
==NULL
||posSuffix
->isEmpty()) &&
1259 // (negPrefix==NULL||negPrefix->isEmpty()) &&
1260 // (negSuffix==NULL||(negSuffix->isEmpty()) ) &&
1261 TRUE
) { // optimized path
1263 int l
=text
.length();
1265 UChar32 ch
= text
.char32At(j
);
1266 const UnicodeString
*decimalString
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1267 UChar32 decimalChar
= 0;
1268 UBool intOnly
= FALSE
;
1269 UChar32 lookForGroup
= (groupingUsed
&&intOnly
&&strictParse
)?groupingChar
:0;
1271 int32_t decimalCount
= decimalString
->countChar32(0,3);
1272 if(isParseIntegerOnly()) {
1273 decimalChar
= 0; // not allowed
1274 intOnly
= TRUE
; // Don't look for decimals.
1275 } else if(decimalCount
==1) {
1276 decimalChar
= decimalString
->char32At(0); // Look for this decimal
1277 } else if(decimalCount
==0) {
1278 decimalChar
=0; // NO decimal set
1280 j
=l
+1;//Set counter to end of line, so that we break. Unknown decimal situation.
1284 printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n",
1285 decimalChar
, groupingChar
, ch
,
1287 (strictParse
)?'y':'n');
1289 if(ch
==0x002D) { // '-'
1290 j
=l
+1;//=break - negative number.
1293 parsedNum.append('-',err);
1295 if(j<l) ch = text.char32At(j);
1298 parsedNum
.append('+',err
);
1301 int32_t digit
= ch
- zero
;
1302 if(digit
>=0 && digit
<= 9) {
1303 parsedNum
.append((char)(digit
+ '0'), err
);
1304 if((digitCount
>0) || digit
!=0 || j
==(l
-1)) {
1307 } else if(ch
== 0) { // break out
1310 } else if(ch
== decimalChar
) {
1311 parsedNum
.append((char)('.'), err
);
1312 decimalChar
=0; // no more decimals.
1313 // fastParseHadDecimal=TRUE;
1314 } else if(ch
== lookForGroup
) {
1315 // ignore grouping char. No decimals, so it has to be an ignorable grouping sep
1316 } else if(intOnly
&& (lookForGroup
!=0) && !u_isdigit(ch
)) {
1317 // parsing integer only and can fall through
1319 digitCount
=-1; // fail - fall through to slow parse
1323 ch
= text
.char32At(j
); // for next
1326 ((j
==l
)||intOnly
) // end OR only parsing integer
1327 && (digitCount
>0)) { // and have at least one digit
1328 fastParseOk
=true; // Fast parse OK!
1332 /* for testing, try it the slow way. also */
1336 parsePosition
.setIndex(position
=j
);
1337 status
[fgStatusInfinite
]=false;
1340 // was not OK. reset, retry
1342 printf("Fall through: j=%d, l=%d, digitCount=%d\n", j
, l
, digitCount
);
1348 printf("Could not fastpath parse. ");
1349 printf("text.length()=%d ", text
.length());
1350 printf("posPrefix=%p posSuffix=%p ", posPrefix
, posSuffix
);
1356 UnicodeString formatPattern
;
1357 toPattern(formatPattern
);
1360 #if UCONFIG_HAVE_PARSEALLINPUT
1361 && fParseAllInput
!=UNUM_YES
1365 int32_t formatWidth
= fImpl
->getOldFormatWidth();
1366 // Match padding before prefix
1367 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforePrefix
) {
1368 position
= skipPadding(text
, position
);
1371 // Match positive and negative prefixes; prefer longest match.
1372 int32_t posMatch
= compareAffix(text
, position
, FALSE
, TRUE
, posPrefix
, complexCurrencyParsing
, type
, currency
);
1373 int32_t negMatch
= compareAffix(text
, position
, TRUE
, TRUE
, negPrefix
, complexCurrencyParsing
, type
, currency
);
1374 if (posMatch
>= 0 && negMatch
>= 0) {
1375 if (posMatch
> negMatch
) {
1377 } else if (negMatch
> posMatch
) {
1381 if (posMatch
>= 0) {
1382 position
+= posMatch
;
1383 parsedNum
.append('+', err
);
1384 } else if (negMatch
>= 0) {
1385 position
+= negMatch
;
1386 parsedNum
.append('-', err
);
1387 } else if (strictParse
){
1388 parsePosition
.setErrorIndex(position
);
1391 // Temporary set positive. This might be changed after checking suffix
1392 parsedNum
.append('+', err
);
1395 // Match padding before prefix
1396 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterPrefix
) {
1397 position
= skipPadding(text
, position
);
1400 if (! strictParse
) {
1401 position
= skipUWhiteSpace(text
, position
);
1404 // process digits or Inf, find decimal position
1405 const UnicodeString
*inf
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol
);
1406 int32_t infLen
= (text
.compare(position
, inf
->length(), *inf
)
1407 ? 0 : inf
->length());
1408 position
+= infLen
; // infLen is non-zero when it does equal to infinity
1409 status
[fgStatusInfinite
] = infLen
!= 0;
1412 parsedNum
.append("Infinity", err
);
1414 // We now have a string of digits, possibly with grouping symbols,
1415 // and decimal points. We want to process these into a DigitList.
1416 // We don't want to put a bunch of leading zeros into the DigitList
1417 // though, so we keep track of the location of the decimal point,
1418 // put only significant digits into the DigitList, and adjust the
1419 // exponent as needed.
1422 UBool strictFail
= FALSE
; // did we exit with a strict parse failure?
1423 int32_t lastGroup
= -1; // where did we last see a grouping separator?
1424 int32_t digitStart
= position
;
1425 int32_t gs2
= fImpl
->fEffGrouping
.fGrouping2
== 0 ? fImpl
->fEffGrouping
.fGrouping
: fImpl
->fEffGrouping
.fGrouping2
;
1427 const UnicodeString
*decimalString
;
1428 if (fImpl
->fMonetary
) {
1429 decimalString
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1431 decimalString
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
1433 UChar32 decimalChar
= decimalString
->char32At(0);
1434 int32_t decimalStringLength
= decimalString
->length();
1435 int32_t decimalCharLength
= U16_LENGTH(decimalChar
);
1437 UBool sawDecimal
= FALSE
;
1438 UChar32 sawDecimalChar
= 0xFFFF;
1439 UBool sawGrouping
= FALSE
;
1440 UChar32 sawGroupingChar
= 0xFFFF;
1441 UBool sawDigit
= FALSE
;
1442 int32_t backup
= -1;
1445 // equivalent grouping and decimal support
1446 const UnicodeSet
*decimalSet
= NULL
;
1447 const UnicodeSet
*groupingSet
= NULL
;
1449 if (decimalCharLength
== decimalStringLength
) {
1450 decimalSet
= DecimalFormatStaticSets::getSimilarDecimals(decimalChar
, strictParse
);
1453 if (groupingCharLength
== groupingStringLength
) {
1455 groupingSet
= fStaticSets
->fStrictDefaultGroupingSeparators
;
1457 groupingSet
= fStaticSets
->fDefaultGroupingSeparators
;
1461 // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized.
1462 // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet
1463 // If a character matches decimalSet, don't consider it to be a member of the groupingSet.
1465 // We have to track digitCount ourselves, because digits.fCount will
1466 // pin when the maximum allowable digits is reached.
1467 int32_t digitCount
= 0;
1468 int32_t integerDigitCount
= 0;
1470 for (; position
< textLength
; )
1472 UChar32 ch
= text
.char32At(position
);
1474 /* We recognize all digit ranges, not only the Latin digit range
1475 * '0'..'9'. We do so by using the Character.digit() method,
1476 * which converts a valid Unicode digit to the range 0..9.
1478 * The character 'ch' may be a digit. If so, place its value
1479 * from 0 to 9 in 'digit'. First try using the locale digit,
1480 * which may or MAY NOT be a standard Unicode digit range. If
1481 * this fails, try using the standard Unicode digit ranges by
1482 * calling Character.digit(). If this also fails, digit will
1483 * have a value outside the range 0..9.
1486 if (digit
< 0 || digit
> 9)
1488 digit
= u_charDigitValue(ch
);
1491 // As a last resort, look through the localized digits if the zero digit
1492 // is not a "standard" Unicode digit.
1493 if ( (digit
< 0 || digit
> 9) && u_charDigitValue(zero
) != 0) {
1495 // Already check above (digit = ch - zero) for ch==zero; the only check we need to do here is:
1496 // if \u3007 is treated as 0 for parsing, \u96F6 should be too. Otherwise check for nonzero digits.
1497 if ( zero
!=0x3007 || ch
!=0x96F6 ) {
1498 for (digit
= 1 ; digit
< 10 ; digit
++ ) {
1499 if ( fImpl
->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)(DecimalFormatSymbols::kOneDigitSymbol
+digit
-1)).char32At(0) == ch
) {
1506 if (digit
>= 0 && digit
<= 9)
1508 if (strictParse
&& backup
!= -1) {
1509 // comma followed by digit, so group before comma is a
1510 // secondary group. If there was a group separator
1511 // before that, the group must == the secondary group
1512 // length, else it can be <= the the secondary group
1514 if ((lastGroup
!= -1 && backup
- lastGroup
- 1 != gs2
) ||
1515 (lastGroup
== -1 && position
- digitStart
- 1 > gs2
)) {
1523 // Cancel out backup setting (see grouping handler below)
1527 // Note: this will append leading zeros
1528 parsedNum
.append((char)(digit
+ '0'), err
);
1530 // count any digit that's not a leading zero
1531 if (digit
> 0 || digitCount
> 0 || sawDecimal
) {
1534 // count any integer digit that's not a leading zero
1536 integerDigitCount
+= 1;
1540 position
+= U16_LENGTH(ch
);
1542 else if (groupingStringLength
> 0 &&
1543 matchGrouping(groupingChar
, sawGrouping
, sawGroupingChar
, groupingSet
,
1544 decimalChar
, decimalSet
,
1545 ch
) && groupingUsed
)
1552 if ( (!sawDigit
&& groupingSet
!=NULL
&& u_isWhitespace(ch
)) || backup
!= -1 ) {
1553 // We differ from the ICU4J code by allowing a leading group sep in strict mode (for
1554 // backward compatibility) as long as it is not one of the breaking whitespace characters
1555 // that is only treated as a group separator because of the equivalence set. If we get
1556 // here it is because the leading sep was such a breaking space, or there were multiple
1557 // group separators in a row. Note that the DecimalFormat documentation says
1558 // "During parsing, grouping separators are ignored" and that was for strict parsing,
1559 // so we may need to further revisit this strictParse restriction to ensure compatibility.
1560 // Also note: u_isWhitespace is true for all Zs/Zl/Zp except the no-break ones: 00A0,2007,202F.
1561 // In CLDR, all locales that have space as a group separator use 00A0 (NBSP).
1567 // Ignore grouping characters, if we are using them, but require
1568 // that they be followed by a digit. Otherwise we backup and
1571 position
+= groupingStringLength
;
1573 // Once we see a grouping character, we only accept that grouping character from then on.
1576 else if (matchDecimal(decimalChar
,sawDecimal
,sawDecimalChar
, decimalSet
, ch
))
1580 (lastGroup
!= -1 && position
- lastGroup
!= fImpl
->fEffGrouping
.fGrouping
+ 1)) {
1586 // If we're only parsing integers, or if we ALREADY saw the
1587 // decimal, then don't parse this one.
1588 if (isParseIntegerOnly() || sawDecimal
) {
1592 parsedNum
.append('.', err
);
1593 position
+= decimalStringLength
;
1595 // Once we see a decimal character, we only accept that decimal character from then on.
1597 // decimalSet is considered to consist of (ch,ch)
1601 if(!fBoolFlags
.contains(UNUM_PARSE_NO_EXPONENT
) || // don't parse if this is set unless..
1602 isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
1603 const UnicodeString
*tmp
;
1604 tmp
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol
);
1606 if (!text
.caseCompare(position
, tmp
->length(), *tmp
, U_FOLD_CASE_DEFAULT
)) // error code is set below if !sawDigit
1608 // Parse sign, if present
1609 int32_t pos
= position
+ tmp
->length();
1610 char exponentSign
= '+';
1612 if (pos
< textLength
)
1614 tmp
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
1615 if (!text
.compare(pos
, tmp
->length(), *tmp
))
1617 pos
+= tmp
->length();
1620 tmp
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
1621 if (!text
.compare(pos
, tmp
->length(), *tmp
))
1624 pos
+= tmp
->length();
1629 UBool sawExponentDigit
= FALSE
;
1630 while (pos
< textLength
) {
1631 ch
= text
[(int32_t)pos
];
1634 if (digit
< 0 || digit
> 9) {
1635 digit
= u_charDigitValue(ch
);
1637 if (0 <= digit
&& digit
<= 9) {
1638 if (!sawExponentDigit
) {
1639 parsedNum
.append('E', err
);
1640 parsedNum
.append(exponentSign
, err
);
1641 sawExponentDigit
= TRUE
;
1644 parsedNum
.append((char)(digit
+ '0'), err
);
1650 if (sawExponentDigit
) {
1651 position
= pos
; // Advance past the exponent
1654 break; // Whether we fail or succeed, we exit this loop
1658 } else { // not parsing exponent
1664 // if we didn't see a decimal and it is required, check to see if the pattern had one
1665 if(!sawDecimal
&& isDecimalPatternMatchRequired())
1667 if(formatPattern
.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol
) != 0)
1669 parsePosition
.setIndex(oldStart
);
1670 parsePosition
.setErrorIndex(position
);
1671 debug("decimal point match required fail!");
1681 if (strictParse
&& !sawDecimal
) {
1682 if (lastGroup
!= -1 && position
- lastGroup
!= fImpl
->fEffGrouping
.fGrouping
+ 1) {
1688 // only set with strictParse and a grouping separator error
1690 parsePosition
.setIndex(oldStart
);
1691 parsePosition
.setErrorIndex(position
);
1692 debug("strictFail!");
1696 // If there was no decimal point we have an integer
1698 // If none of the text string was recognized. For example, parse
1699 // "x" with pattern "#0.00" (return index and error index both 0)
1700 // parse "$" with pattern "$#0.00". (return index 0 and error index
1702 if (!sawDigit
&& digitCount
== 0) {
1704 debug("none of text rec");
1705 printf("position=%d\n",position
);
1707 parsePosition
.setIndex(oldStart
);
1708 parsePosition
.setErrorIndex(oldStart
);
1713 // Match padding before suffix
1714 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadBeforeSuffix
) {
1715 position
= skipPadding(text
, position
);
1718 int32_t posSuffixMatch
= -1, negSuffixMatch
= -1;
1720 // Match positive and negative suffixes; prefer longest match.
1721 if (posMatch
>= 0 || (!strictParse
&& negMatch
< 0)) {
1722 posSuffixMatch
= compareAffix(text
, position
, FALSE
, FALSE
, posSuffix
, complexCurrencyParsing
, type
, currency
);
1724 if (negMatch
>= 0) {
1725 negSuffixMatch
= compareAffix(text
, position
, TRUE
, FALSE
, negSuffix
, complexCurrencyParsing
, type
, currency
);
1727 if (posSuffixMatch
>= 0 && negSuffixMatch
>= 0) {
1728 if (posSuffixMatch
> negSuffixMatch
) {
1729 negSuffixMatch
= -1;
1730 } else if (negSuffixMatch
> posSuffixMatch
) {
1731 posSuffixMatch
= -1;
1735 // Fail if neither or both
1736 if (strictParse
&& ((posSuffixMatch
>= 0) == (negSuffixMatch
>= 0))) {
1737 parsePosition
.setErrorIndex(position
);
1738 debug("neither or both");
1742 position
+= (posSuffixMatch
>= 0 ? posSuffixMatch
: (negSuffixMatch
>= 0 ? negSuffixMatch
: 0));
1744 // Match padding before suffix
1745 if (formatWidth
> 0 && fImpl
->fAffixes
.fPadPosition
== DigitAffixesAndPadding::kPadAfterSuffix
) {
1746 position
= skipPadding(text
, position
);
1749 parsePosition
.setIndex(position
);
1751 parsedNum
.data()[0] = (posSuffixMatch
>= 0 || (!strictParse
&& negMatch
< 0 && negSuffixMatch
< 0)) ? '+' : '-';
1753 printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position
, parsedNum
.data(), parsePosition
.getIndex(),oldStart
,u_errorName(err
));
1755 } /* end SLOW parse */
1756 if(parsePosition
.getIndex() == oldStart
)
1759 printf(" PP didnt move, err\n");
1761 parsePosition
.setErrorIndex(position
);
1764 #if UCONFIG_HAVE_PARSEALLINPUT
1765 else if (fParseAllInput
==UNUM_YES
&&parsePosition
.getIndex()!=textLength
)
1768 printf(" PP didnt consume all (UNUM_YES), err\n");
1770 parsePosition
.setErrorIndex(position
);
1774 // uint32_t bits = (fastParseOk?kFastpathOk:0) |
1775 // (fastParseHadDecimal?0:kNoDecimal);
1776 //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits);
1777 digits
.set(parsedNum
.toStringPiece(),
1782 if (U_FAILURE(err
)) {
1784 printf(" err setting %s\n", u_errorName(err
));
1786 parsePosition
.setErrorIndex(position
);
1790 // check if we missed a required decimal point
1791 if(fastParseOk
&& isDecimalPatternMatchRequired())
1793 if(formatPattern
.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol
) != 0)
1795 parsePosition
.setIndex(oldStart
);
1796 parsePosition
.setErrorIndex(position
);
1797 debug("decimal point match required fail!");
1807 * Starting at position, advance past a run of pad characters, if any.
1808 * Return the index of the first character after position that is not a pad
1809 * character. Result is >= position.
1811 int32_t DecimalFormat::skipPadding(const UnicodeString
& text
, int32_t position
) const {
1812 int32_t padLen
= U16_LENGTH(fImpl
->fAffixes
.fPadChar
);
1813 while (position
< text
.length() &&
1814 text
.char32At(position
) == fImpl
->fAffixes
.fPadChar
) {
1821 * Return the length matched by the given affix, or -1 if none.
1822 * Runs of white space in the affix, match runs of white space in
1823 * the input. Pattern white space and input white space are
1824 * determined differently; see code.
1825 * @param text input text
1826 * @param pos offset into input at which to begin matching
1829 * @param affixPat affix pattern used for currency affix comparison.
1830 * @param complexCurrencyParsing whether it is currency parsing or not
1831 * @param type the currency type to parse against, LONG_NAME only or not.
1832 * @param currency return value for parsed currency, for generic
1833 * currency parsing mode, or null for normal parsing. In generic
1834 * currency parsing mode, any currency is parsed, not just the
1835 * currency that this formatter is set to.
1836 * @return length of input that matches, or -1 if match failure
1838 int32_t DecimalFormat::compareAffix(const UnicodeString
& text
,
1842 const UnicodeString
* affixPat
,
1843 UBool complexCurrencyParsing
,
1845 UChar
* currency
) const
1847 const UnicodeString
*patternToCompare
;
1848 if (currency
!= NULL
||
1849 (fImpl
->fMonetary
&& complexCurrencyParsing
)) {
1851 if (affixPat
!= NULL
) {
1852 return compareComplexAffix(*affixPat
, text
, pos
, type
, currency
);
1858 patternToCompare
= &fImpl
->fAffixes
.fNegativePrefix
.getOtherVariant().toString();
1861 patternToCompare
= &fImpl
->fAffixes
.fNegativeSuffix
.getOtherVariant().toString();
1866 patternToCompare
= &fImpl
->fAffixes
.fPositivePrefix
.getOtherVariant().toString();
1869 patternToCompare
= &fImpl
->fAffixes
.fPositiveSuffix
.getOtherVariant().toString();
1872 return compareSimpleAffix(*patternToCompare
, text
, pos
, isLenient());
1875 UBool
DecimalFormat::equalWithSignCompatibility(UChar32 lhs
, UChar32 rhs
) const {
1879 U_ASSERT(fStaticSets
!= NULL
); // should already be loaded
1880 const UnicodeSet
*minusSigns
= fStaticSets
->fMinusSigns
;
1881 const UnicodeSet
*plusSigns
= fStaticSets
->fPlusSigns
;
1882 return (minusSigns
->contains(lhs
) && minusSigns
->contains(rhs
)) ||
1883 (plusSigns
->contains(lhs
) && plusSigns
->contains(rhs
));
1886 // check for LRM 0x200E, RLM 0x200F, ALM 0x061C
1887 #define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C)
1889 #define TRIM_BUFLEN 32
1890 UnicodeString
& DecimalFormat::trimMarksFromAffix(const UnicodeString
& affix
, UnicodeString
& trimmedAffix
) {
1891 UChar trimBuf
[TRIM_BUFLEN
];
1892 int32_t affixLen
= affix
.length();
1893 int32_t affixPos
, trimLen
= 0;
1895 for (affixPos
= 0; affixPos
< affixLen
; affixPos
++) {
1896 UChar c
= affix
.charAt(affixPos
);
1897 if (!IS_BIDI_MARK(c
)) {
1898 if (trimLen
< TRIM_BUFLEN
) {
1899 trimBuf
[trimLen
++] = c
;
1906 return (trimLen
> 0)? trimmedAffix
.setTo(trimBuf
, trimLen
): trimmedAffix
.setTo(affix
);
1910 * Return the length matched by the given affix, or -1 if none.
1911 * Runs of white space in the affix, match runs of white space in
1912 * the input. Pattern white space and input white space are
1913 * determined differently; see code.
1914 * @param affix pattern string, taken as a literal
1915 * @param input input text
1916 * @param pos offset into input at which to begin matching
1917 * @return length of input that matches, or -1 if match failure
1919 int32_t DecimalFormat::compareSimpleAffix(const UnicodeString
& affix
,
1920 const UnicodeString
& input
,
1922 UBool lenient
) const {
1923 int32_t start
= pos
;
1924 UnicodeString trimmedAffix
;
1925 // For more efficiency we should keep lazily-created trimmed affixes around in
1926 // instance variables instead of trimming each time they are used (the next step)
1927 trimMarksFromAffix(affix
, trimmedAffix
);
1928 UChar32 affixChar
= trimmedAffix
.char32At(0);
1929 int32_t affixLength
= trimmedAffix
.length();
1930 int32_t inputLength
= input
.length();
1931 int32_t affixCharLength
= U16_LENGTH(affixChar
);
1932 UnicodeSet
*affixSet
;
1933 UErrorCode status
= U_ZERO_ERROR
;
1935 U_ASSERT(fStaticSets
!= NULL
); // should already be loaded
1937 if (U_FAILURE(status
)) {
1941 affixSet
= fStaticSets
->fStrictDashEquivalents
;
1943 // If the trimmedAffix is exactly one character long and that character
1944 // is in the dash set and the very next input character is also
1945 // in the dash set, return a match.
1946 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
1947 UChar32 ic
= input
.char32At(pos
);
1948 if (affixSet
->contains(ic
)) {
1949 pos
+= U16_LENGTH(ic
);
1950 pos
= skipBidiMarks(input
, pos
); // skip any trailing bidi marks
1955 for (int32_t i
= 0; i
< affixLength
; ) {
1956 UChar32 c
= trimmedAffix
.char32At(i
);
1957 int32_t len
= U16_LENGTH(c
);
1958 if (PatternProps::isWhiteSpace(c
)) {
1959 // We may have a pattern like: \u200F \u0020
1960 // and input text like: \u200F \u0020
1961 // Note that U+200F and U+0020 are Pattern_White_Space but only
1962 // U+0020 is UWhiteSpace. So we have to first do a direct
1963 // match of the run of Pattern_White_Space in the pattern,
1964 // then match any extra characters.
1965 UBool literalMatch
= FALSE
;
1966 while (pos
< inputLength
) {
1967 UChar32 ic
= input
.char32At(pos
);
1969 literalMatch
= TRUE
;
1972 if (i
== affixLength
) {
1975 c
= trimmedAffix
.char32At(i
);
1976 len
= U16_LENGTH(c
);
1977 if (!PatternProps::isWhiteSpace(c
)) {
1980 } else if (IS_BIDI_MARK(ic
)) {
1981 pos
++; // just skip over this input text
1987 // Advance over run in pattern
1988 i
= skipPatternWhiteSpace(trimmedAffix
, i
);
1990 // Advance over run in input text
1991 // Must see at least one white space char in input,
1992 // unless we've already matched some characters literally.
1994 pos
= skipUWhiteSpace(input
, pos
);
1995 if (pos
== s
&& !literalMatch
) {
1999 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
2000 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
2001 // is also in the trimmedAffix.
2002 i
= skipUWhiteSpace(trimmedAffix
, i
);
2004 UBool match
= FALSE
;
2005 while (pos
< inputLength
) {
2006 UChar32 ic
= input
.char32At(pos
);
2007 if (!match
&& ic
== c
) {
2011 } else if (IS_BIDI_MARK(ic
)) {
2012 pos
++; // just skip over this input text
2023 UBool match
= FALSE
;
2025 affixSet
= fStaticSets
->fDashEquivalents
;
2027 if (affixCharLength
== affixLength
&& affixSet
->contains(affixChar
)) {
2028 pos
= skipUWhiteSpaceAndMarks(input
, pos
);
2029 UChar32 ic
= input
.char32At(pos
);
2031 if (affixSet
->contains(ic
)) {
2032 pos
+= U16_LENGTH(ic
);
2033 pos
= skipBidiMarks(input
, pos
);
2038 for (int32_t i
= 0; i
< affixLength
; )
2040 //i = skipRuleWhiteSpace(trimmedAffix, i);
2041 i
= skipUWhiteSpace(trimmedAffix
, i
);
2042 pos
= skipUWhiteSpaceAndMarks(input
, pos
);
2044 if (i
>= affixLength
|| pos
>= inputLength
) {
2048 UChar32 c
= trimmedAffix
.char32At(i
);
2049 UChar32 ic
= input
.char32At(pos
);
2051 if (!equalWithSignCompatibility(ic
, c
)) {
2057 pos
+= U16_LENGTH(ic
);
2058 pos
= skipBidiMarks(input
, pos
);
2061 if (affixLength
> 0 && ! match
) {
2069 * Skip over a run of zero or more Pattern_White_Space characters at
2072 int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2073 const UChar
* s
= text
.getBuffer();
2074 return (int32_t)(PatternProps::skipWhiteSpace(s
+ pos
, text
.length() - pos
) - s
);
2078 * Skip over a run of zero or more isUWhiteSpace() characters at pos
2081 int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString
& text
, int32_t pos
) {
2082 while (pos
< text
.length()) {
2083 UChar32 c
= text
.char32At(pos
);
2084 if (!u_isUWhiteSpace(c
)) {
2087 pos
+= U16_LENGTH(c
);
2093 * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos
2096 int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString
& text
, int32_t pos
) {
2097 while (pos
< text
.length()) {
2098 UChar32 c
= text
.char32At(pos
);
2099 if (!u_isUWhiteSpace(c
) && !IS_BIDI_MARK(c
)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM
2102 pos
+= U16_LENGTH(c
);
2108 * Skip over a run of zero or more bidi marks at pos in text.
2110 int32_t DecimalFormat::skipBidiMarks(const UnicodeString
& text
, int32_t pos
) {
2111 while (pos
< text
.length()) {
2112 UChar c
= text
.charAt(pos
);
2113 if (!IS_BIDI_MARK(c
)) {
2122 * Return the length matched by the given affix, or -1 if none.
2123 * @param affixPat pattern string
2124 * @param input input text
2125 * @param pos offset into input at which to begin matching
2126 * @param type the currency type to parse against, LONG_NAME only or not.
2127 * @param currency return value for parsed currency, for generic
2128 * currency parsing mode, or null for normal parsing. In generic
2129 * currency parsing mode, any currency is parsed, not just the
2130 * currency that this formatter is set to.
2131 * @return length of input that matches, or -1 if match failure
2133 int32_t DecimalFormat::compareComplexAffix(const UnicodeString
& affixPat
,
2134 const UnicodeString
& text
,
2137 UChar
* currency
) const
2139 int32_t start
= pos
;
2140 U_ASSERT(currency
!= NULL
|| fImpl
->fMonetary
);
2143 i
<affixPat
.length() && pos
>= 0; ) {
2144 UChar32 c
= affixPat
.char32At(i
);
2148 U_ASSERT(i
<= affixPat
.length());
2149 c
= affixPat
.char32At(i
);
2152 const UnicodeString
* affix
= NULL
;
2155 case kCurrencySign
: {
2156 // since the currency names in choice format is saved
2157 // the same way as other currency names,
2158 // do not need to do currency choice parsing here.
2159 // the general currency parsing parse against all names,
2160 // including names in choice format.
2161 UBool intl
= i
<affixPat
.length() &&
2162 affixPat
.char32At(i
) == kCurrencySign
;
2166 UBool plural
= i
<affixPat
.length() &&
2167 affixPat
.char32At(i
) == kCurrencySign
;
2172 // Parse generic currency -- anything for which we
2173 // have a display name, or any 3-letter ISO code.
2174 // Try to parse display name for our locale; first
2175 // determine our locale.
2176 const char* loc
= fCurrencyPluralInfo
->getLocale().getName();
2177 ParsePosition
ppos(pos
);
2179 UErrorCode ec
= U_ZERO_ERROR
;
2180 // Delegate parse of display name => ISO code to Currency
2181 uprv_parseCurrency(loc
, text
, ppos
, type
, curr
, ec
);
2183 // If parse succeeds, populate currency[0]
2184 if (U_SUCCESS(ec
) && ppos
.getIndex() != pos
) {
2186 u_strcpy(currency
, curr
);
2188 // The formatter is currency-style but the client has not requested
2189 // the value of the parsed currency. In this case, if that value does
2190 // not match the formatter's current value, then the parse fails.
2191 UChar effectiveCurr
[4];
2192 getEffectiveCurrency(effectiveCurr
, ec
);
2193 if ( U_FAILURE(ec
) || u_strncmp(curr
,effectiveCurr
,4) != 0 ) {
2198 pos
= ppos
.getIndex();
2199 } else if (!isLenient()){
2204 case kPatternPercent
:
2205 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPercentSymbol
);
2207 case kPatternPerMill
:
2208 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol
);
2211 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol
);
2214 affix
= &fImpl
->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol
);
2217 // fall through to affix!=0 test, which will fail
2221 if (affix
!= NULL
) {
2222 pos
= match(text
, pos
, *affix
);
2227 pos
= match(text
, pos
, c
);
2228 if (PatternProps::isWhiteSpace(c
)) {
2229 i
= skipPatternWhiteSpace(affixPat
, i
);
2236 * Match a single character at text[pos] and return the index of the
2237 * next character upon success. Return -1 on failure. If
2238 * ch is a Pattern_White_Space then match a run of white space in text.
2240 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, UChar32 ch
) {
2241 if (PatternProps::isWhiteSpace(ch
)) {
2242 // Advance over run of white space in input text
2243 // Must see at least one white space char in input
2245 pos
= skipPatternWhiteSpace(text
, pos
);
2251 return (pos
>= 0 && text
.char32At(pos
) == ch
) ?
2252 (pos
+ U16_LENGTH(ch
)) : -1;
2256 * Match a string at text[pos] and return the index of the next
2257 * character upon success. Return -1 on failure. Match a run of
2258 * white space in str with a run of white space in text.
2260 int32_t DecimalFormat::match(const UnicodeString
& text
, int32_t pos
, const UnicodeString
& str
) {
2261 for (int32_t i
=0; i
<str
.length() && pos
>= 0; ) {
2262 UChar32 ch
= str
.char32At(i
);
2263 i
+= U16_LENGTH(ch
);
2264 if (PatternProps::isWhiteSpace(ch
)) {
2265 i
= skipPatternWhiteSpace(str
, i
);
2267 pos
= match(text
, pos
, ch
);
2272 UBool
DecimalFormat::matchSymbol(const UnicodeString
&text
, int32_t position
, int32_t length
, const UnicodeString
&symbol
,
2273 UnicodeSet
*sset
, UChar32 schar
)
2276 return sset
->contains(schar
);
2279 return text
.compare(position
, length
, symbol
) == 0;
2282 UBool
DecimalFormat::matchDecimal(UChar32 symbolChar
,
2283 UBool sawDecimal
, UChar32 sawDecimalChar
,
2284 const UnicodeSet
*sset
, UChar32 schar
) {
2286 return schar
==sawDecimalChar
;
2287 } else if(schar
==symbolChar
) {
2289 } else if(sset
!=NULL
) {
2290 return sset
->contains(schar
);
2296 UBool
DecimalFormat::matchGrouping(UChar32 groupingChar
,
2297 UBool sawGrouping
, UChar32 sawGroupingChar
,
2298 const UnicodeSet
*sset
,
2299 UChar32
/*decimalChar*/, const UnicodeSet
*decimalSet
,
2302 return schar
==sawGroupingChar
; // previously found
2303 } else if(schar
==groupingChar
) {
2304 return TRUE
; // char from symbols
2305 } else if(sset
!=NULL
) {
2306 return sset
->contains(schar
) && // in groupingSet but...
2307 ((decimalSet
==NULL
) || !decimalSet
->contains(schar
)); // Exclude decimalSet from groupingSet
2315 //------------------------------------------------------------------------------
2316 // Gets the pointer to the localized decimal format symbols
2318 const DecimalFormatSymbols
*
2319 DecimalFormat::getDecimalFormatSymbols() const
2321 return &fImpl
->getDecimalFormatSymbols();
2324 //------------------------------------------------------------------------------
2325 // De-owning the current localized symbols and adopt the new symbols.
2328 DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols
* symbolsToAdopt
)
2330 if (symbolsToAdopt
== NULL
) {
2331 return; // do not allow caller to set fSymbols to NULL
2333 fImpl
->adoptDecimalFormatSymbols(symbolsToAdopt
);
2335 //------------------------------------------------------------------------------
2336 // Setting the symbols is equlivalent to adopting a newly created localized
2340 DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols
& symbols
)
2342 adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols
));
2346 const CurrencyPluralInfo
*
2347 DecimalFormat::getCurrencyPluralInfo(void) const
2349 return fCurrencyPluralInfo
;
2354 DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo
* toAdopt
)
2356 if (toAdopt
!= NULL
) {
2357 delete fCurrencyPluralInfo
;
2358 fCurrencyPluralInfo
= toAdopt
;
2359 // re-set currency affix patterns and currency affixes.
2360 if (fImpl
->fMonetary
) {
2361 UErrorCode status
= U_ZERO_ERROR
;
2362 if (fAffixPatternsForCurrency
) {
2363 deleteHashForAffixPattern();
2365 setupCurrencyAffixPatterns(status
);
2371 DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo
& info
)
2373 adoptCurrencyPluralInfo(info
.clone());
2377 //------------------------------------------------------------------------------
2378 // Gets the positive prefix of the number pattern.
2381 DecimalFormat::getPositivePrefix(UnicodeString
& result
) const
2383 return fImpl
->getPositivePrefix(result
);
2386 //------------------------------------------------------------------------------
2387 // Sets the positive prefix of the number pattern.
2390 DecimalFormat::setPositivePrefix(const UnicodeString
& newValue
)
2392 fImpl
->setPositivePrefix(newValue
);
2395 //------------------------------------------------------------------------------
2396 // Gets the negative prefix of the number pattern.
2399 DecimalFormat::getNegativePrefix(UnicodeString
& result
) const
2401 return fImpl
->getNegativePrefix(result
);
2404 //------------------------------------------------------------------------------
2405 // Gets the negative prefix of the number pattern.
2408 DecimalFormat::setNegativePrefix(const UnicodeString
& newValue
)
2410 fImpl
->setNegativePrefix(newValue
);
2413 //------------------------------------------------------------------------------
2414 // Gets the positive suffix of the number pattern.
2417 DecimalFormat::getPositiveSuffix(UnicodeString
& result
) const
2419 return fImpl
->getPositiveSuffix(result
);
2422 //------------------------------------------------------------------------------
2423 // Sets the positive suffix of the number pattern.
2426 DecimalFormat::setPositiveSuffix(const UnicodeString
& newValue
)
2428 fImpl
->setPositiveSuffix(newValue
);
2431 //------------------------------------------------------------------------------
2432 // Gets the negative suffix of the number pattern.
2435 DecimalFormat::getNegativeSuffix(UnicodeString
& result
) const
2437 return fImpl
->getNegativeSuffix(result
);
2440 //------------------------------------------------------------------------------
2441 // Sets the negative suffix of the number pattern.
2444 DecimalFormat::setNegativeSuffix(const UnicodeString
& newValue
)
2446 fImpl
->setNegativeSuffix(newValue
);
2449 //------------------------------------------------------------------------------
2450 // Gets the multiplier of the number pattern.
2451 // Multipliers are stored as decimal numbers (DigitLists) because that
2452 // is the most convenient for muliplying or dividing the numbers to be formatted.
2453 // A NULL multiplier implies one, and the scaling operations are skipped.
2456 DecimalFormat::getMultiplier() const
2458 return fImpl
->getMultiplier();
2461 //------------------------------------------------------------------------------
2462 // Sets the multiplier of the number pattern.
2464 DecimalFormat::setMultiplier(int32_t newValue
)
2466 fImpl
->setMultiplier(newValue
);
2470 * Get the rounding increment.
2471 * @return A positive rounding increment, or 0.0 if rounding
2473 * @see #setRoundingIncrement
2474 * @see #getRoundingMode
2475 * @see #setRoundingMode
2477 double DecimalFormat::getRoundingIncrement() const {
2478 return fImpl
->getRoundingIncrement();
2482 * Set the rounding increment. This method also controls whether
2483 * rounding is enabled.
2484 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
2485 * Negative increments are equivalent to 0.0.
2486 * @see #getRoundingIncrement
2487 * @see #getRoundingMode
2488 * @see #setRoundingMode
2490 void DecimalFormat::setRoundingIncrement(double newValue
) {
2491 fImpl
->setRoundingIncrement(newValue
);
2495 * Get the rounding mode.
2496 * @return A rounding mode
2497 * @see #setRoundingIncrement
2498 * @see #getRoundingIncrement
2499 * @see #setRoundingMode
2501 DecimalFormat::ERoundingMode
DecimalFormat::getRoundingMode() const {
2502 return fImpl
->getRoundingMode();
2506 * Set the rounding mode. This has no effect unless the rounding
2507 * increment is greater than zero.
2508 * @param roundingMode A rounding mode
2509 * @see #setRoundingIncrement
2510 * @see #getRoundingIncrement
2511 * @see #getRoundingMode
2513 void DecimalFormat::setRoundingMode(ERoundingMode roundingMode
) {
2514 fImpl
->setRoundingMode(roundingMode
);
2518 * Get the width to which the output of <code>format()</code> is padded.
2519 * @return the format width, or zero if no padding is in effect
2520 * @see #setFormatWidth
2521 * @see #getPadCharacter
2522 * @see #setPadCharacter
2523 * @see #getPadPosition
2524 * @see #setPadPosition
2526 int32_t DecimalFormat::getFormatWidth() const {
2527 return fImpl
->getFormatWidth();
2531 * Set the width to which the output of <code>format()</code> is padded.
2532 * This method also controls whether padding is enabled.
2533 * @param width the width to which to pad the result of
2534 * <code>format()</code>, or zero to disable padding. A negative
2535 * width is equivalent to 0.
2536 * @see #getFormatWidth
2537 * @see #getPadCharacter
2538 * @see #setPadCharacter
2539 * @see #getPadPosition
2540 * @see #setPadPosition
2542 void DecimalFormat::setFormatWidth(int32_t width
) {
2543 int32_t formatWidth
= (width
> 0) ? width
: 0;
2544 fImpl
->setFormatWidth(formatWidth
);
2547 UnicodeString
DecimalFormat::getPadCharacterString() const {
2548 return UnicodeString(fImpl
->getPadCharacter());
2551 void DecimalFormat::setPadCharacter(const UnicodeString
&padChar
) {
2553 if (padChar
.length() > 0) {
2554 pad
= padChar
.char32At(0);
2559 fImpl
->setPadCharacter(pad
);
2562 static DecimalFormat::EPadPosition
fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos
) {
2564 case DigitAffixesAndPadding::kPadBeforePrefix
:
2565 return DecimalFormat::kPadBeforePrefix
;
2566 case DigitAffixesAndPadding::kPadAfterPrefix
:
2567 return DecimalFormat::kPadAfterPrefix
;
2568 case DigitAffixesAndPadding::kPadBeforeSuffix
:
2569 return DecimalFormat::kPadBeforeSuffix
;
2570 case DigitAffixesAndPadding::kPadAfterSuffix
:
2571 return DecimalFormat::kPadAfterSuffix
;
2576 return DecimalFormat::kPadBeforePrefix
;
2580 * Get the position at which padding will take place. This is the location
2581 * at which padding will be inserted if the result of <code>format()</code>
2582 * is shorter than the format width.
2583 * @return the pad position, one of <code>kPadBeforePrefix</code>,
2584 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2585 * <code>kPadAfterSuffix</code>.
2586 * @see #setFormatWidth
2587 * @see #getFormatWidth
2588 * @see #setPadCharacter
2589 * @see #getPadCharacter
2590 * @see #setPadPosition
2591 * @see #kPadBeforePrefix
2592 * @see #kPadAfterPrefix
2593 * @see #kPadBeforeSuffix
2594 * @see #kPadAfterSuffix
2596 DecimalFormat::EPadPosition
DecimalFormat::getPadPosition() const {
2597 return fromPadPosition(fImpl
->getPadPosition());
2600 static DigitAffixesAndPadding::EPadPosition
toPadPosition(DecimalFormat::EPadPosition padPos
) {
2602 case DecimalFormat::kPadBeforePrefix
:
2603 return DigitAffixesAndPadding::kPadBeforePrefix
;
2604 case DecimalFormat::kPadAfterPrefix
:
2605 return DigitAffixesAndPadding::kPadAfterPrefix
;
2606 case DecimalFormat::kPadBeforeSuffix
:
2607 return DigitAffixesAndPadding::kPadBeforeSuffix
;
2608 case DecimalFormat::kPadAfterSuffix
:
2609 return DigitAffixesAndPadding::kPadAfterSuffix
;
2614 return DigitAffixesAndPadding::kPadBeforePrefix
;
2618 * <strong><font face=helvetica color=red>NEW</font></strong>
2619 * Set the position at which padding will take place. This is the location
2620 * at which padding will be inserted if the result of <code>format()</code>
2621 * is shorter than the format width. This has no effect unless padding is
2623 * @param padPos the pad position, one of <code>kPadBeforePrefix</code>,
2624 * <code>kPadAfterPrefix</code>, <code>kPadBeforeSuffix</code>, or
2625 * <code>kPadAfterSuffix</code>.
2626 * @see #setFormatWidth
2627 * @see #getFormatWidth
2628 * @see #setPadCharacter
2629 * @see #getPadCharacter
2630 * @see #getPadPosition
2631 * @see #kPadBeforePrefix
2632 * @see #kPadAfterPrefix
2633 * @see #kPadBeforeSuffix
2634 * @see #kPadAfterSuffix
2636 void DecimalFormat::setPadPosition(EPadPosition padPos
) {
2637 fImpl
->setPadPosition(toPadPosition(padPos
));
2641 * Return whether or not scientific notation is used.
2642 * @return TRUE if this object formats and parses scientific notation
2643 * @see #setScientificNotation
2644 * @see #getMinimumExponentDigits
2645 * @see #setMinimumExponentDigits
2646 * @see #isExponentSignAlwaysShown
2647 * @see #setExponentSignAlwaysShown
2649 UBool
DecimalFormat::isScientificNotation() const {
2650 return fImpl
->isScientificNotation();
2654 * Set whether or not scientific notation is used.
2655 * @param useScientific TRUE if this object formats and parses scientific
2657 * @see #isScientificNotation
2658 * @see #getMinimumExponentDigits
2659 * @see #setMinimumExponentDigits
2660 * @see #isExponentSignAlwaysShown
2661 * @see #setExponentSignAlwaysShown
2663 void DecimalFormat::setScientificNotation(UBool useScientific
) {
2664 fImpl
->setScientificNotation(useScientific
);
2668 * Return the minimum exponent digits that will be shown.
2669 * @return the minimum exponent digits that will be shown
2670 * @see #setScientificNotation
2671 * @see #isScientificNotation
2672 * @see #setMinimumExponentDigits
2673 * @see #isExponentSignAlwaysShown
2674 * @see #setExponentSignAlwaysShown
2676 int8_t DecimalFormat::getMinimumExponentDigits() const {
2677 return fImpl
->getMinimumExponentDigits();
2681 * Set the minimum exponent digits that will be shown. This has no
2682 * effect unless scientific notation is in use.
2683 * @param minExpDig a value >= 1 indicating the fewest exponent digits
2684 * that will be shown. Values less than 1 will be treated as 1.
2685 * @see #setScientificNotation
2686 * @see #isScientificNotation
2687 * @see #getMinimumExponentDigits
2688 * @see #isExponentSignAlwaysShown
2689 * @see #setExponentSignAlwaysShown
2691 void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig
) {
2692 int32_t minExponentDigits
= (int8_t)((minExpDig
> 0) ? minExpDig
: 1);
2693 fImpl
->setMinimumExponentDigits(minExponentDigits
);
2697 * Return whether the exponent sign is always shown.
2698 * @return TRUE if the exponent is always prefixed with either the
2699 * localized minus sign or the localized plus sign, false if only negative
2700 * exponents are prefixed with the localized minus sign.
2701 * @see #setScientificNotation
2702 * @see #isScientificNotation
2703 * @see #setMinimumExponentDigits
2704 * @see #getMinimumExponentDigits
2705 * @see #setExponentSignAlwaysShown
2707 UBool
DecimalFormat::isExponentSignAlwaysShown() const {
2708 return fImpl
->isExponentSignAlwaysShown();
2712 * Set whether the exponent sign is always shown. This has no effect
2713 * unless scientific notation is in use.
2714 * @param expSignAlways TRUE if the exponent is always prefixed with either
2715 * the localized minus sign or the localized plus sign, false if only
2716 * negative exponents are prefixed with the localized minus sign.
2717 * @see #setScientificNotation
2718 * @see #isScientificNotation
2719 * @see #setMinimumExponentDigits
2720 * @see #getMinimumExponentDigits
2721 * @see #isExponentSignAlwaysShown
2723 void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways
) {
2724 fImpl
->setExponentSignAlwaysShown(expSignAlways
);
2727 //------------------------------------------------------------------------------
2728 // Gets the grouping size of the number pattern. For example, thousand or 10
2729 // thousand groupings.
2732 DecimalFormat::getGroupingSize() const
2734 return fImpl
->getGroupingSize();
2737 //------------------------------------------------------------------------------
2738 // Gets the grouping size of the number pattern.
2741 DecimalFormat::setGroupingSize(int32_t newValue
)
2743 fImpl
->setGroupingSize(newValue
);
2746 //------------------------------------------------------------------------------
2749 DecimalFormat::getSecondaryGroupingSize() const
2751 return fImpl
->getSecondaryGroupingSize();
2754 //------------------------------------------------------------------------------
2757 DecimalFormat::setSecondaryGroupingSize(int32_t newValue
)
2759 fImpl
->setSecondaryGroupingSize(newValue
);
2762 //------------------------------------------------------------------------------
2765 DecimalFormat::getMinimumGroupingDigits() const
2767 return fImpl
->getMinimumGroupingDigits();
2770 //------------------------------------------------------------------------------
2773 DecimalFormat::setMinimumGroupingDigits(int32_t newValue
)
2775 fImpl
->setMinimumGroupingDigits(newValue
);
2778 //------------------------------------------------------------------------------
2779 // Checks if to show the decimal separator.
2782 DecimalFormat::isDecimalSeparatorAlwaysShown() const
2784 return fImpl
->isDecimalSeparatorAlwaysShown();
2787 //------------------------------------------------------------------------------
2788 // Sets to always show the decimal separator.
2791 DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue
)
2793 fImpl
->setDecimalSeparatorAlwaysShown(newValue
);
2796 //------------------------------------------------------------------------------
2797 // Checks if decimal point pattern match is required
2799 DecimalFormat::isDecimalPatternMatchRequired(void) const
2801 return fBoolFlags
.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED
);
2804 //------------------------------------------------------------------------------
2805 // Checks if decimal point pattern match is required
2808 DecimalFormat::setDecimalPatternMatchRequired(UBool newValue
)
2810 fBoolFlags
.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED
, newValue
);
2814 //------------------------------------------------------------------------------
2815 // Emits the pattern of this DecimalFormat instance.
2818 DecimalFormat::toPattern(UnicodeString
& result
) const
2820 return fImpl
->toPattern(result
);
2823 //------------------------------------------------------------------------------
2824 // Emits the localized pattern this DecimalFormat instance.
2827 DecimalFormat::toLocalizedPattern(UnicodeString
& result
) const
2829 // toLocalizedPattern is deprecated, so we just make it the same as
2831 return fImpl
->toPattern(result
);
2834 //------------------------------------------------------------------------------
2837 DecimalFormat::applyPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
2839 if (pattern
.indexOf(kCurrencySign
) != -1) {
2840 handleCurrencySignInPattern(status
);
2842 fImpl
->applyPattern(pattern
, status
);
2845 //------------------------------------------------------------------------------
2848 DecimalFormat::applyPattern(const UnicodeString
& pattern
,
2849 UParseError
& parseError
,
2852 if (pattern
.indexOf(kCurrencySign
) != -1) {
2853 handleCurrencySignInPattern(status
);
2855 fImpl
->applyPattern(pattern
, parseError
, status
);
2857 //------------------------------------------------------------------------------
2860 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
, UErrorCode
& status
)
2862 if (pattern
.indexOf(kCurrencySign
) != -1) {
2863 handleCurrencySignInPattern(status
);
2865 fImpl
->applyLocalizedPattern(pattern
, status
);
2868 //------------------------------------------------------------------------------
2871 DecimalFormat::applyLocalizedPattern(const UnicodeString
& pattern
,
2872 UParseError
& parseError
,
2875 if (pattern
.indexOf(kCurrencySign
) != -1) {
2876 handleCurrencySignInPattern(status
);
2878 fImpl
->applyLocalizedPattern(pattern
, parseError
, status
);
2881 //------------------------------------------------------------------------------
2884 * Sets the maximum number of digits allowed in the integer portion of a
2886 * @see NumberFormat#setMaximumIntegerDigits
2888 void DecimalFormat::setMaximumIntegerDigits(int32_t newValue
) {
2889 newValue
= _min(newValue
, gDefaultMaxIntegerDigits
);
2890 NumberFormat::setMaximumIntegerDigits(newValue
);
2891 fImpl
->updatePrecision();
2895 * Sets the minimum number of digits allowed in the integer portion of a
2896 * number. This override limits the integer digit count to 309.
2897 * @see NumberFormat#setMinimumIntegerDigits
2899 void DecimalFormat::setMinimumIntegerDigits(int32_t newValue
) {
2900 newValue
= _min(newValue
, kDoubleIntegerDigits
);
2901 NumberFormat::setMinimumIntegerDigits(newValue
);
2902 fImpl
->updatePrecision();
2906 * Sets the maximum number of digits allowed in the fraction portion of a
2907 * number. This override limits the fraction digit count to 340.
2908 * @see NumberFormat#setMaximumFractionDigits
2910 void DecimalFormat::setMaximumFractionDigits(int32_t newValue
) {
2911 newValue
= _min(newValue
, kDoubleFractionDigits
);
2912 NumberFormat::setMaximumFractionDigits(newValue
);
2913 fImpl
->updatePrecision();
2917 * Sets the minimum number of digits allowed in the fraction portion of a
2918 * number. This override limits the fraction digit count to 340.
2919 * @see NumberFormat#setMinimumFractionDigits
2921 void DecimalFormat::setMinimumFractionDigits(int32_t newValue
) {
2922 newValue
= _min(newValue
, kDoubleFractionDigits
);
2923 NumberFormat::setMinimumFractionDigits(newValue
);
2924 fImpl
->updatePrecision();
2927 int32_t DecimalFormat::getMinimumSignificantDigits() const {
2928 return fImpl
->getMinimumSignificantDigits();
2931 int32_t DecimalFormat::getMaximumSignificantDigits() const {
2932 return fImpl
->getMaximumSignificantDigits();
2935 void DecimalFormat::setMinimumSignificantDigits(int32_t min
) {
2939 // pin max sig dig to >= min
2940 int32_t max
= _max(fImpl
->fMaxSigDigits
, min
);
2941 fImpl
->setMinMaxSignificantDigits(min
, max
);
2944 void DecimalFormat::setMaximumSignificantDigits(int32_t max
) {
2948 // pin min sig dig to 1..max
2949 U_ASSERT(fImpl
->fMinSigDigits
>= 1);
2950 int32_t min
= _min(fImpl
->fMinSigDigits
, max
);
2951 fImpl
->setMinMaxSignificantDigits(min
, max
);
2954 UBool
DecimalFormat::areSignificantDigitsUsed() const {
2955 return fImpl
->areSignificantDigitsUsed();
2958 void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits
) {
2959 fImpl
->setSignificantDigitsUsed(useSignificantDigits
);
2962 void DecimalFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
2963 // set the currency before compute affixes to get the right currency names
2964 NumberFormat::setCurrency(theCurrency
, ec
);
2965 fImpl
->updateCurrency(ec
);
2968 void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext
, UErrorCode
* ec
){
2969 fImpl
->setCurrencyUsage(newContext
, *ec
);
2972 UCurrencyUsage
DecimalFormat::getCurrencyUsage() const {
2973 return fImpl
->getCurrencyUsage();
2976 // Deprecated variant with no UErrorCode parameter
2977 void DecimalFormat::setCurrency(const UChar
* theCurrency
) {
2978 UErrorCode ec
= U_ZERO_ERROR
;
2979 setCurrency(theCurrency
, ec
);
2982 void DecimalFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
2983 if (fImpl
->fSymbols
== NULL
) {
2984 ec
= U_MEMORY_ALLOCATION_ERROR
;
2988 const UChar
* c
= getCurrency();
2990 const UnicodeString
&intl
=
2991 fImpl
->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
2992 c
= intl
.getBuffer(); // ok for intl to go out of scope
2994 u_strncpy(result
, c
, 3);
2999 DecimalFormat::initHashForAffixPattern(UErrorCode
& status
) {
3000 if ( U_FAILURE(status
) ) {
3004 if ( (hTable
= new Hashtable(TRUE
, status
)) == NULL
) {
3005 status
= U_MEMORY_ALLOCATION_ERROR
;
3008 if ( U_FAILURE(status
) ) {
3012 hTable
->setValueComparator(decimfmtAffixPatternValueComparator
);
3017 DecimalFormat::deleteHashForAffixPattern()
3019 if ( fAffixPatternsForCurrency
== NULL
) {
3022 int32_t pos
= UHASH_FIRST
;
3023 const UHashElement
* element
= NULL
;
3024 while ( (element
= fAffixPatternsForCurrency
->nextElement(pos
)) != NULL
) {
3025 const UHashTok valueTok
= element
->value
;
3026 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
3029 delete fAffixPatternsForCurrency
;
3030 fAffixPatternsForCurrency
= NULL
;
3035 DecimalFormat::copyHashForAffixPattern(const Hashtable
* source
,
3037 UErrorCode
& status
) {
3038 if ( U_FAILURE(status
) ) {
3041 int32_t pos
= UHASH_FIRST
;
3042 const UHashElement
* element
= NULL
;
3044 while ( (element
= source
->nextElement(pos
)) != NULL
) {
3045 const UHashTok keyTok
= element
->key
;
3046 const UnicodeString
* key
= (UnicodeString
*)keyTok
.pointer
;
3047 const UHashTok valueTok
= element
->value
;
3048 const AffixPatternsForCurrency
* value
= (AffixPatternsForCurrency
*)valueTok
.pointer
;
3049 AffixPatternsForCurrency
* copy
= new AffixPatternsForCurrency(
3050 value
->negPrefixPatternForCurrency
,
3051 value
->negSuffixPatternForCurrency
,
3052 value
->posPrefixPatternForCurrency
,
3053 value
->posSuffixPatternForCurrency
,
3054 value
->patternType
);
3055 target
->put(UnicodeString(*key
), copy
, status
);
3056 if ( U_FAILURE(status
) ) {
3064 DecimalFormat::setGroupingUsed(UBool newValue
) {
3065 NumberFormat::setGroupingUsed(newValue
);
3066 fImpl
->updateGrouping();
3070 DecimalFormat::setParseIntegerOnly(UBool newValue
) {
3071 NumberFormat::setParseIntegerOnly(newValue
);
3075 DecimalFormat::setContext(UDisplayContext value
, UErrorCode
& status
) {
3076 NumberFormat::setContext(value
, status
);
3079 DecimalFormat
& DecimalFormat::setAttribute( UNumberFormatAttribute attr
,
3081 UErrorCode
&status
) {
3082 if(U_FAILURE(status
)) return *this;
3085 case UNUM_LENIENT_PARSE
:
3086 setLenient(newValue
!=0);
3089 case UNUM_PARSE_INT_ONLY
:
3090 setParseIntegerOnly(newValue
!=0);
3093 case UNUM_GROUPING_USED
:
3094 setGroupingUsed(newValue
!=0);
3097 case UNUM_DECIMAL_ALWAYS_SHOWN
:
3098 setDecimalSeparatorAlwaysShown(newValue
!=0);
3101 case UNUM_MAX_INTEGER_DIGITS
:
3102 setMaximumIntegerDigits(newValue
);
3105 case UNUM_MIN_INTEGER_DIGITS
:
3106 setMinimumIntegerDigits(newValue
);
3109 case UNUM_INTEGER_DIGITS
:
3110 setMinimumIntegerDigits(newValue
);
3111 setMaximumIntegerDigits(newValue
);
3114 case UNUM_MAX_FRACTION_DIGITS
:
3115 setMaximumFractionDigits(newValue
);
3118 case UNUM_MIN_FRACTION_DIGITS
:
3119 setMinimumFractionDigits(newValue
);
3122 case UNUM_FRACTION_DIGITS
:
3123 setMinimumFractionDigits(newValue
);
3124 setMaximumFractionDigits(newValue
);
3127 case UNUM_SIGNIFICANT_DIGITS_USED
:
3128 setSignificantDigitsUsed(newValue
!=0);
3131 case UNUM_MAX_SIGNIFICANT_DIGITS
:
3132 setMaximumSignificantDigits(newValue
);
3135 case UNUM_MIN_SIGNIFICANT_DIGITS
:
3136 setMinimumSignificantDigits(newValue
);
3139 case UNUM_MULTIPLIER
:
3140 setMultiplier(newValue
);
3143 case UNUM_GROUPING_SIZE
:
3144 setGroupingSize(newValue
);
3147 case UNUM_ROUNDING_MODE
:
3148 setRoundingMode((DecimalFormat::ERoundingMode
)newValue
);
3151 case UNUM_FORMAT_WIDTH
:
3152 setFormatWidth(newValue
);
3155 case UNUM_PADDING_POSITION
:
3156 /** The position at which padding will take place. */
3157 setPadPosition((DecimalFormat::EPadPosition
)newValue
);
3160 case UNUM_SECONDARY_GROUPING_SIZE
:
3161 setSecondaryGroupingSize(newValue
);
3164 #if UCONFIG_HAVE_PARSEALLINPUT
3165 case UNUM_PARSE_ALL_INPUT
:
3166 setParseAllInput((UNumberFormatAttributeValue
)newValue
);
3170 /* These are stored in fBoolFlags */
3171 case UNUM_PARSE_NO_EXPONENT
:
3172 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
3173 case UNUM_PARSE_DECIMAL_MARK_REQUIRED
:
3174 if(!fBoolFlags
.isValidValue(newValue
)) {
3175 status
= U_ILLEGAL_ARGUMENT_ERROR
;
3177 if (attr
== UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
) {
3178 fImpl
->setFailIfMoreThanMaxDigits((UBool
) newValue
);
3180 fBoolFlags
.set(attr
, newValue
);
3185 fImpl
->setScale(newValue
);
3188 case UNUM_CURRENCY_USAGE
:
3189 setCurrencyUsage((UCurrencyUsage
)newValue
, &status
);
3192 case UNUM_MINIMUM_GROUPING_DIGITS
:
3193 setMinimumGroupingDigits(newValue
);
3197 status
= U_UNSUPPORTED_ERROR
;
3203 int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr
,
3204 UErrorCode
&status
) const {
3205 if(U_FAILURE(status
)) return -1;
3207 case UNUM_LENIENT_PARSE
:
3210 case UNUM_PARSE_INT_ONLY
:
3211 return isParseIntegerOnly();
3213 case UNUM_GROUPING_USED
:
3214 return isGroupingUsed();
3216 case UNUM_DECIMAL_ALWAYS_SHOWN
:
3217 return isDecimalSeparatorAlwaysShown();
3219 case UNUM_MAX_INTEGER_DIGITS
:
3220 return getMaximumIntegerDigits();
3222 case UNUM_MIN_INTEGER_DIGITS
:
3223 return getMinimumIntegerDigits();
3225 case UNUM_INTEGER_DIGITS
:
3226 // TBD: what should this return?
3227 return getMinimumIntegerDigits();
3229 case UNUM_MAX_FRACTION_DIGITS
:
3230 return getMaximumFractionDigits();
3232 case UNUM_MIN_FRACTION_DIGITS
:
3233 return getMinimumFractionDigits();
3235 case UNUM_FRACTION_DIGITS
:
3236 // TBD: what should this return?
3237 return getMinimumFractionDigits();
3239 case UNUM_SIGNIFICANT_DIGITS_USED
:
3240 return areSignificantDigitsUsed();
3242 case UNUM_MAX_SIGNIFICANT_DIGITS
:
3243 return getMaximumSignificantDigits();
3245 case UNUM_MIN_SIGNIFICANT_DIGITS
:
3246 return getMinimumSignificantDigits();
3248 case UNUM_MULTIPLIER
:
3249 return getMultiplier();
3251 case UNUM_GROUPING_SIZE
:
3252 return getGroupingSize();
3254 case UNUM_ROUNDING_MODE
:
3255 return getRoundingMode();
3257 case UNUM_FORMAT_WIDTH
:
3258 return getFormatWidth();
3260 case UNUM_PADDING_POSITION
:
3261 return getPadPosition();
3263 case UNUM_SECONDARY_GROUPING_SIZE
:
3264 return getSecondaryGroupingSize();
3266 /* These are stored in fBoolFlags */
3267 case UNUM_PARSE_NO_EXPONENT
:
3268 case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS
:
3269 case UNUM_PARSE_DECIMAL_MARK_REQUIRED
:
3270 return fBoolFlags
.get(attr
);
3273 return fImpl
->fScale
;
3275 case UNUM_CURRENCY_USAGE
:
3276 return fImpl
->getCurrencyUsage();
3278 case UNUM_MINIMUM_GROUPING_DIGITS
:
3279 return getMinimumGroupingDigits();
3282 status
= U_UNSUPPORTED_ERROR
;
3286 return -1; /* undefined */
3289 #if UCONFIG_HAVE_PARSEALLINPUT
3290 void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value
) {
3291 fParseAllInput
= value
;
3297 #endif /* #if !UCONFIG_NO_FORMATTING */