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"
56 #include "sharednumberformat.h"
57 #include "unifiedcache.h"
63 static inline void debugout(UnicodeString s
) {
65 s
.extract((int32_t) 0, s
.length(), buf
);
68 #define debug(x) printf("%s", x);
74 // If no number pattern can be located for a locale, this is the last
75 // resort. The patterns are same as the ones in root locale.
76 static const UChar gLastResortDecimalPat
[] = {
77 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */
79 static const UChar gLastResortCurrencyPat
[] = {
80 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
82 static const UChar gLastResortPercentPat
[] = {
83 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */
85 static const UChar gLastResortScientificPat
[] = {
86 0x23, 0x45, 0x30, 0 /* "#E0" */
88 static const UChar gLastResortIsoCurrencyPat
[] = {
89 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */
91 static const UChar gLastResortPluralCurrencyPat
[] = {
92 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/
94 static const UChar gLastResortAccountingCurrencyPat
[] = {
95 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
98 static const UChar gSingleCurrencySign
[] = {0xA4, 0};
99 static const UChar gDoubleCurrencySign
[] = {0xA4, 0xA4, 0};
101 static const UChar gSlash
= 0x2f;
103 // If the maximum base 10 exponent were 4, then the largest number would
104 // be 99,999 which has 5 digits.
105 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
106 // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999
107 const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits
= 2000000000;
108 const int32_t icu::NumberFormat::gDefaultMinIntegerDigits
= 127;
110 static const UChar
* const gLastResortNumberPatterns
[UNUM_FORMAT_STYLE_COUNT
] = {
111 NULL
, // UNUM_PATTERN_DECIMAL
112 gLastResortDecimalPat
, // UNUM_DECIMAL
113 gLastResortCurrencyPat
, // UNUM_CURRENCY
114 gLastResortPercentPat
, // UNUM_PERCENT
115 gLastResortScientificPat
, // UNUM_SCIENTIFIC
116 NULL
, // UNUM_SPELLOUT
117 NULL
, // UNUM_ORDINAL
118 NULL
, // UNUM_DURATION
119 NULL
, // UNUM_NUMBERING_SYSTEM
120 NULL
, // UNUM_PATTERN_RULEBASED
121 gLastResortIsoCurrencyPat
, // UNUM_CURRENCY_ISO
122 gLastResortPluralCurrencyPat
, // UNUM_CURRENCY_PLURAL
123 gLastResortAccountingCurrencyPat
, // UNUM_CURRENCY_ACCOUNTING
124 gLastResortCurrencyPat
, // UNUM_CASH_CURRENCY
125 NULL
, // UNUM_DECIMAL_COMPACT_SHORT
126 NULL
, // UNUM_DECIMAL_COMPACT_LONG
127 gLastResortCurrencyPat
, // UNUM_CURRENCY_STANDARD
130 // Keys used for accessing resource bundles
132 static const char *gNumberElements
= "NumberElements";
133 static const char *gLatn
= "latn";
134 static const char *gPatterns
= "patterns";
135 static const char *gFormatKeys
[UNUM_FORMAT_STYLE_COUNT
] = {
136 NULL
, // UNUM_PATTERN_DECIMAL
137 "decimalFormat", // UNUM_DECIMAL
138 "currencyFormat", // UNUM_CURRENCY
139 "percentFormat", // UNUM_PERCENT
140 "scientificFormat", // UNUM_SCIENTIFIC
141 NULL
, // UNUM_SPELLOUT
142 NULL
, // UNUM_ORDINAL
143 NULL
, // UNUM_DURATION
144 NULL
, // UNUM_NUMBERING_SYSTEM
145 NULL
, // UNUM_PATTERN_RULEBASED
146 // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
147 // the pattern is the same as the pattern of UNUM_CURRENCY
148 // except for replacing the single currency sign with
149 // double currency sign or triple currency sign.
150 "currencyFormat", // UNUM_CURRENCY_ISO
151 "currencyFormat", // UNUM_CURRENCY_PLURAL
152 "accountingFormat", // UNUM_CURRENCY_ACCOUNTING
153 "currencyFormat", // UNUM_CASH_CURRENCY
154 NULL
, // UNUM_DECIMAL_COMPACT_SHORT
155 NULL
, // UNUM_DECIMAL_COMPACT_LONG
156 "currencyFormat", // UNUM_CURRENCY_STANDARD
159 // Static hashtable cache of NumberingSystem objects used by NumberFormat
160 static UHashtable
* NumberingSystem_cache
= NULL
;
161 static UMutex nscacheMutex
= U_MUTEX_INITIALIZER
;
162 static icu::UInitOnce gNSCacheInitOnce
= U_INITONCE_INITIALIZER
;
164 #if !UCONFIG_NO_SERVICE
165 static icu::ICULocaleService
* gService
= NULL
;
166 static icu::UInitOnce gServiceInitOnce
= U_INITONCE_INITIALIZER
;
170 * Release all static memory held by Number Format.
173 static void U_CALLCONV
174 deleteNumberingSystem(void *obj
) {
175 delete (icu::NumberingSystem
*)obj
;
178 static UBool U_CALLCONV
numfmt_cleanup(void) {
179 #if !UCONFIG_NO_SERVICE
180 gServiceInitOnce
.reset();
186 gNSCacheInitOnce
.reset();
187 if (NumberingSystem_cache
) {
188 // delete NumberingSystem_cache;
189 uhash_close(NumberingSystem_cache
);
190 NumberingSystem_cache
= NULL
;
196 // *****************************************************************************
197 // class NumberFormat
198 // *****************************************************************************
202 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat
)
204 #if !UCONFIG_NO_SERVICE
205 // -------------------------------------
206 // SimpleNumberFormatFactory implementation
207 NumberFormatFactory::~NumberFormatFactory() {}
208 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale
& locale
, UBool visible
)
211 LocaleUtility::initNameFromLocale(locale
, _id
);
214 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
216 UBool
SimpleNumberFormatFactory::visible(void) const {
220 const UnicodeString
*
221 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count
, UErrorCode
& status
) const
223 if (U_SUCCESS(status
)) {
230 #endif /* #if !UCONFIG_NO_SERVICE */
232 // -------------------------------------
233 // default constructor
234 NumberFormat::NumberFormat()
235 : fGroupingUsed(TRUE
),
236 fMaxIntegerDigits(gDefaultMaxIntegerDigits
),
237 fMinIntegerDigits(1),
238 fMaxFractionDigits(3), // invariant, >= minFractionDigits
239 fMinFractionDigits(0),
240 fParseIntegerOnly(FALSE
),
242 fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE
)
247 // -------------------------------------
249 NumberFormat::~NumberFormat()
253 SharedNumberFormat::~SharedNumberFormat() {
257 // -------------------------------------
260 NumberFormat::NumberFormat(const NumberFormat
&source
)
266 // -------------------------------------
267 // assignment operator
270 NumberFormat::operator=(const NumberFormat
& rhs
)
274 Format::operator=(rhs
);
275 fGroupingUsed
= rhs
.fGroupingUsed
;
276 fMaxIntegerDigits
= rhs
.fMaxIntegerDigits
;
277 fMinIntegerDigits
= rhs
.fMinIntegerDigits
;
278 fMaxFractionDigits
= rhs
.fMaxFractionDigits
;
279 fMinFractionDigits
= rhs
.fMinFractionDigits
;
280 fParseIntegerOnly
= rhs
.fParseIntegerOnly
;
281 u_strncpy(fCurrency
, rhs
.fCurrency
, 3);
283 fLenient
= rhs
.fLenient
;
284 fCapitalizationContext
= rhs
.fCapitalizationContext
;
289 // -------------------------------------
292 NumberFormat::operator==(const Format
& that
) const
294 // Format::operator== guarantees this cast is safe
295 NumberFormat
* other
= (NumberFormat
*)&that
;
298 // This code makes it easy to determine why two format objects that should
301 if (!Format::operator==(that
)) {
302 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
305 if (!(fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
306 fMinIntegerDigits
== other
->fMinIntegerDigits
)) {
307 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
308 debug("Integer digits !=");
310 if (!(fMaxFractionDigits
== other
->fMaxFractionDigits
&&
311 fMinFractionDigits
== other
->fMinFractionDigits
)) {
312 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
313 debug("Fraction digits !=");
315 if (!(fGroupingUsed
== other
->fGroupingUsed
)) {
316 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
317 debug("fGroupingUsed != ");
319 if (!(fParseIntegerOnly
== other
->fParseIntegerOnly
)) {
320 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
321 debug("fParseIntegerOnly != ");
323 if (!(u_strcmp(fCurrency
, other
->fCurrency
) == 0)) {
324 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
325 debug("fCurrency !=");
327 if (!(fLenient
== other
->fLenient
)) {
328 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
329 debug("fLenient != ");
331 if (!(fCapitalizationContext
== other
->fCapitalizationContext
)) {
332 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
333 debug("fCapitalizationContext != ");
335 if (!first
) { printf(" ]"); }
338 return ((this == &that
) ||
339 ((Format::operator==(that
) &&
340 fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
341 fMinIntegerDigits
== other
->fMinIntegerDigits
&&
342 fMaxFractionDigits
== other
->fMaxFractionDigits
&&
343 fMinFractionDigits
== other
->fMinFractionDigits
&&
344 fGroupingUsed
== other
->fGroupingUsed
&&
345 fParseIntegerOnly
== other
->fParseIntegerOnly
&&
346 u_strcmp(fCurrency
, other
->fCurrency
) == 0 &&
347 fLenient
== other
->fLenient
&&
348 fCapitalizationContext
== other
->fCapitalizationContext
)));
351 // -------------------------------------
352 // Default implementation sets unsupported error; subclasses should
356 NumberFormat::format(double /* unused number */,
357 UnicodeString
& toAppendTo
,
358 FieldPositionIterator
* /* unused posIter */,
359 UErrorCode
& status
) const
361 if (!U_FAILURE(status
)) {
362 status
= U_UNSUPPORTED_ERROR
;
367 // -------------------------------------
368 // Default implementation sets unsupported error; subclasses should
372 NumberFormat::format(int32_t /* unused number */,
373 UnicodeString
& toAppendTo
,
374 FieldPositionIterator
* /* unused posIter */,
375 UErrorCode
& status
) const
377 if (!U_FAILURE(status
)) {
378 status
= U_UNSUPPORTED_ERROR
;
383 // -------------------------------------
384 // Default implementation sets unsupported error; subclasses should
388 NumberFormat::format(int64_t /* unused number */,
389 UnicodeString
& toAppendTo
,
390 FieldPositionIterator
* /* unused posIter */,
391 UErrorCode
& status
) const
393 if (!U_FAILURE(status
)) {
394 status
= U_UNSUPPORTED_ERROR
;
399 // ------------------------------------------
400 // These functions add the status code, just fall back to the non-status versions
402 NumberFormat::format(double number
,
403 UnicodeString
& appendTo
,
405 UErrorCode
&status
) const {
406 if(U_SUCCESS(status
)) {
407 return format(number
,appendTo
,pos
);
414 NumberFormat::format(int32_t number
,
415 UnicodeString
& appendTo
,
417 UErrorCode
&status
) const {
418 if(U_SUCCESS(status
)) {
419 return format(number
,appendTo
,pos
);
426 NumberFormat::format(int64_t number
,
427 UnicodeString
& appendTo
,
429 UErrorCode
&status
) const {
430 if(U_SUCCESS(status
)) {
431 return format(number
,appendTo
,pos
);
439 // -------------------------------------
440 // Decimal Number format() default implementation
441 // Subclasses do not normally override this function, but rather the DigitList
442 // formatting functions..
443 // The expected call chain from here is
445 // NumberFormat::format(Formattable ->
446 // DecimalFormat::format(DigitList
448 // Or, for subclasses of Formattable that do not know about DigitList,
450 // NumberFormat::format(Formattable ->
451 // NumberFormat::format(DigitList ->
452 // XXXFormat::format(double
455 NumberFormat::format(StringPiece decimalNum
,
456 UnicodeString
& toAppendTo
,
457 FieldPositionIterator
* fpi
,
458 UErrorCode
& status
) const
461 f
.setDecimalNumber(decimalNum
, status
);
462 format(f
, toAppendTo
, fpi
, status
);
468 // Formats the number object and save the format
469 // result in the toAppendTo string buffer.
471 // utility to save/restore state, used in two overloads
472 // of format(const Formattable&...) below.
474 * Old purpose of ArgExtractor was to avoid const. Not thread safe!
476 * keeping it around as a shim.
479 const Formattable
* num
;
484 ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
);
487 const Formattable
* number(void) const;
488 const UChar
*iso(void) const;
489 UBool
wasCurrency(void) const;
492 inline const Formattable
*
493 ArgExtractor::number(void) const {
498 ArgExtractor::wasCurrency(void) const {
503 ArgExtractor::iso(void) const {
507 ArgExtractor::ArgExtractor(const NumberFormat
& /*nf*/, const Formattable
& obj
, UErrorCode
& /*status*/)
508 : num(&obj
), fWasCurrency(FALSE
) {
510 const UObject
* o
= obj
.getObject(); // most commonly o==NULL
511 const CurrencyAmount
* amt
;
512 if (o
!= NULL
&& (amt
= dynamic_cast<const CurrencyAmount
*>(o
)) != NULL
) {
513 // getISOCurrency() returns a pointer to internal storage, so we
514 // copy it to retain it across the call to setCurrency().
515 //const UChar* curr = amt->getISOCurrency();
516 u_strcpy(save
, amt
->getISOCurrency());
517 num
= &amt
->getNumber();
524 ArgExtractor::~ArgExtractor() {
527 UnicodeString
& NumberFormat::format(const DigitList
&number
,
528 UnicodeString
& appendTo
,
529 FieldPositionIterator
* posIter
,
530 UErrorCode
& status
) const {
531 // DecimalFormat overrides this function, and handles DigitList based big decimals.
532 // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
533 // so this default implementation falls back to formatting decimal numbers as doubles.
534 if (U_FAILURE(status
)) {
537 double dnum
= number
.getDouble();
538 format(dnum
, appendTo
, posIter
, status
);
545 NumberFormat::format(const DigitList
&number
,
546 UnicodeString
& appendTo
,
548 UErrorCode
&status
) const {
549 // DecimalFormat overrides this function, and handles DigitList based big decimals.
550 // Other subclasses (ChoiceFormat) do not (yet) handle DigitLists,
551 // so this default implementation falls back to formatting decimal numbers as doubles.
552 if (U_FAILURE(status
)) {
555 double dnum
= number
.getDouble();
556 format(dnum
, appendTo
, pos
, status
);
561 NumberFormat::format(const Formattable
& obj
,
562 UnicodeString
& appendTo
,
564 UErrorCode
& status
) const
566 if (U_FAILURE(status
)) return appendTo
;
568 ArgExtractor
arg(*this, obj
, status
);
569 const Formattable
*n
= arg
.number();
570 const UChar
*iso
= arg
.iso();
572 if(arg
.wasCurrency() && u_strcmp(iso
, getCurrency())) {
573 // trying to format a different currency.
574 // Right now, we clone.
575 LocalPointer
<NumberFormat
> cloneFmt((NumberFormat
*)this->clone());
576 cloneFmt
->setCurrency(iso
, status
);
577 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
578 return cloneFmt
->format(*n
, appendTo
, pos
, status
);
581 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
582 // Decimal Number. We will have a DigitList available if the value was
583 // set to a decimal number, or if the value originated with a parse.
585 // The default implementation for formatting a DigitList converts it
586 // to a double, and formats that, allowing formatting classes that don't
587 // know about DigitList to continue to operate as they had.
589 // DecimalFormat overrides the DigitList formatting functions.
590 format(*n
->getDigitList(), appendTo
, pos
, status
);
592 switch (n
->getType()) {
593 case Formattable::kDouble
:
594 format(n
->getDouble(), appendTo
, pos
);
596 case Formattable::kLong
:
597 format(n
->getLong(), appendTo
, pos
);
599 case Formattable::kInt64
:
600 format(n
->getInt64(), appendTo
, pos
);
603 status
= U_INVALID_FORMAT_ERROR
;
611 // -------------------------------------x
612 // Formats the number object and save the format
613 // result in the toAppendTo string buffer.
616 NumberFormat::format(const Formattable
& obj
,
617 UnicodeString
& appendTo
,
618 FieldPositionIterator
* posIter
,
619 UErrorCode
& status
) const
621 if (U_FAILURE(status
)) return appendTo
;
623 ArgExtractor
arg(*this, obj
, status
);
624 const Formattable
*n
= arg
.number();
625 const UChar
*iso
= arg
.iso();
627 if(arg
.wasCurrency() && u_strcmp(iso
, getCurrency())) {
628 // trying to format a different currency.
629 // Right now, we clone.
630 LocalPointer
<NumberFormat
> cloneFmt((NumberFormat
*)this->clone());
631 cloneFmt
->setCurrency(iso
, status
);
632 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
633 return cloneFmt
->format(*n
, appendTo
, posIter
, status
);
636 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
638 format(*n
->getDigitList(), appendTo
, posIter
, status
);
640 switch (n
->getType()) {
641 case Formattable::kDouble
:
642 format(n
->getDouble(), appendTo
, posIter
, status
);
644 case Formattable::kLong
:
645 format(n
->getLong(), appendTo
, posIter
, status
);
647 case Formattable::kInt64
:
648 format(n
->getInt64(), appendTo
, posIter
, status
);
651 status
= U_INVALID_FORMAT_ERROR
;
659 // -------------------------------------
662 NumberFormat::format(int64_t number
,
663 UnicodeString
& appendTo
,
664 FieldPosition
& pos
) const
666 // default so we don't introduce a new abstract method
667 return format((int32_t)number
, appendTo
, pos
);
670 // -------------------------------------
671 // Parses the string and save the result object as well
672 // as the final parsed position.
675 NumberFormat::parseObject(const UnicodeString
& source
,
677 ParsePosition
& parse_pos
) const
679 parse(source
, result
, parse_pos
);
682 // -------------------------------------
683 // Formats a double number and save the result in a string.
686 NumberFormat::format(double number
, UnicodeString
& appendTo
) const
688 FieldPosition
pos(FieldPosition::DONT_CARE
);
689 return format(number
, appendTo
, pos
);
692 // -------------------------------------
693 // Formats a long number and save the result in a string.
696 NumberFormat::format(int32_t number
, UnicodeString
& appendTo
) const
698 FieldPosition
pos(FieldPosition::DONT_CARE
);
699 return format(number
, appendTo
, pos
);
702 // -------------------------------------
703 // Formats a long number and save the result in a string.
706 NumberFormat::format(int64_t number
, UnicodeString
& appendTo
) const
708 FieldPosition
pos(FieldPosition::DONT_CARE
);
709 return format(number
, appendTo
, pos
);
712 // -------------------------------------
713 // Parses the text and save the result object. If the returned
714 // parse position is 0, that means the parsing failed, the status
715 // code needs to be set to failure. Ignores the returned parse
716 // position, otherwise.
719 NumberFormat::parse(const UnicodeString
& text
,
721 UErrorCode
& status
) const
723 if (U_FAILURE(status
)) return;
725 ParsePosition
parsePosition(0);
726 parse(text
, result
, parsePosition
);
727 if (parsePosition
.getIndex() == 0) {
728 status
= U_INVALID_FORMAT_ERROR
;
732 CurrencyAmount
* NumberFormat::parseCurrency(const UnicodeString
& text
,
733 ParsePosition
& pos
) const {
734 // Default implementation only -- subclasses should override
735 Formattable parseResult
;
736 int32_t start
= pos
.getIndex();
737 parse(text
, parseResult
, pos
);
738 if (pos
.getIndex() != start
) {
740 UErrorCode ec
= U_ZERO_ERROR
;
741 getEffectiveCurrency(curr
, ec
);
743 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curr
, ec
), ec
);
745 pos
.setIndex(start
); // indicate failure
747 return currAmt
.orphan();
754 // -------------------------------------
755 // Sets to only parse integers.
758 NumberFormat::setParseIntegerOnly(UBool value
)
760 fParseIntegerOnly
= value
;
763 // -------------------------------------
764 // Sets whether lenient parse is enabled.
767 NumberFormat::setLenient(UBool enable
)
772 // -------------------------------------
773 // Create a number style NumberFormat instance with the default locale.
775 NumberFormat
* U_EXPORT2
776 NumberFormat::createInstance(UErrorCode
& status
)
778 return createInstance(Locale::getDefault(), UNUM_DECIMAL
, status
);
781 // -------------------------------------
782 // Create a number style NumberFormat instance with the inLocale locale.
784 NumberFormat
* U_EXPORT2
785 NumberFormat::createInstance(const Locale
& inLocale
, UErrorCode
& status
)
787 return createInstance(inLocale
, UNUM_DECIMAL
, status
);
790 // -------------------------------------
791 // Create a currency style NumberFormat instance with the default locale.
793 NumberFormat
* U_EXPORT2
794 NumberFormat::createCurrencyInstance(UErrorCode
& status
)
796 return createCurrencyInstance(Locale::getDefault(), status
);
799 // -------------------------------------
800 // Create a currency style NumberFormat instance with the inLocale locale.
802 NumberFormat
* U_EXPORT2
803 NumberFormat::createCurrencyInstance(const Locale
& inLocale
, UErrorCode
& status
)
805 return createInstance(inLocale
, UNUM_CURRENCY
, status
);
808 // -------------------------------------
809 // Create a percent style NumberFormat instance with the default locale.
811 NumberFormat
* U_EXPORT2
812 NumberFormat::createPercentInstance(UErrorCode
& status
)
814 return createInstance(Locale::getDefault(), UNUM_PERCENT
, status
);
817 // -------------------------------------
818 // Create a percent style NumberFormat instance with the inLocale locale.
820 NumberFormat
* U_EXPORT2
821 NumberFormat::createPercentInstance(const Locale
& inLocale
, UErrorCode
& status
)
823 return createInstance(inLocale
, UNUM_PERCENT
, status
);
826 // -------------------------------------
827 // Create a scientific style NumberFormat instance with the default locale.
829 NumberFormat
* U_EXPORT2
830 NumberFormat::createScientificInstance(UErrorCode
& status
)
832 return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC
, status
);
835 // -------------------------------------
836 // Create a scientific style NumberFormat instance with the inLocale locale.
838 NumberFormat
* U_EXPORT2
839 NumberFormat::createScientificInstance(const Locale
& inLocale
, UErrorCode
& status
)
841 return createInstance(inLocale
, UNUM_SCIENTIFIC
, status
);
844 // -------------------------------------
846 const Locale
* U_EXPORT2
847 NumberFormat::getAvailableLocales(int32_t& count
)
849 return Locale::getAvailableLocales(count
);
852 // ------------------------------------------
856 //-------------------------------------------
858 #if !UCONFIG_NO_SERVICE
860 // -------------------------------------
862 class ICUNumberFormatFactory
: public ICUResourceBundleFactory
{
864 virtual ~ICUNumberFormatFactory();
866 virtual UObject
* handleCreate(const Locale
& loc
, int32_t kind
, const ICUService
* /* service */, UErrorCode
& status
) const {
867 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
871 ICUNumberFormatFactory::~ICUNumberFormatFactory() {}
873 // -------------------------------------
875 class NFFactory
: public LocaleKeyFactory
{
877 NumberFormatFactory
* _delegate
;
881 NFFactory(NumberFormatFactory
* delegate
)
882 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
883 , _delegate(delegate
)
888 virtual ~NFFactory();
890 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const
892 if (handlesKey(key
, status
)) {
893 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
895 lkey
.canonicalLocale(loc
);
896 int32_t kind
= lkey
.kind();
898 UObject
* result
= _delegate
->createFormat(loc
, (UNumberFormatStyle
)kind
);
899 if (result
== NULL
) {
900 result
= service
->getKey((ICUServiceKey
&)key
/* cast away const */, NULL
, this, status
);
909 * Return the set of ids that this factory supports (visible or
910 * otherwise). This can be called often and might need to be
911 * cached if it is expensive to create.
913 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
915 if (U_SUCCESS(status
)) {
918 const UnicodeString
* const idlist
= _delegate
->getSupportedIDs(count
, status
);
919 ((NFFactory
*)this)->_ids
= new Hashtable(status
); /* cast away const */
921 for (int i
= 0; i
< count
; ++i
) {
922 _ids
->put(idlist
[i
], (void*)this, status
);
932 NFFactory::~NFFactory()
938 class ICUNumberFormatService
: public ICULocaleService
{
940 ICUNumberFormatService()
941 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
943 UErrorCode status
= U_ZERO_ERROR
;
944 registerFactory(new ICUNumberFormatFactory(), status
);
947 virtual ~ICUNumberFormatService();
949 virtual UObject
* cloneInstance(UObject
* instance
) const {
950 return ((NumberFormat
*)instance
)->clone();
953 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* /* actualID */, UErrorCode
& status
) const {
954 LocaleKey
& lkey
= (LocaleKey
&)key
;
955 int32_t kind
= lkey
.kind();
957 lkey
.currentLocale(loc
);
958 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
961 virtual UBool
isDefault() const {
962 return countFactories() == 1;
966 ICUNumberFormatService::~ICUNumberFormatService() {}
968 // -------------------------------------
970 static void U_CALLCONV
initNumberFormatService() {
971 U_ASSERT(gService
== NULL
);
972 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
973 gService
= new ICUNumberFormatService();
976 static ICULocaleService
*
977 getNumberFormatService(void)
979 umtx_initOnce(gServiceInitOnce
, &initNumberFormatService
);
983 static UBool
haveService() {
984 return !gServiceInitOnce
.isReset() && (getNumberFormatService() != NULL
);
987 // -------------------------------------
989 URegistryKey U_EXPORT2
990 NumberFormat::registerFactory(NumberFormatFactory
* toAdopt
, UErrorCode
& status
)
992 ICULocaleService
*service
= getNumberFormatService();
994 NFFactory
*tempnnf
= new NFFactory(toAdopt
);
995 if (tempnnf
!= NULL
) {
996 return service
->registerFactory(tempnnf
, status
);
999 status
= U_MEMORY_ALLOCATION_ERROR
;
1003 // -------------------------------------
1006 NumberFormat::unregister(URegistryKey key
, UErrorCode
& status
)
1008 if (U_FAILURE(status
)) {
1011 if (haveService()) {
1012 return gService
->unregister(key
, status
);
1014 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1019 // -------------------------------------
1020 StringEnumeration
* U_EXPORT2
1021 NumberFormat::getAvailableLocales(void)
1023 ICULocaleService
*service
= getNumberFormatService();
1025 return service
->getAvailableLocales();
1027 return NULL
; // no way to return error condition
1029 #endif /* UCONFIG_NO_SERVICE */
1030 // -------------------------------------
1032 enum { kKeyValueLenMax
= 32 };
1035 NumberFormat::internalCreateInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1036 if (kind
== UNUM_CURRENCY
) {
1037 char cfKeyValue
[kKeyValueLenMax
] = {0};
1038 UErrorCode kvStatus
= U_ZERO_ERROR
;
1039 int32_t kLen
= loc
.getKeywordValue("cf", cfKeyValue
, kKeyValueLenMax
, kvStatus
);
1040 if (U_SUCCESS(kvStatus
) && kLen
> 0 && uprv_strcmp(cfKeyValue
,"account")==0) {
1041 kind
= UNUM_CURRENCY_ACCOUNTING
;
1044 #if !UCONFIG_NO_SERVICE
1045 if (haveService()) {
1046 return (NumberFormat
*)gService
->get(loc
, kind
, status
);
1049 return makeInstance(loc
, kind
, status
);
1052 NumberFormat
* U_EXPORT2
1053 NumberFormat::createInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1054 if (kind
!= UNUM_DECIMAL
) {
1055 return internalCreateInstance(loc
, kind
, status
);
1057 const SharedNumberFormat
*shared
= createSharedInstance(loc
, kind
, status
);
1058 if (U_FAILURE(status
)) {
1061 NumberFormat
*result
= static_cast<NumberFormat
*>((*shared
)->clone());
1062 shared
->removeRef();
1063 if (result
== NULL
) {
1064 status
= U_MEMORY_ALLOCATION_ERROR
;
1070 // -------------------------------------
1071 // Checks if the thousand/10 thousand grouping is used in the
1072 // NumberFormat instance.
1075 NumberFormat::isGroupingUsed() const
1077 return fGroupingUsed
;
1080 // -------------------------------------
1081 // Sets to use the thousand/10 thousand grouping in the
1082 // NumberFormat instance.
1085 NumberFormat::setGroupingUsed(UBool newValue
)
1087 fGroupingUsed
= newValue
;
1090 // -------------------------------------
1091 // Gets the maximum number of digits for the integral part for
1092 // this NumberFormat instance.
1094 int32_t NumberFormat::getMaximumIntegerDigits() const
1096 return fMaxIntegerDigits
;
1099 // -------------------------------------
1100 // Sets the maximum number of digits for the integral part for
1101 // this NumberFormat instance.
1104 NumberFormat::setMaximumIntegerDigits(int32_t newValue
)
1106 fMaxIntegerDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMaxIntegerDigits
));
1107 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1108 fMinIntegerDigits
= fMaxIntegerDigits
;
1111 // -------------------------------------
1112 // Gets the minimum number of digits for the integral part for
1113 // this NumberFormat instance.
1116 NumberFormat::getMinimumIntegerDigits() const
1118 return fMinIntegerDigits
;
1121 // -------------------------------------
1122 // Sets the minimum number of digits for the integral part for
1123 // this NumberFormat instance.
1126 NumberFormat::setMinimumIntegerDigits(int32_t newValue
)
1128 fMinIntegerDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMinIntegerDigits
));
1129 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1130 fMaxIntegerDigits
= fMinIntegerDigits
;
1133 // -------------------------------------
1134 // Gets the maximum number of digits for the fractional part for
1135 // this NumberFormat instance.
1138 NumberFormat::getMaximumFractionDigits() const
1140 return fMaxFractionDigits
;
1143 // -------------------------------------
1144 // Sets the maximum number of digits for the fractional part for
1145 // this NumberFormat instance.
1148 NumberFormat::setMaximumFractionDigits(int32_t newValue
)
1150 fMaxFractionDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMaxIntegerDigits
));
1151 if(fMaxFractionDigits
< fMinFractionDigits
)
1152 fMinFractionDigits
= fMaxFractionDigits
;
1155 // -------------------------------------
1156 // Gets the minimum number of digits for the fractional part for
1157 // this NumberFormat instance.
1160 NumberFormat::getMinimumFractionDigits() const
1162 return fMinFractionDigits
;
1165 // -------------------------------------
1166 // Sets the minimum number of digits for the fractional part for
1167 // this NumberFormat instance.
1170 NumberFormat::setMinimumFractionDigits(int32_t newValue
)
1172 fMinFractionDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMinIntegerDigits
));
1173 if (fMaxFractionDigits
< fMinFractionDigits
)
1174 fMaxFractionDigits
= fMinFractionDigits
;
1177 // -------------------------------------
1179 void NumberFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
1180 if (U_FAILURE(ec
)) {
1184 u_strncpy(fCurrency
, theCurrency
, 3);
1191 const char16_t* NumberFormat::getCurrency() const {
1195 void NumberFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
1196 const UChar
* c
= getCurrency();
1198 u_strncpy(result
, c
, 3);
1201 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
1203 loc
= uloc_getDefault();
1205 ucurr_forLocale(loc
, result
, 4, &ec
);
1209 //----------------------------------------------------------------------
1212 void NumberFormat::setContext(UDisplayContext value
, UErrorCode
& status
)
1214 if (U_FAILURE(status
))
1216 if ( (UDisplayContextType
)((uint32_t)value
>> 8) == UDISPCTX_TYPE_CAPITALIZATION
) {
1217 fCapitalizationContext
= value
;
1219 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1224 UDisplayContext
NumberFormat::getContext(UDisplayContextType type
, UErrorCode
& status
) const
1226 if (U_FAILURE(status
))
1227 return (UDisplayContext
)0;
1228 if (type
!= UDISPCTX_TYPE_CAPITALIZATION
) {
1229 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1230 return (UDisplayContext
)0;
1232 return fCapitalizationContext
;
1236 // -------------------------------------
1237 // Creates the NumberFormat instance of the specified style (number, currency,
1238 // or percent) for the desired locale.
1240 static void U_CALLCONV
nscacheInit() {
1241 U_ASSERT(NumberingSystem_cache
== NULL
);
1242 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
1243 UErrorCode status
= U_ZERO_ERROR
;
1244 NumberingSystem_cache
= uhash_open(uhash_hashLong
,
1248 if (U_FAILURE(status
)) {
1249 // Number Format code will run with no cache if creation fails.
1250 NumberingSystem_cache
= NULL
;
1253 uhash_setValueDeleter(NumberingSystem_cache
, deleteNumberingSystem
);
1256 template<> U_I18N_API
1257 const SharedNumberFormat
*LocaleCacheKey
<SharedNumberFormat
>::createObject(
1258 const void * /*unused*/, UErrorCode
&status
) const {
1259 const char *localeId
= fLoc
.getName();
1260 NumberFormat
*nf
= NumberFormat::internalCreateInstance(
1261 localeId
, UNUM_DECIMAL
, status
);
1262 if (U_FAILURE(status
)) {
1265 SharedNumberFormat
*result
= new SharedNumberFormat(nf
);
1266 if (result
== NULL
) {
1267 status
= U_MEMORY_ALLOCATION_ERROR
;
1275 const SharedNumberFormat
* U_EXPORT2
1276 NumberFormat::createSharedInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1277 if (U_FAILURE(status
)) {
1280 if (kind
!= UNUM_DECIMAL
) {
1281 status
= U_UNSUPPORTED_ERROR
;
1284 const SharedNumberFormat
*result
= NULL
;
1285 UnifiedCache::getByLocale(loc
, result
, status
);
1290 NumberFormat::isStyleSupported(UNumberFormatStyle style
) {
1291 return gLastResortNumberPatterns
[style
] != NULL
;
1295 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1296 UNumberFormatStyle style
,
1297 UErrorCode
& status
) {
1298 return makeInstance(desiredLocale
, style
, false, status
);
1302 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1303 UNumberFormatStyle style
,
1304 UBool mustBeDecimalFormat
,
1305 UErrorCode
& status
) {
1306 if (U_FAILURE(status
)) return NULL
;
1308 if (style
< 0 || style
>= UNUM_FORMAT_STYLE_COUNT
) {
1309 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1313 // Some styles are not supported. This is a result of merging
1314 // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
1315 // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
1316 // this one and unum_open().
1317 // The UNUM_PATTERN_ styles are not supported here
1318 // because this method does not take a pattern string.
1319 if (!isStyleSupported(style
)) {
1320 status
= U_UNSUPPORTED_ERROR
;
1324 #if U_PLATFORM_USES_ONLY_WIN32_API
1325 if (!mustBeDecimalFormat
) {
1327 int32_t count
= desiredLocale
.getKeywordValue("compat", buffer
, sizeof(buffer
), status
);
1329 // if the locale has "@compat=host", create a host-specific NumberFormat
1330 if (U_SUCCESS(status
) && count
> 0 && uprv_strcmp(buffer
, "host") == 0) {
1331 Win32NumberFormat
*f
= NULL
;
1340 case UNUM_CURRENCY_ISO
: // do not support plural formatting here
1341 case UNUM_CURRENCY_PLURAL
:
1342 case UNUM_CURRENCY_ACCOUNTING
:
1343 case UNUM_CASH_CURRENCY
:
1344 case UNUM_CURRENCY_STANDARD
:
1345 f
= new Win32NumberFormat(desiredLocale
, curr
, status
);
1347 if (U_SUCCESS(status
)) {
1359 // Use numbering system cache hashtable
1360 umtx_initOnce(gNSCacheInitOnce
, &nscacheInit
);
1362 // Get cached numbering system
1363 LocalPointer
<NumberingSystem
> ownedNs
;
1364 NumberingSystem
*ns
= NULL
;
1365 if (NumberingSystem_cache
!= NULL
) {
1366 // TODO: Bad hash key usage, see ticket #8504.
1367 int32_t hashKey
= desiredLocale
.hashCode();
1369 Mutex
lock(&nscacheMutex
);
1370 ns
= (NumberingSystem
*)uhash_iget(NumberingSystem_cache
, hashKey
);
1372 ns
= NumberingSystem::createInstance(desiredLocale
,status
);
1373 uhash_iput(NumberingSystem_cache
, hashKey
, (void*)ns
, &status
);
1376 ownedNs
.adoptInstead(NumberingSystem::createInstance(desiredLocale
,status
));
1377 ns
= ownedNs
.getAlias();
1380 // check results of getting a numbering system
1381 if (U_FAILURE(status
)) {
1385 if (mustBeDecimalFormat
&& ns
->isAlgorithmic()) {
1386 status
= U_UNSUPPORTED_ERROR
;
1390 LocalPointer
<DecimalFormatSymbols
> symbolsToAdopt
;
1391 UnicodeString pattern
;
1392 LocalUResourceBundlePointer
ownedResource(ures_open(NULL
, desiredLocale
.getName(), &status
));
1393 if (U_FAILURE(status
)) {
1397 // Loads the decimal symbols of the desired locale.
1398 symbolsToAdopt
.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(desiredLocale
, status
), status
);
1399 if (U_FAILURE(status
)) {
1403 UResourceBundle
*resource
= ownedResource
.orphan();
1404 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, gNumberElements
, NULL
, &status
);
1405 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &status
);
1406 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1407 ownedResource
.adoptInstead(resource
);
1410 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[style
], &patLen
, &status
);
1412 // Didn't find a pattern specific to the numbering system, so fall back to "latn"
1413 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(gLatn
,ns
->getName())) {
1414 status
= U_ZERO_ERROR
;
1415 resource
= ures_getByKeyWithFallback(numElements
, gLatn
, resource
, &status
);
1416 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1417 patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[style
], &patLen
, &status
);
1420 ures_close(numElements
);
1422 // Creates the specified decimal format style of the desired locale.
1423 pattern
.setTo(TRUE
, patResStr
, patLen
);
1425 if (U_FAILURE(status
)) {
1428 if(style
==UNUM_CURRENCY
|| style
== UNUM_CURRENCY_ISO
|| style
== UNUM_CURRENCY_ACCOUNTING
1429 || style
== UNUM_CASH_CURRENCY
|| style
== UNUM_CURRENCY_STANDARD
){
1430 const UChar
* currPattern
= symbolsToAdopt
->getCurrencyPattern();
1431 if(currPattern
!=NULL
){
1432 pattern
.setTo(currPattern
, u_strlen(currPattern
));
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 if its memory allocation fails.
1482 DecimalFormatSymbols
*syms
= symbolsToAdopt
.orphan();
1483 DecimalFormat
* df
= new DecimalFormat(pattern
, syms
, style
, status
);
1485 // if it is cash currency style, setCurrencyUsage with usage
1486 if (style
== UNUM_CASH_CURRENCY
){
1487 df
->setCurrencyUsage(UCURR_USAGE_CASH
, &status
);
1490 if (U_FAILURE(status
)) {
1498 status
= U_MEMORY_ALLOCATION_ERROR
;
1503 f
->setLocaleIDs(ures_getLocaleByType(ownedResource
.getAlias(), ULOC_VALID_LOCALE
, &status
),
1504 ures_getLocaleByType(ownedResource
.getAlias(), ULOC_ACTUAL_LOCALE
, &status
));
1505 if (U_FAILURE(status
)) {
1514 #endif /* #if !UCONFIG_NO_FORMATTING */