1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
5 * Copyright (C) 1997-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
11 * Modification History:
13 * Date Name Description
14 * 02/19/97 aliu Converted from java.
15 * 03/18/97 clhuang Implemented with C++ APIs.
16 * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accomodate the
17 * largest double, by default.
18 * Changed DigitCount to int per code review.
19 * 07/20/98 stephen Changed operator== to check for grouping
20 * Changed setMaxIntegerDigits per Java implementation.
21 * Changed setMinIntegerDigits per Java implementation.
22 * Changed setMinFractionDigits per Java implementation.
23 * Changed setMaxFractionDigits per Java implementation.
24 ********************************************************************************
27 #include "unicode/utypes.h"
29 #if !UCONFIG_NO_FORMATTING
31 #include "unicode/numfmt.h"
32 #include "unicode/locid.h"
33 #include "unicode/dcfmtsym.h"
34 #include "unicode/decimfmt.h"
35 #include "unicode/ustring.h"
36 #include "unicode/ucurr.h"
37 #include "unicode/curramt.h"
38 #include "unicode/numsys.h"
39 #include "unicode/rbnf.h"
40 #include "unicode/localpointer.h"
41 #include "unicode/udisplaycontext.h"
55 #include "sharednumberformat.h"
56 #include "unifiedcache.h"
57 #include "number_decimalquantity.h"
58 #include "number_utils.h"
64 static inline void debugout(UnicodeString s
) {
66 s
.extract((int32_t) 0, s
.length(), buf
);
69 #define debug(x) printf("%s", x);
75 // If no number pattern can be located for a locale, this is the last
76 // resort. The patterns are same as the ones in root locale.
77 static const UChar gLastResortDecimalPat
[] = {
78 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */
80 static const UChar gLastResortCurrencyPat
[] = {
81 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
83 static const UChar gLastResortPercentPat
[] = {
84 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */
86 static const UChar gLastResortScientificPat
[] = {
87 0x23, 0x45, 0x30, 0 /* "#E0" */
89 static const UChar gLastResortIsoCurrencyPat
[] = {
90 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */
92 static const UChar gLastResortPluralCurrencyPat
[] = {
93 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/
95 static const UChar gLastResortAccountingCurrencyPat
[] = {
96 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
99 static const UChar gSingleCurrencySign
[] = {0xA4, 0};
100 static const UChar gDoubleCurrencySign
[] = {0xA4, 0xA4, 0};
102 static const UChar gSlash
= 0x2f;
104 // If the maximum base 10 exponent were 4, then the largest number would
105 // be 99,999 which has 5 digits.
106 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
107 // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999
108 const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits
= 2000000000;
109 const int32_t icu::NumberFormat::gDefaultMinIntegerDigits
= 127;
111 static const UChar
* const gLastResortNumberPatterns
[UNUM_FORMAT_STYLE_COUNT
] = {
112 NULL
, // UNUM_PATTERN_DECIMAL
113 gLastResortDecimalPat
, // UNUM_DECIMAL
114 gLastResortCurrencyPat
, // UNUM_CURRENCY
115 gLastResortPercentPat
, // UNUM_PERCENT
116 gLastResortScientificPat
, // UNUM_SCIENTIFIC
117 NULL
, // UNUM_SPELLOUT
118 NULL
, // UNUM_ORDINAL
119 NULL
, // UNUM_DURATION
120 NULL
, // UNUM_NUMBERING_SYSTEM
121 NULL
, // UNUM_PATTERN_RULEBASED
122 gLastResortIsoCurrencyPat
, // UNUM_CURRENCY_ISO
123 gLastResortPluralCurrencyPat
, // UNUM_CURRENCY_PLURAL
124 gLastResortAccountingCurrencyPat
, // UNUM_CURRENCY_ACCOUNTING
125 gLastResortCurrencyPat
, // UNUM_CASH_CURRENCY
126 NULL
, // UNUM_DECIMAL_COMPACT_SHORT
127 NULL
, // UNUM_DECIMAL_COMPACT_LONG
128 gLastResortCurrencyPat
, // UNUM_CURRENCY_STANDARD
131 // Keys used for accessing resource bundles
133 static const icu::number::impl::CldrPatternStyle gFormatCldrStyles
[UNUM_FORMAT_STYLE_COUNT
] = {
134 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_PATTERN_DECIMAL
135 icu::number::impl::CLDR_PATTERN_STYLE_DECIMAL
, // UNUM_DECIMAL
136 icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY
, // UNUM_CURRENCY
137 icu::number::impl::CLDR_PATTERN_STYLE_PERCENT
, // UNUM_PERCENT
138 icu::number::impl::CLDR_PATTERN_STYLE_SCIENTIFIC
, // UNUM_SCIENTIFIC
139 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_SPELLOUT
140 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_ORDINAL
141 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_DURATION
142 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_NUMBERING_SYSTEM
143 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_PATTERN_RULEBASED
144 // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
145 // the pattern is the same as the pattern of UNUM_CURRENCY
146 // except for replacing the single currency sign with
147 // double currency sign or triple currency sign.
148 icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY
, // UNUM_CURRENCY_ISO
149 icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY
, // UNUM_CURRENCY_PLURAL
150 icu::number::impl::CLDR_PATTERN_STYLE_ACCOUNTING
, // UNUM_CURRENCY_ACCOUNTING
151 icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY
, // UNUM_CASH_CURRENCY
152 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_DECIMAL_COMPACT_SHORT
153 /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT
, // UNUM_DECIMAL_COMPACT_LONG
154 icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY
, // UNUM_CURRENCY_STANDARD
157 // Static hashtable cache of NumberingSystem objects used by NumberFormat
158 static UHashtable
* NumberingSystem_cache
= NULL
;
159 static icu::UInitOnce gNSCacheInitOnce
= U_INITONCE_INITIALIZER
;
161 #if !UCONFIG_NO_SERVICE
162 static icu::ICULocaleService
* gService
= NULL
;
163 static icu::UInitOnce gServiceInitOnce
= U_INITONCE_INITIALIZER
;
167 * Release all static memory held by Number Format.
170 static void U_CALLCONV
171 deleteNumberingSystem(void *obj
) {
172 delete (icu::NumberingSystem
*)obj
;
175 static UBool U_CALLCONV
numfmt_cleanup(void) {
176 #if !UCONFIG_NO_SERVICE
177 gServiceInitOnce
.reset();
183 gNSCacheInitOnce
.reset();
184 if (NumberingSystem_cache
) {
185 // delete NumberingSystem_cache;
186 uhash_close(NumberingSystem_cache
);
187 NumberingSystem_cache
= NULL
;
193 // *****************************************************************************
194 // class NumberFormat
195 // *****************************************************************************
199 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat
)
201 #if !UCONFIG_NO_SERVICE
202 // -------------------------------------
203 // SimpleNumberFormatFactory implementation
204 NumberFormatFactory::~NumberFormatFactory() {}
205 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale
& locale
, UBool visible
)
208 LocaleUtility::initNameFromLocale(locale
, _id
);
211 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
213 UBool
SimpleNumberFormatFactory::visible(void) const {
217 const UnicodeString
*
218 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count
, UErrorCode
& status
) const
220 if (U_SUCCESS(status
)) {
227 #endif /* #if !UCONFIG_NO_SERVICE */
229 // -------------------------------------
230 // default constructor
231 NumberFormat::NumberFormat()
232 : fGroupingUsed(TRUE
),
233 fMaxIntegerDigits(gDefaultMaxIntegerDigits
),
234 fMinIntegerDigits(1),
235 fMaxFractionDigits(3), // invariant, >= minFractionDigits
236 fMinFractionDigits(0),
237 fParseIntegerOnly(FALSE
),
239 fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE
)
244 // -------------------------------------
246 NumberFormat::~NumberFormat()
250 SharedNumberFormat::~SharedNumberFormat() {
254 // -------------------------------------
257 NumberFormat::NumberFormat(const NumberFormat
&source
)
263 // -------------------------------------
264 // assignment operator
267 NumberFormat::operator=(const NumberFormat
& rhs
)
271 Format::operator=(rhs
);
272 fGroupingUsed
= rhs
.fGroupingUsed
;
273 fMaxIntegerDigits
= rhs
.fMaxIntegerDigits
;
274 fMinIntegerDigits
= rhs
.fMinIntegerDigits
;
275 fMaxFractionDigits
= rhs
.fMaxFractionDigits
;
276 fMinFractionDigits
= rhs
.fMinFractionDigits
;
277 fParseIntegerOnly
= rhs
.fParseIntegerOnly
;
278 u_strncpy(fCurrency
, rhs
.fCurrency
, 3);
280 fLenient
= rhs
.fLenient
;
281 fCapitalizationContext
= rhs
.fCapitalizationContext
;
286 // -------------------------------------
289 NumberFormat::operator==(const Format
& that
) const
291 // Format::operator== guarantees this cast is safe
292 NumberFormat
* other
= (NumberFormat
*)&that
;
295 // This code makes it easy to determine why two format objects that should
298 if (!Format::operator==(that
)) {
299 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
302 if (!(fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
303 fMinIntegerDigits
== other
->fMinIntegerDigits
)) {
304 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
305 debug("Integer digits !=");
307 if (!(fMaxFractionDigits
== other
->fMaxFractionDigits
&&
308 fMinFractionDigits
== other
->fMinFractionDigits
)) {
309 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
310 debug("Fraction digits !=");
312 if (!(fGroupingUsed
== other
->fGroupingUsed
)) {
313 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
314 debug("fGroupingUsed != ");
316 if (!(fParseIntegerOnly
== other
->fParseIntegerOnly
)) {
317 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
318 debug("fParseIntegerOnly != ");
320 if (!(u_strcmp(fCurrency
, other
->fCurrency
) == 0)) {
321 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
322 debug("fCurrency !=");
324 if (!(fLenient
== other
->fLenient
)) {
325 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
326 debug("fLenient != ");
328 if (!(fCapitalizationContext
== other
->fCapitalizationContext
)) {
329 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
330 debug("fCapitalizationContext != ");
332 if (!first
) { printf(" ]"); }
335 return ((this == &that
) ||
336 ((Format::operator==(that
) &&
337 fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
338 fMinIntegerDigits
== other
->fMinIntegerDigits
&&
339 fMaxFractionDigits
== other
->fMaxFractionDigits
&&
340 fMinFractionDigits
== other
->fMinFractionDigits
&&
341 fGroupingUsed
== other
->fGroupingUsed
&&
342 fParseIntegerOnly
== other
->fParseIntegerOnly
&&
343 u_strcmp(fCurrency
, other
->fCurrency
) == 0 &&
344 fLenient
== other
->fLenient
&&
345 fCapitalizationContext
== other
->fCapitalizationContext
)));
348 // -------------------------------------
349 // Default implementation sets unsupported error; subclasses should
353 NumberFormat::format(double /* unused number */,
354 UnicodeString
& toAppendTo
,
355 FieldPositionIterator
* /* unused posIter */,
356 UErrorCode
& status
) const
358 if (!U_FAILURE(status
)) {
359 status
= U_UNSUPPORTED_ERROR
;
364 // -------------------------------------
365 // Default implementation sets unsupported error; subclasses should
369 NumberFormat::format(int32_t /* unused number */,
370 UnicodeString
& toAppendTo
,
371 FieldPositionIterator
* /* unused posIter */,
372 UErrorCode
& status
) const
374 if (!U_FAILURE(status
)) {
375 status
= U_UNSUPPORTED_ERROR
;
380 // -------------------------------------
381 // Default implementation sets unsupported error; subclasses should
385 NumberFormat::format(int64_t /* unused number */,
386 UnicodeString
& toAppendTo
,
387 FieldPositionIterator
* /* unused posIter */,
388 UErrorCode
& status
) const
390 if (!U_FAILURE(status
)) {
391 status
= U_UNSUPPORTED_ERROR
;
396 // ------------------------------------------
397 // These functions add the status code, just fall back to the non-status versions
399 NumberFormat::format(double number
,
400 UnicodeString
& appendTo
,
402 UErrorCode
&status
) const {
403 if(U_SUCCESS(status
)) {
404 return format(number
,appendTo
,pos
);
411 NumberFormat::format(int32_t number
,
412 UnicodeString
& appendTo
,
414 UErrorCode
&status
) const {
415 if(U_SUCCESS(status
)) {
416 return format(number
,appendTo
,pos
);
423 NumberFormat::format(int64_t number
,
424 UnicodeString
& appendTo
,
426 UErrorCode
&status
) const {
427 if(U_SUCCESS(status
)) {
428 return format(number
,appendTo
,pos
);
436 // -------------------------------------
437 // Decimal Number format() default implementation
438 // Subclasses do not normally override this function, but rather the DigitList
439 // formatting functions..
440 // The expected call chain from here is
442 // NumberFormat::format(Formattable ->
443 // DecimalFormat::format(DigitList
445 // Or, for subclasses of Formattable that do not know about DigitList,
447 // NumberFormat::format(Formattable ->
448 // NumberFormat::format(DigitList ->
449 // XXXFormat::format(double
452 NumberFormat::format(StringPiece decimalNum
,
453 UnicodeString
& toAppendTo
,
454 FieldPositionIterator
* fpi
,
455 UErrorCode
& status
) const
458 f
.setDecimalNumber(decimalNum
, status
);
459 format(f
, toAppendTo
, fpi
, status
);
465 // Formats the number object and save the format
466 // result in the toAppendTo string buffer.
468 // utility to save/restore state, used in two overloads
469 // of format(const Formattable&...) below.
471 * Old purpose of ArgExtractor was to avoid const. Not thread safe!
473 * keeping it around as a shim.
476 const Formattable
* num
;
481 ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
);
484 const Formattable
* number(void) const;
485 const UChar
*iso(void) const;
486 UBool
wasCurrency(void) const;
489 inline const Formattable
*
490 ArgExtractor::number(void) const {
495 ArgExtractor::wasCurrency(void) const {
500 ArgExtractor::iso(void) const {
504 ArgExtractor::ArgExtractor(const NumberFormat
& /*nf*/, const Formattable
& obj
, UErrorCode
& /*status*/)
505 : num(&obj
), fWasCurrency(FALSE
) {
507 const UObject
* o
= obj
.getObject(); // most commonly o==NULL
508 const CurrencyAmount
* amt
;
509 if (o
!= NULL
&& (amt
= dynamic_cast<const CurrencyAmount
*>(o
)) != NULL
) {
510 // getISOCurrency() returns a pointer to internal storage, so we
511 // copy it to retain it across the call to setCurrency().
512 //const UChar* curr = amt->getISOCurrency();
513 u_strcpy(save
, amt
->getISOCurrency());
514 num
= &amt
->getNumber();
521 ArgExtractor::~ArgExtractor() {
524 UnicodeString
& NumberFormat::format(const number::impl::DecimalQuantity
&number
,
525 UnicodeString
& appendTo
,
526 FieldPositionIterator
* posIter
,
527 UErrorCode
& status
) const {
528 // DecimalFormat overrides this function, and handles DigitList based big decimals.
529 // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
530 // so this default implementation falls back to formatting decimal numbers as doubles.
531 if (U_FAILURE(status
)) {
534 double dnum
= number
.toDouble();
535 format(dnum
, appendTo
, posIter
, status
);
542 NumberFormat::format(const number::impl::DecimalQuantity
&number
,
543 UnicodeString
& appendTo
,
545 UErrorCode
&status
) const {
546 // DecimalFormat overrides this function, and handles DigitList based big decimals.
547 // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
548 // so this default implementation falls back to formatting decimal numbers as doubles.
549 if (U_FAILURE(status
)) {
552 double dnum
= number
.toDouble();
553 format(dnum
, appendTo
, pos
, status
);
558 NumberFormat::format(const Formattable
& obj
,
559 UnicodeString
& appendTo
,
561 UErrorCode
& status
) const
563 if (U_FAILURE(status
)) return appendTo
;
565 ArgExtractor
arg(*this, obj
, status
);
566 const Formattable
*n
= arg
.number();
567 const UChar
*iso
= arg
.iso();
569 if(arg
.wasCurrency() && u_strcmp(iso
, getCurrency())) {
570 // trying to format a different currency.
571 // Right now, we clone.
572 LocalPointer
<NumberFormat
> cloneFmt((NumberFormat
*)this->clone());
573 cloneFmt
->setCurrency(iso
, status
);
574 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
575 return cloneFmt
->format(*n
, appendTo
, pos
, status
);
578 if (n
->isNumeric() && n
->getDecimalQuantity() != NULL
) {
579 // Decimal Number. We will have a DigitList available if the value was
580 // set to a decimal number, or if the value originated with a parse.
582 // The default implementation for formatting a DigitList converts it
583 // to a double, and formats that, allowing formatting classes that don't
584 // know about DigitList to continue to operate as they had.
586 // DecimalFormat overrides the DigitList formatting functions.
587 format(*n
->getDecimalQuantity(), appendTo
, pos
, status
);
589 switch (n
->getType()) {
590 case Formattable::kDouble
:
591 format(n
->getDouble(), appendTo
, pos
, status
);
593 case Formattable::kLong
:
594 format(n
->getLong(), appendTo
, pos
, status
);
596 case Formattable::kInt64
:
597 format(n
->getInt64(), appendTo
, pos
, status
);
600 status
= U_INVALID_FORMAT_ERROR
;
608 // -------------------------------------x
609 // Formats the number object and save the format
610 // result in the toAppendTo string buffer.
613 NumberFormat::format(const Formattable
& obj
,
614 UnicodeString
& appendTo
,
615 FieldPositionIterator
* posIter
,
616 UErrorCode
& status
) const
618 if (U_FAILURE(status
)) return appendTo
;
620 ArgExtractor
arg(*this, obj
, status
);
621 const Formattable
*n
= arg
.number();
622 const UChar
*iso
= arg
.iso();
624 if(arg
.wasCurrency() && u_strcmp(iso
, getCurrency())) {
625 // trying to format a different currency.
626 // Right now, we clone.
627 LocalPointer
<NumberFormat
> cloneFmt((NumberFormat
*)this->clone());
628 cloneFmt
->setCurrency(iso
, status
);
629 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
630 return cloneFmt
->format(*n
, appendTo
, posIter
, status
);
633 if (n
->isNumeric() && n
->getDecimalQuantity() != NULL
) {
635 format(*n
->getDecimalQuantity(), appendTo
, posIter
, status
);
637 switch (n
->getType()) {
638 case Formattable::kDouble
:
639 format(n
->getDouble(), appendTo
, posIter
, status
);
641 case Formattable::kLong
:
642 format(n
->getLong(), appendTo
, posIter
, status
);
644 case Formattable::kInt64
:
645 format(n
->getInt64(), appendTo
, posIter
, status
);
648 status
= U_INVALID_FORMAT_ERROR
;
656 // -------------------------------------
659 NumberFormat::format(int64_t number
,
660 UnicodeString
& appendTo
,
661 FieldPosition
& pos
) const
663 // default so we don't introduce a new abstract method
664 return format((int32_t)number
, appendTo
, pos
);
667 // -------------------------------------
668 // Parses the string and save the result object as well
669 // as the final parsed position.
672 NumberFormat::parseObject(const UnicodeString
& source
,
674 ParsePosition
& parse_pos
) const
676 parse(source
, result
, parse_pos
);
679 // -------------------------------------
680 // Formats a double number and save the result in a string.
683 NumberFormat::format(double number
, UnicodeString
& appendTo
) const
685 FieldPosition
pos(FieldPosition::DONT_CARE
);
686 return format(number
, appendTo
, pos
);
689 // -------------------------------------
690 // Formats a long number and save the result in a string.
693 NumberFormat::format(int32_t number
, UnicodeString
& appendTo
) const
695 FieldPosition
pos(FieldPosition::DONT_CARE
);
696 return format(number
, appendTo
, pos
);
699 // -------------------------------------
700 // Formats a long number and save the result in a string.
703 NumberFormat::format(int64_t number
, UnicodeString
& appendTo
) const
705 FieldPosition
pos(FieldPosition::DONT_CARE
);
706 return format(number
, appendTo
, pos
);
709 // -------------------------------------
710 // Parses the text and save the result object. If the returned
711 // parse position is 0, that means the parsing failed, the status
712 // code needs to be set to failure. Ignores the returned parse
713 // position, otherwise.
716 NumberFormat::parse(const UnicodeString
& text
,
718 UErrorCode
& status
) const
720 if (U_FAILURE(status
)) return;
722 ParsePosition
parsePosition(0);
723 parse(text
, result
, parsePosition
);
724 if (parsePosition
.getIndex() == 0) {
725 status
= U_INVALID_FORMAT_ERROR
;
729 CurrencyAmount
* NumberFormat::parseCurrency(const UnicodeString
& text
,
730 ParsePosition
& pos
) const {
731 // Default implementation only -- subclasses should override
732 Formattable parseResult
;
733 int32_t start
= pos
.getIndex();
734 parse(text
, parseResult
, pos
);
735 if (pos
.getIndex() != start
) {
737 UErrorCode ec
= U_ZERO_ERROR
;
738 getEffectiveCurrency(curr
, ec
);
740 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curr
, ec
), ec
);
742 pos
.setIndex(start
); // indicate failure
744 return currAmt
.orphan();
751 // -------------------------------------
752 // Sets to only parse integers.
755 NumberFormat::setParseIntegerOnly(UBool value
)
757 fParseIntegerOnly
= value
;
760 // -------------------------------------
761 // Sets whether lenient parse is enabled.
764 NumberFormat::setLenient(UBool enable
)
769 // -------------------------------------
770 // Create a number style NumberFormat instance with the default locale.
772 NumberFormat
* U_EXPORT2
773 NumberFormat::createInstance(UErrorCode
& status
)
775 return createInstance(Locale::getDefault(), UNUM_DECIMAL
, status
);
778 // -------------------------------------
779 // Create a number style NumberFormat instance with the inLocale locale.
781 NumberFormat
* U_EXPORT2
782 NumberFormat::createInstance(const Locale
& inLocale
, UErrorCode
& status
)
784 return createInstance(inLocale
, UNUM_DECIMAL
, status
);
787 // -------------------------------------
788 // Create a currency style NumberFormat instance with the default locale.
790 NumberFormat
* U_EXPORT2
791 NumberFormat::createCurrencyInstance(UErrorCode
& status
)
793 return createCurrencyInstance(Locale::getDefault(), status
);
796 // -------------------------------------
797 // Create a currency style NumberFormat instance with the inLocale locale.
799 NumberFormat
* U_EXPORT2
800 NumberFormat::createCurrencyInstance(const Locale
& inLocale
, UErrorCode
& status
)
802 return createInstance(inLocale
, UNUM_CURRENCY
, status
);
805 // -------------------------------------
806 // Create a percent style NumberFormat instance with the default locale.
808 NumberFormat
* U_EXPORT2
809 NumberFormat::createPercentInstance(UErrorCode
& status
)
811 return createInstance(Locale::getDefault(), UNUM_PERCENT
, status
);
814 // -------------------------------------
815 // Create a percent style NumberFormat instance with the inLocale locale.
817 NumberFormat
* U_EXPORT2
818 NumberFormat::createPercentInstance(const Locale
& inLocale
, UErrorCode
& status
)
820 return createInstance(inLocale
, UNUM_PERCENT
, status
);
823 // -------------------------------------
824 // Create a scientific style NumberFormat instance with the default locale.
826 NumberFormat
* U_EXPORT2
827 NumberFormat::createScientificInstance(UErrorCode
& status
)
829 return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC
, status
);
832 // -------------------------------------
833 // Create a scientific style NumberFormat instance with the inLocale locale.
835 NumberFormat
* U_EXPORT2
836 NumberFormat::createScientificInstance(const Locale
& inLocale
, UErrorCode
& status
)
838 return createInstance(inLocale
, UNUM_SCIENTIFIC
, status
);
841 // -------------------------------------
843 const Locale
* U_EXPORT2
844 NumberFormat::getAvailableLocales(int32_t& count
)
846 return Locale::getAvailableLocales(count
);
849 // ------------------------------------------
853 //-------------------------------------------
855 #if !UCONFIG_NO_SERVICE
857 // -------------------------------------
859 class ICUNumberFormatFactory
: public ICUResourceBundleFactory
{
861 virtual ~ICUNumberFormatFactory();
863 virtual UObject
* handleCreate(const Locale
& loc
, int32_t kind
, const ICUService
* /* service */, UErrorCode
& status
) const {
864 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
868 ICUNumberFormatFactory::~ICUNumberFormatFactory() {}
870 // -------------------------------------
872 class NFFactory
: public LocaleKeyFactory
{
874 NumberFormatFactory
* _delegate
;
878 NFFactory(NumberFormatFactory
* delegate
)
879 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
880 , _delegate(delegate
)
885 virtual ~NFFactory();
887 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const
889 if (handlesKey(key
, status
)) {
890 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
892 lkey
.canonicalLocale(loc
);
893 int32_t kind
= lkey
.kind();
895 UObject
* result
= _delegate
->createFormat(loc
, (UNumberFormatStyle
)kind
);
896 if (result
== NULL
) {
897 result
= service
->getKey((ICUServiceKey
&)key
/* cast away const */, NULL
, this, status
);
906 * Return the set of ids that this factory supports (visible or
907 * otherwise). This can be called often and might need to be
908 * cached if it is expensive to create.
910 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
912 if (U_SUCCESS(status
)) {
915 const UnicodeString
* const idlist
= _delegate
->getSupportedIDs(count
, status
);
916 ((NFFactory
*)this)->_ids
= new Hashtable(status
); /* cast away const */
918 for (int i
= 0; i
< count
; ++i
) {
919 _ids
->put(idlist
[i
], (void*)this, status
);
929 NFFactory::~NFFactory()
935 class ICUNumberFormatService
: public ICULocaleService
{
937 ICUNumberFormatService()
938 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
940 UErrorCode status
= U_ZERO_ERROR
;
941 registerFactory(new ICUNumberFormatFactory(), status
);
944 virtual ~ICUNumberFormatService();
946 virtual UObject
* cloneInstance(UObject
* instance
) const {
947 return ((NumberFormat
*)instance
)->clone();
950 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* /* actualID */, UErrorCode
& status
) const {
951 LocaleKey
& lkey
= (LocaleKey
&)key
;
952 int32_t kind
= lkey
.kind();
954 lkey
.currentLocale(loc
);
955 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
958 virtual UBool
isDefault() const {
959 return countFactories() == 1;
963 ICUNumberFormatService::~ICUNumberFormatService() {}
965 // -------------------------------------
967 static void U_CALLCONV
initNumberFormatService() {
968 U_ASSERT(gService
== NULL
);
969 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
970 gService
= new ICUNumberFormatService();
973 static ICULocaleService
*
974 getNumberFormatService(void)
976 umtx_initOnce(gServiceInitOnce
, &initNumberFormatService
);
980 static UBool
haveService() {
981 return !gServiceInitOnce
.isReset() && (getNumberFormatService() != NULL
);
984 // -------------------------------------
986 URegistryKey U_EXPORT2
987 NumberFormat::registerFactory(NumberFormatFactory
* toAdopt
, UErrorCode
& status
)
989 ICULocaleService
*service
= getNumberFormatService();
991 NFFactory
*tempnnf
= new NFFactory(toAdopt
);
992 if (tempnnf
!= NULL
) {
993 return service
->registerFactory(tempnnf
, status
);
996 status
= U_MEMORY_ALLOCATION_ERROR
;
1000 // -------------------------------------
1003 NumberFormat::unregister(URegistryKey key
, UErrorCode
& status
)
1005 if (U_FAILURE(status
)) {
1008 if (haveService()) {
1009 return gService
->unregister(key
, status
);
1011 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1016 // -------------------------------------
1017 StringEnumeration
* U_EXPORT2
1018 NumberFormat::getAvailableLocales(void)
1020 ICULocaleService
*service
= getNumberFormatService();
1022 return service
->getAvailableLocales();
1024 return NULL
; // no way to return error condition
1026 #endif /* UCONFIG_NO_SERVICE */
1027 // -------------------------------------
1029 enum { kKeyValueLenMax
= 32 };
1032 NumberFormat::internalCreateInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1033 if (kind
== UNUM_CURRENCY
) {
1034 char cfKeyValue
[kKeyValueLenMax
] = {0};
1035 UErrorCode kvStatus
= U_ZERO_ERROR
;
1036 int32_t kLen
= loc
.getKeywordValue("cf", cfKeyValue
, kKeyValueLenMax
, kvStatus
);
1037 if (U_SUCCESS(kvStatus
) && kLen
> 0 && uprv_strcmp(cfKeyValue
,"account")==0) {
1038 kind
= UNUM_CURRENCY_ACCOUNTING
;
1041 #if !UCONFIG_NO_SERVICE
1042 if (haveService()) {
1043 return (NumberFormat
*)gService
->get(loc
, kind
, status
);
1046 return makeInstance(loc
, kind
, status
);
1049 NumberFormat
* U_EXPORT2
1050 NumberFormat::createInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1051 if (kind
!= UNUM_DECIMAL
) {
1052 return internalCreateInstance(loc
, kind
, status
);
1054 const SharedNumberFormat
*shared
= createSharedInstance(loc
, kind
, status
);
1055 if (U_FAILURE(status
)) {
1058 NumberFormat
*result
= static_cast<NumberFormat
*>((*shared
)->clone());
1059 shared
->removeRef();
1060 if (result
== NULL
) {
1061 status
= U_MEMORY_ALLOCATION_ERROR
;
1067 // -------------------------------------
1068 // Checks if the thousand/10 thousand grouping is used in the
1069 // NumberFormat instance.
1072 NumberFormat::isGroupingUsed() const
1074 return fGroupingUsed
;
1077 // -------------------------------------
1078 // Sets to use the thousand/10 thousand grouping in the
1079 // NumberFormat instance.
1082 NumberFormat::setGroupingUsed(UBool newValue
)
1084 fGroupingUsed
= newValue
;
1087 // -------------------------------------
1088 // Gets the maximum number of digits for the integral part for
1089 // this NumberFormat instance.
1091 int32_t NumberFormat::getMaximumIntegerDigits() const
1093 return fMaxIntegerDigits
;
1096 // -------------------------------------
1097 // Sets the maximum number of digits for the integral part for
1098 // this NumberFormat instance.
1101 NumberFormat::setMaximumIntegerDigits(int32_t newValue
)
1103 fMaxIntegerDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMaxIntegerDigits
));
1104 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1105 fMinIntegerDigits
= fMaxIntegerDigits
;
1108 // -------------------------------------
1109 // Gets the minimum number of digits for the integral part for
1110 // this NumberFormat instance.
1113 NumberFormat::getMinimumIntegerDigits() const
1115 return fMinIntegerDigits
;
1118 // -------------------------------------
1119 // Sets the minimum number of digits for the integral part for
1120 // this NumberFormat instance.
1123 NumberFormat::setMinimumIntegerDigits(int32_t newValue
)
1125 fMinIntegerDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMinIntegerDigits
));
1126 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1127 fMaxIntegerDigits
= fMinIntegerDigits
;
1130 // -------------------------------------
1131 // Gets the maximum number of digits for the fractional part for
1132 // this NumberFormat instance.
1135 NumberFormat::getMaximumFractionDigits() const
1137 return fMaxFractionDigits
;
1140 // -------------------------------------
1141 // Sets the maximum number of digits for the fractional part for
1142 // this NumberFormat instance.
1145 NumberFormat::setMaximumFractionDigits(int32_t newValue
)
1147 fMaxFractionDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMaxIntegerDigits
));
1148 if(fMaxFractionDigits
< fMinFractionDigits
)
1149 fMinFractionDigits
= fMaxFractionDigits
;
1152 // -------------------------------------
1153 // Gets the minimum number of digits for the fractional part for
1154 // this NumberFormat instance.
1157 NumberFormat::getMinimumFractionDigits() const
1159 return fMinFractionDigits
;
1162 // -------------------------------------
1163 // Sets the minimum number of digits for the fractional part for
1164 // this NumberFormat instance.
1167 NumberFormat::setMinimumFractionDigits(int32_t newValue
)
1169 fMinFractionDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMinIntegerDigits
));
1170 if (fMaxFractionDigits
< fMinFractionDigits
)
1171 fMaxFractionDigits
= fMinFractionDigits
;
1174 // -------------------------------------
1175 // Group-set several settings used for numbers in date formats. Apple rdar://50064762
1178 NumberFormat::setDateSettings(void)
1180 fGroupingUsed
= FALSE
;
1181 fParseIntegerOnly
= TRUE
;
1182 fMinFractionDigits
= 0;
1183 if (fMaxFractionDigits
< fMinFractionDigits
)
1184 fMaxFractionDigits
= fMinFractionDigits
;
1187 // -------------------------------------
1189 void NumberFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
1190 if (U_FAILURE(ec
)) {
1194 u_strncpy(fCurrency
, theCurrency
, 3);
1201 const char16_t* NumberFormat::getCurrency() const {
1205 void NumberFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
1206 const UChar
* c
= getCurrency();
1208 u_strncpy(result
, c
, 3);
1211 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
1213 loc
= uloc_getDefault();
1215 ucurr_forLocale(loc
, result
, 4, &ec
);
1219 //----------------------------------------------------------------------
1222 void NumberFormat::setContext(UDisplayContext value
, UErrorCode
& status
)
1224 if (U_FAILURE(status
))
1226 if ( (UDisplayContextType
)((uint32_t)value
>> 8) == UDISPCTX_TYPE_CAPITALIZATION
) {
1227 fCapitalizationContext
= value
;
1229 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1234 UDisplayContext
NumberFormat::getContext(UDisplayContextType type
, UErrorCode
& status
) const
1236 if (U_FAILURE(status
))
1237 return (UDisplayContext
)0;
1238 if (type
!= UDISPCTX_TYPE_CAPITALIZATION
) {
1239 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1240 return (UDisplayContext
)0;
1242 return fCapitalizationContext
;
1246 // -------------------------------------
1247 // Creates the NumberFormat instance of the specified style (number, currency,
1248 // or percent) for the desired locale.
1250 static void U_CALLCONV
nscacheInit() {
1251 U_ASSERT(NumberingSystem_cache
== NULL
);
1252 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
1253 UErrorCode status
= U_ZERO_ERROR
;
1254 NumberingSystem_cache
= uhash_open(uhash_hashLong
,
1258 if (U_FAILURE(status
)) {
1259 // Number Format code will run with no cache if creation fails.
1260 NumberingSystem_cache
= NULL
;
1263 uhash_setValueDeleter(NumberingSystem_cache
, deleteNumberingSystem
);
1266 template<> U_I18N_API
1267 const SharedNumberFormat
*LocaleCacheKey
<SharedNumberFormat
>::createObject(
1268 const void * /*unused*/, UErrorCode
&status
) const {
1269 const char *localeId
= fLoc
.getName();
1270 NumberFormat
*nf
= NumberFormat::internalCreateInstance(
1271 localeId
, UNUM_DECIMAL
, status
);
1272 if (U_FAILURE(status
)) {
1275 SharedNumberFormat
*result
= new SharedNumberFormat(nf
);
1276 if (result
== NULL
) {
1277 status
= U_MEMORY_ALLOCATION_ERROR
;
1285 const SharedNumberFormat
* U_EXPORT2
1286 NumberFormat::createSharedInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1287 if (U_FAILURE(status
)) {
1290 if (kind
!= UNUM_DECIMAL
) {
1291 status
= U_UNSUPPORTED_ERROR
;
1294 const SharedNumberFormat
*result
= NULL
;
1295 UnifiedCache::getByLocale(loc
, result
, status
);
1300 NumberFormat::isStyleSupported(UNumberFormatStyle style
) {
1301 return gLastResortNumberPatterns
[style
] != NULL
;
1305 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1306 UNumberFormatStyle style
,
1307 UErrorCode
& status
) {
1308 return makeInstance(desiredLocale
, style
, false, status
);
1312 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1313 UNumberFormatStyle style
,
1314 UBool mustBeDecimalFormat
,
1315 UErrorCode
& status
) {
1316 if (U_FAILURE(status
)) return NULL
;
1318 if (style
< 0 || style
>= UNUM_FORMAT_STYLE_COUNT
) {
1319 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1323 // Some styles are not supported. This is a result of merging
1324 // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
1325 // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
1326 // this one and unum_open().
1327 // The UNUM_PATTERN_ styles are not supported here
1328 // because this method does not take a pattern string.
1329 if (!isStyleSupported(style
)) {
1330 status
= U_UNSUPPORTED_ERROR
;
1334 #if U_PLATFORM_USES_ONLY_WIN32_API
1335 if (!mustBeDecimalFormat
) {
1337 int32_t count
= desiredLocale
.getKeywordValue("compat", buffer
, sizeof(buffer
), status
);
1339 // if the locale has "@compat=host", create a host-specific NumberFormat
1340 if (U_SUCCESS(status
) && count
> 0 && uprv_strcmp(buffer
, "host") == 0) {
1350 case UNUM_CURRENCY_ISO
: // do not support plural formatting here
1351 case UNUM_CURRENCY_PLURAL
:
1352 case UNUM_CURRENCY_ACCOUNTING
:
1353 case UNUM_CASH_CURRENCY
:
1354 case UNUM_CURRENCY_STANDARD
:
1356 LocalPointer
<Win32NumberFormat
> f(new Win32NumberFormat(desiredLocale
, curr
, status
), status
);
1357 if (U_SUCCESS(status
)) {
1368 // Use numbering system cache hashtable
1369 umtx_initOnce(gNSCacheInitOnce
, &nscacheInit
);
1371 // Get cached numbering system
1372 LocalPointer
<NumberingSystem
> ownedNs
;
1373 NumberingSystem
*ns
= NULL
;
1374 if (NumberingSystem_cache
!= NULL
) {
1375 // TODO: Bad hash key usage, see ticket #8504.
1376 int32_t hashKey
= desiredLocale
.hashCode();
1378 static UMutex
*nscacheMutex
= STATIC_NEW(UMutex
);
1379 Mutex
lock(nscacheMutex
);
1380 ns
= (NumberingSystem
*)uhash_iget(NumberingSystem_cache
, hashKey
);
1382 ns
= NumberingSystem::createInstance(desiredLocale
,status
);
1383 uhash_iput(NumberingSystem_cache
, hashKey
, (void*)ns
, &status
);
1386 ownedNs
.adoptInstead(NumberingSystem::createInstance(desiredLocale
,status
));
1387 ns
= ownedNs
.getAlias();
1390 // check results of getting a numbering system
1391 if (U_FAILURE(status
)) {
1395 if (mustBeDecimalFormat
&& ns
->isAlgorithmic()) {
1396 status
= U_UNSUPPORTED_ERROR
;
1400 LocalPointer
<DecimalFormatSymbols
> symbolsToAdopt
;
1401 UnicodeString pattern
;
1402 LocalUResourceBundlePointer
ownedResource(ures_open(NULL
, desiredLocale
.getName(), &status
));
1403 if (U_FAILURE(status
)) {
1407 // Loads the decimal symbols of the desired locale.
1408 if (ns
!= nullptr) {
1409 // Apple <rdar://51672521> use the ns we already have, so DecimalFormatSymbols does not instantiate another
1410 symbolsToAdopt
.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(desiredLocale
, *ns
, status
), status
);
1412 symbolsToAdopt
.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(desiredLocale
, status
), status
);
1414 if (U_FAILURE(status
)) {
1418 // Load the pattern from data using the common library function
1419 const char16_t* patternPtr
= number::impl::utils::getPatternForStyle(
1422 gFormatCldrStyles
[style
],
1424 pattern
= UnicodeString(TRUE
, patternPtr
, -1);
1426 if (U_FAILURE(status
)) {
1429 if(style
==UNUM_CURRENCY
|| style
== UNUM_CURRENCY_ISO
|| style
== UNUM_CURRENCY_ACCOUNTING
1430 || style
== UNUM_CASH_CURRENCY
|| style
== UNUM_CURRENCY_STANDARD
){
1431 const UChar
* currPattern
= symbolsToAdopt
->getCurrencyPattern();
1432 if(currPattern
!=NULL
){
1433 pattern
.setTo(currPattern
, u_strlen(currPattern
));
1437 LocalPointer
<NumberFormat
> f
;
1438 if (ns
->isAlgorithmic()) {
1439 UnicodeString nsDesc
;
1440 UnicodeString nsRuleSetGroup
;
1441 UnicodeString nsRuleSetName
;
1443 URBNFRuleSetTag desiredRulesType
= URBNF_NUMBERING_SYSTEM
;
1445 nsDesc
.setTo(ns
->getDescription());
1446 int32_t firstSlash
= nsDesc
.indexOf(gSlash
);
1447 int32_t lastSlash
= nsDesc
.lastIndexOf(gSlash
);
1448 if ( lastSlash
> firstSlash
) {
1451 nsLocID
.appendInvariantChars(nsDesc
.tempSubString(0, firstSlash
), status
);
1452 nsRuleSetGroup
.setTo(nsDesc
,firstSlash
+1,lastSlash
-firstSlash
-1);
1453 nsRuleSetName
.setTo(nsDesc
,lastSlash
+1);
1455 nsLoc
= Locale::createFromName(nsLocID
.data());
1457 UnicodeString SpelloutRules
= UNICODE_STRING_SIMPLE("SpelloutRules");
1458 if ( nsRuleSetGroup
.compare(SpelloutRules
) == 0 ) {
1459 desiredRulesType
= URBNF_SPELLOUT
;
1462 nsLoc
= desiredLocale
;
1463 nsRuleSetName
.setTo(nsDesc
);
1466 RuleBasedNumberFormat
*r
= new RuleBasedNumberFormat(desiredRulesType
,nsLoc
,status
);
1468 status
= U_MEMORY_ALLOCATION_ERROR
;
1471 r
->setDefaultRuleSet(nsRuleSetName
,status
);
1474 // replace single currency sign in the pattern with double currency sign
1475 // if the style is UNUM_CURRENCY_ISO
1476 if (style
== UNUM_CURRENCY_ISO
) {
1477 pattern
.findAndReplace(UnicodeString(TRUE
, gSingleCurrencySign
, 1),
1478 UnicodeString(TRUE
, gDoubleCurrencySign
, 2));
1481 // "new DecimalFormat()" does not adopt the symbols argument if its memory allocation fails.
1482 // So we can't use adoptInsteadAndCheckErrorCode as we need to know if the 'new' failed.
1483 DecimalFormatSymbols
*syms
= symbolsToAdopt
.getAlias();
1484 LocalPointer
<DecimalFormat
> df(new DecimalFormat(pattern
, syms
, style
, status
));
1487 // if the DecimalFormat object was successfully new'ed, then it will own symbolsToAdopt, even if the status is a failure.
1488 symbolsToAdopt
.orphan();
1491 status
= U_MEMORY_ALLOCATION_ERROR
;
1494 if (U_FAILURE(status
)) {
1498 // if it is cash currency style, setCurrencyUsage with usage
1499 if (style
== UNUM_CASH_CURRENCY
){
1500 df
->setCurrencyUsage(UCURR_USAGE_CASH
, &status
);
1503 if (U_FAILURE(status
)) {
1507 f
.adoptInstead(df
.orphan());
1510 f
->setLocaleIDs(ures_getLocaleByType(ownedResource
.getAlias(), ULOC_VALID_LOCALE
, &status
),
1511 ures_getLocaleByType(ownedResource
.getAlias(), ULOC_ACTUAL_LOCALE
, &status
));
1512 if (U_FAILURE(status
)) {
1519 * Get the rounding mode.
1520 * @return A rounding mode
1522 NumberFormat::ERoundingMode
NumberFormat::getRoundingMode() const {
1523 // Default value. ICU4J throws an exception and we can't change this API.
1524 return NumberFormat::ERoundingMode::kRoundUnnecessary
;
1528 * Set the rounding mode. This has no effect unless the rounding
1529 * increment is greater than zero.
1530 * @param roundingMode A rounding mode
1532 void NumberFormat::setRoundingMode(NumberFormat::ERoundingMode
/*roundingMode*/) {
1533 // No-op ICU4J throws an exception, and we can't change this API.
1538 #endif /* #if !UCONFIG_NO_FORMATTING */