2 *******************************************************************************
3 * Copyright (C) 1997-2014, 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/18/97 clhuang Implemented with C++ APIs.
14 * 04/17/97 aliu Enlarged MAX_INTEGER_DIGITS to fully accomodate the
15 * largest double, by default.
16 * Changed DigitCount to int per code review.
17 * 07/20/98 stephen Changed operator== to check for grouping
18 * Changed setMaxIntegerDigits per Java implementation.
19 * Changed setMinIntegerDigits per Java implementation.
20 * Changed setMinFractionDigits per Java implementation.
21 * Changed setMaxFractionDigits per Java implementation.
22 ********************************************************************************
25 #include "unicode/utypes.h"
27 #if !UCONFIG_NO_FORMATTING
29 #include "unicode/numfmt.h"
30 #include "unicode/locid.h"
31 #include "unicode/dcfmtsym.h"
32 #include "unicode/decimfmt.h"
33 #include "unicode/ustring.h"
34 #include "unicode/ucurr.h"
35 #include "unicode/curramt.h"
36 #include "unicode/numsys.h"
37 #include "unicode/rbnf.h"
38 #include "unicode/localpointer.h"
39 #include "unicode/udisplaycontext.h"
54 #include "sharednumberformat.h"
61 static inline void debugout(UnicodeString s
) {
63 s
.extract((int32_t) 0, s
.length(), buf
);
66 #define debug(x) printf("%s", x);
72 // If no number pattern can be located for a locale, this is the last
73 // resort. The patterns are same as the ones in root locale.
74 static const UChar gLastResortDecimalPat
[] = {
75 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */
77 static const UChar gLastResortCurrencyPat
[] = {
78 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
80 static const UChar gLastResortPercentPat
[] = {
81 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */
83 static const UChar gLastResortScientificPat
[] = {
84 0x23, 0x45, 0x30, 0 /* "#E0" */
86 static const UChar gLastResortIsoCurrencyPat
[] = {
87 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */
89 static const UChar gLastResortPluralCurrencyPat
[] = {
90 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/
92 static const UChar gLastResortAccountingCurrencyPat
[] = {
93 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */
96 static const UChar gSingleCurrencySign
[] = {0xA4, 0};
97 static const UChar gDoubleCurrencySign
[] = {0xA4, 0xA4, 0};
99 static const UChar gSlash
= 0x2f;
101 // If the maximum base 10 exponent were 4, then the largest number would
102 // be 99,999 which has 5 digits.
103 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
104 // With big decimal, the max exponent is 999,999,999 and the max number of digits is the same, 999,999,999
105 const int32_t icu::NumberFormat::gDefaultMaxIntegerDigits
= 2000000000;
106 const int32_t icu::NumberFormat::gDefaultMinIntegerDigits
= 127;
108 static const UChar
* const gLastResortNumberPatterns
[UNUM_FORMAT_STYLE_COUNT
] = {
109 NULL
, // UNUM_PATTERN_DECIMAL
110 gLastResortDecimalPat
, // UNUM_DECIMAL
111 gLastResortCurrencyPat
, // UNUM_CURRENCY
112 gLastResortPercentPat
, // UNUM_PERCENT
113 gLastResortScientificPat
, // UNUM_SCIENTIFIC
114 NULL
, // UNUM_SPELLOUT
115 NULL
, // UNUM_ORDINAL
116 NULL
, // UNUM_DURATION
117 NULL
, // UNUM_NUMBERING_SYSTEM
118 NULL
, // UNUM_PATTERN_RULEBASED
119 gLastResortIsoCurrencyPat
, // UNUM_CURRENCY_ISO
120 gLastResortPluralCurrencyPat
, // UNUM_CURRENCY_PLURAL
121 gLastResortAccountingCurrencyPat
// UNUM_CURRENCY_ACCOUNTING
124 // Keys used for accessing resource bundles
126 static const char *gNumberElements
= "NumberElements";
127 static const char *gLatn
= "latn";
128 static const char *gPatterns
= "patterns";
129 static const char *gFormatKeys
[UNUM_FORMAT_STYLE_COUNT
] = {
130 NULL
, // UNUM_PATTERN_DECIMAL
131 "decimalFormat", // UNUM_DECIMAL
132 "currencyFormat", // UNUM_CURRENCY
133 "percentFormat", // UNUM_PERCENT
134 "scientificFormat", // UNUM_SCIENTIFIC
135 NULL
, // UNUM_SPELLOUT
136 NULL
, // UNUM_ORDINAL
137 NULL
, // UNUM_DURATION
138 NULL
, // UNUM_NUMBERING_SYSTEM
139 NULL
, // UNUM_PATTERN_RULEBASED
140 // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
141 // the pattern is the same as the pattern of UNUM_CURRENCY
142 // except for replacing the single currency sign with
143 // double currency sign or triple currency sign.
144 "currencyFormat", // UNUM_CURRENCY_ISO
145 "currencyFormat", // UNUM_CURRENCY_PLURAL
146 "accountingFormat" // UNUM_CURRENCY_ACCOUNTING
149 static icu::LRUCache
*gNumberFormatCache
= NULL
;
150 static UMutex gNumberFormatCacheMutex
= U_MUTEX_INITIALIZER
;
151 static icu::UInitOnce gNumberFormatCacheInitOnce
= U_INITONCE_INITIALIZER
;
153 // Static hashtable cache of NumberingSystem objects used by NumberFormat
154 static UHashtable
* NumberingSystem_cache
= NULL
;
155 static UMutex nscacheMutex
= U_MUTEX_INITIALIZER
;
156 static icu::UInitOnce gNSCacheInitOnce
= U_INITONCE_INITIALIZER
;
158 #if !UCONFIG_NO_SERVICE
159 static icu::ICULocaleService
* gService
= NULL
;
160 static icu::UInitOnce gServiceInitOnce
= U_INITONCE_INITIALIZER
;
164 * Release all static memory held by Number Format.
167 static void U_CALLCONV
168 deleteNumberingSystem(void *obj
) {
169 delete (icu::NumberingSystem
*)obj
;
172 static UBool U_CALLCONV
numfmt_cleanup(void) {
173 #if !UCONFIG_NO_SERVICE
174 gServiceInitOnce
.reset();
180 gNSCacheInitOnce
.reset();
181 if (NumberingSystem_cache
) {
182 // delete NumberingSystem_cache;
183 uhash_close(NumberingSystem_cache
);
184 NumberingSystem_cache
= NULL
;
186 gNumberFormatCacheInitOnce
.reset();
187 if (gNumberFormatCache
) {
188 delete gNumberFormatCache
;
189 gNumberFormatCache
= NULL
;
195 // *****************************************************************************
196 // class NumberFormat
197 // *****************************************************************************
201 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat
)
203 #if !UCONFIG_NO_SERVICE
204 // -------------------------------------
205 // SimpleNumberFormatFactory implementation
206 NumberFormatFactory::~NumberFormatFactory() {}
207 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale
& locale
, UBool visible
)
210 LocaleUtility::initNameFromLocale(locale
, _id
);
213 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
215 UBool
SimpleNumberFormatFactory::visible(void) const {
219 const UnicodeString
*
220 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count
, UErrorCode
& status
) const
222 if (U_SUCCESS(status
)) {
229 #endif /* #if !UCONFIG_NO_SERVICE */
231 // -------------------------------------
232 // default constructor
233 NumberFormat::NumberFormat()
234 : fGroupingUsed(TRUE
),
235 fMaxIntegerDigits(gDefaultMaxIntegerDigits
),
236 fMinIntegerDigits(1),
237 fMaxFractionDigits(3), // invariant, >= minFractionDigits
238 fMinFractionDigits(0),
239 fParseIntegerOnly(FALSE
),
241 fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE
)
246 // -------------------------------------
248 NumberFormat::~NumberFormat()
252 SharedNumberFormat::~SharedNumberFormat() {
256 // -------------------------------------
259 NumberFormat::NumberFormat(const NumberFormat
&source
)
265 // -------------------------------------
266 // assignment operator
269 NumberFormat::operator=(const NumberFormat
& rhs
)
273 Format::operator=(rhs
);
274 fGroupingUsed
= rhs
.fGroupingUsed
;
275 fMaxIntegerDigits
= rhs
.fMaxIntegerDigits
;
276 fMinIntegerDigits
= rhs
.fMinIntegerDigits
;
277 fMaxFractionDigits
= rhs
.fMaxFractionDigits
;
278 fMinFractionDigits
= rhs
.fMinFractionDigits
;
279 fParseIntegerOnly
= rhs
.fParseIntegerOnly
;
280 u_strncpy(fCurrency
, rhs
.fCurrency
, 4);
281 fLenient
= rhs
.fLenient
;
282 fCapitalizationContext
= rhs
.fCapitalizationContext
;
287 // -------------------------------------
290 NumberFormat::operator==(const Format
& that
) const
292 // Format::operator== guarantees this cast is safe
293 NumberFormat
* other
= (NumberFormat
*)&that
;
296 // This code makes it easy to determine why two format objects that should
299 if (!Format::operator==(that
)) {
300 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
303 if (!(fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
304 fMinIntegerDigits
== other
->fMinIntegerDigits
)) {
305 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
306 debug("Integer digits !=");
308 if (!(fMaxFractionDigits
== other
->fMaxFractionDigits
&&
309 fMinFractionDigits
== other
->fMinFractionDigits
)) {
310 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
311 debug("Fraction digits !=");
313 if (!(fGroupingUsed
== other
->fGroupingUsed
)) {
314 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
315 debug("fGroupingUsed != ");
317 if (!(fParseIntegerOnly
== other
->fParseIntegerOnly
)) {
318 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
319 debug("fParseIntegerOnly != ");
321 if (!(u_strcmp(fCurrency
, other
->fCurrency
) == 0)) {
322 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
323 debug("fCurrency !=");
325 if (!(fLenient
== other
->fLenient
)) {
326 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
327 debug("fLenient != ");
329 if (!(fCapitalizationContext
== other
->fCapitalizationContext
)) {
330 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
331 debug("fCapitalizationContext != ");
333 if (!first
) { printf(" ]"); }
336 return ((this == &that
) ||
337 ((Format::operator==(that
) &&
338 fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
339 fMinIntegerDigits
== other
->fMinIntegerDigits
&&
340 fMaxFractionDigits
== other
->fMaxFractionDigits
&&
341 fMinFractionDigits
== other
->fMinFractionDigits
&&
342 fGroupingUsed
== other
->fGroupingUsed
&&
343 fParseIntegerOnly
== other
->fParseIntegerOnly
&&
344 u_strcmp(fCurrency
, other
->fCurrency
) == 0 &&
345 fLenient
== other
->fLenient
&&
346 fCapitalizationContext
== other
->fCapitalizationContext
)));
349 // -------------------------------------
350 // Default implementation sets unsupported error; subclasses should
354 NumberFormat::format(double /* unused number */,
355 UnicodeString
& toAppendTo
,
356 FieldPositionIterator
* /* unused posIter */,
357 UErrorCode
& status
) const
359 if (!U_FAILURE(status
)) {
360 status
= U_UNSUPPORTED_ERROR
;
365 // -------------------------------------
366 // Default implementation sets unsupported error; subclasses should
370 NumberFormat::format(int32_t /* unused number */,
371 UnicodeString
& toAppendTo
,
372 FieldPositionIterator
* /* unused posIter */,
373 UErrorCode
& status
) const
375 if (!U_FAILURE(status
)) {
376 status
= U_UNSUPPORTED_ERROR
;
381 // -------------------------------------
382 // Default implementation sets unsupported error; subclasses should
386 NumberFormat::format(int64_t /* unused number */,
387 UnicodeString
& toAppendTo
,
388 FieldPositionIterator
* /* unused posIter */,
389 UErrorCode
& status
) const
391 if (!U_FAILURE(status
)) {
392 status
= U_UNSUPPORTED_ERROR
;
397 // ------------------------------------------
398 // These functions add the status code, just fall back to the non-status versions
400 NumberFormat::format(double number
,
401 UnicodeString
& appendTo
,
403 UErrorCode
&status
) const {
404 if(U_SUCCESS(status
)) {
405 return format(number
,appendTo
,pos
);
412 NumberFormat::format(int32_t number
,
413 UnicodeString
& appendTo
,
415 UErrorCode
&status
) const {
416 if(U_SUCCESS(status
)) {
417 return format(number
,appendTo
,pos
);
424 NumberFormat::format(int64_t number
,
425 UnicodeString
& appendTo
,
427 UErrorCode
&status
) const {
428 if(U_SUCCESS(status
)) {
429 return format(number
,appendTo
,pos
);
437 // -------------------------------------
438 // Decimal Number format() default implementation
439 // Subclasses do not normally override this function, but rather the DigitList
440 // formatting functions..
441 // The expected call chain from here is
443 // NumberFormat::format(Formattable ->
444 // DecimalFormat::format(DigitList
446 // Or, for subclasses of Formattable that do not know about DigitList,
448 // NumberFormat::format(Formattable ->
449 // NumberFormat::format(DigitList ->
450 // XXXFormat::format(double
453 NumberFormat::format(const StringPiece
&decimalNum
,
454 UnicodeString
& toAppendTo
,
455 FieldPositionIterator
* fpi
,
456 UErrorCode
& status
) const
459 f
.setDecimalNumber(decimalNum
, status
);
460 format(f
, toAppendTo
, fpi
, status
);
466 // Formats the number object and save the format
467 // result in the toAppendTo string buffer.
469 // utility to save/restore state, used in two overloads
470 // of format(const Formattable&...) below.
472 * Old purpose of ArgExtractor was to avoid const. Not thread safe!
474 * keeping it around as a shim.
477 const Formattable
* num
;
482 ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
);
485 const Formattable
* number(void) const;
486 const UChar
*iso(void) const;
487 UBool
wasCurrency(void) const;
490 inline const Formattable
*
491 ArgExtractor::number(void) const {
496 ArgExtractor::wasCurrency(void) const {
501 ArgExtractor::iso(void) const {
505 ArgExtractor::ArgExtractor(const NumberFormat
& /*nf*/, const Formattable
& obj
, UErrorCode
& /*status*/)
506 : num(&obj
), fWasCurrency(FALSE
) {
508 const UObject
* o
= obj
.getObject(); // most commonly o==NULL
509 const CurrencyAmount
* amt
;
510 if (o
!= NULL
&& (amt
= dynamic_cast<const CurrencyAmount
*>(o
)) != NULL
) {
511 // getISOCurrency() returns a pointer to internal storage, so we
512 // copy it to retain it across the call to setCurrency().
513 //const UChar* curr = amt->getISOCurrency();
514 u_strcpy(save
, amt
->getISOCurrency());
515 num
= &amt
->getNumber();
522 ArgExtractor::~ArgExtractor() {
525 UnicodeString
& NumberFormat::format(const DigitList
&number
,
526 UnicodeString
& appendTo
,
527 FieldPositionIterator
* posIter
,
528 UErrorCode
& status
) const {
529 // DecimalFormat overrides this function, and handles DigitList based big decimals.
530 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
531 // so this default implementation falls back to formatting decimal numbers as doubles.
532 if (U_FAILURE(status
)) {
535 double dnum
= number
.getDouble();
536 format(dnum
, appendTo
, posIter
, status
);
543 NumberFormat::format(const DigitList
&number
,
544 UnicodeString
& appendTo
,
546 UErrorCode
&status
) const {
547 // DecimalFormat overrides this function, and handles DigitList based big decimals.
548 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
549 // so this default implementation falls back to formatting decimal numbers as doubles.
550 if (U_FAILURE(status
)) {
553 double dnum
= number
.getDouble();
554 format(dnum
, appendTo
, pos
, status
);
559 NumberFormat::format(const Formattable
& obj
,
560 UnicodeString
& appendTo
,
562 UErrorCode
& status
) const
564 if (U_FAILURE(status
)) return appendTo
;
566 ArgExtractor
arg(*this, obj
, status
);
567 const Formattable
*n
= arg
.number();
568 const UChar
*iso
= arg
.iso();
570 if(arg
.wasCurrency() && u_strcmp(iso
, getCurrency())) {
571 // trying to format a different currency.
572 // Right now, we clone.
573 LocalPointer
<NumberFormat
> cloneFmt((NumberFormat
*)this->clone());
574 cloneFmt
->setCurrency(iso
, status
);
575 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
576 return cloneFmt
->format(*n
, appendTo
, pos
, status
);
579 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
580 // Decimal Number. We will have a DigitList available if the value was
581 // set to a decimal number, or if the value originated with a parse.
583 // The default implementation for formatting a DigitList converts it
584 // to a double, and formats that, allowing formatting classes that don't
585 // know about DigitList to continue to operate as they had.
587 // DecimalFormat overrides the DigitList formatting functions.
588 format(*n
->getDigitList(), appendTo
, pos
, status
);
590 switch (n
->getType()) {
591 case Formattable::kDouble
:
592 format(n
->getDouble(), appendTo
, pos
);
594 case Formattable::kLong
:
595 format(n
->getLong(), appendTo
, pos
);
597 case Formattable::kInt64
:
598 format(n
->getInt64(), appendTo
, pos
);
601 status
= U_INVALID_FORMAT_ERROR
;
609 // -------------------------------------x
610 // Formats the number object and save the format
611 // result in the toAppendTo string buffer.
614 NumberFormat::format(const Formattable
& obj
,
615 UnicodeString
& appendTo
,
616 FieldPositionIterator
* posIter
,
617 UErrorCode
& status
) const
619 if (U_FAILURE(status
)) return appendTo
;
621 ArgExtractor
arg(*this, obj
, status
);
622 const Formattable
*n
= arg
.number();
623 const UChar
*iso
= arg
.iso();
625 if(arg
.wasCurrency() && u_strcmp(iso
, getCurrency())) {
626 // trying to format a different currency.
627 // Right now, we clone.
628 LocalPointer
<NumberFormat
> cloneFmt((NumberFormat
*)this->clone());
629 cloneFmt
->setCurrency(iso
, status
);
630 // next line should NOT recurse, because n is numeric whereas obj was a wrapper around currency amount.
631 return cloneFmt
->format(*n
, appendTo
, posIter
, status
);
634 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
636 format(*n
->getDigitList(), appendTo
, posIter
, status
);
638 switch (n
->getType()) {
639 case Formattable::kDouble
:
640 format(n
->getDouble(), appendTo
, posIter
, status
);
642 case Formattable::kLong
:
643 format(n
->getLong(), appendTo
, posIter
, status
);
645 case Formattable::kInt64
:
646 format(n
->getInt64(), appendTo
, posIter
, status
);
649 status
= U_INVALID_FORMAT_ERROR
;
657 // -------------------------------------
660 NumberFormat::format(int64_t number
,
661 UnicodeString
& appendTo
,
662 FieldPosition
& pos
) const
664 // default so we don't introduce a new abstract method
665 return format((int32_t)number
, appendTo
, pos
);
668 // -------------------------------------
669 // Parses the string and save the result object as well
670 // as the final parsed position.
673 NumberFormat::parseObject(const UnicodeString
& source
,
675 ParsePosition
& parse_pos
) const
677 parse(source
, result
, parse_pos
);
680 // -------------------------------------
681 // Formats a double number and save the result in a string.
684 NumberFormat::format(double number
, UnicodeString
& appendTo
) const
686 FieldPosition
pos(0);
687 return format(number
, appendTo
, pos
);
690 // -------------------------------------
691 // Formats a long number and save the result in a string.
694 NumberFormat::format(int32_t number
, UnicodeString
& appendTo
) const
696 FieldPosition
pos(0);
697 return format(number
, appendTo
, pos
);
700 // -------------------------------------
701 // Formats a long number and save the result in a string.
704 NumberFormat::format(int64_t number
, UnicodeString
& appendTo
) const
706 FieldPosition
pos(0);
707 return format(number
, appendTo
, pos
);
710 // -------------------------------------
711 // Parses the text and save the result object. If the returned
712 // parse position is 0, that means the parsing failed, the status
713 // code needs to be set to failure. Ignores the returned parse
714 // position, otherwise.
717 NumberFormat::parse(const UnicodeString
& text
,
719 UErrorCode
& status
) const
721 if (U_FAILURE(status
)) return;
723 ParsePosition
parsePosition(0);
724 parse(text
, result
, parsePosition
);
725 if (parsePosition
.getIndex() == 0) {
726 status
= U_INVALID_FORMAT_ERROR
;
730 CurrencyAmount
* NumberFormat::parseCurrency(const UnicodeString
& text
,
731 ParsePosition
& pos
) const {
732 // Default implementation only -- subclasses should override
733 Formattable parseResult
;
734 int32_t start
= pos
.getIndex();
735 parse(text
, parseResult
, pos
);
736 if (pos
.getIndex() != start
) {
738 UErrorCode ec
= U_ZERO_ERROR
;
739 getEffectiveCurrency(curr
, ec
);
741 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curr
, ec
));
743 pos
.setIndex(start
); // indicate failure
745 return currAmt
.orphan();
752 // -------------------------------------
753 // Sets to only parse integers.
756 NumberFormat::setParseIntegerOnly(UBool value
)
758 fParseIntegerOnly
= value
;
761 // -------------------------------------
762 // Sets whether lenient parse is enabled.
765 NumberFormat::setLenient(UBool enable
)
770 // -------------------------------------
771 // Create a number style NumberFormat instance with the default locale.
773 NumberFormat
* U_EXPORT2
774 NumberFormat::createInstance(UErrorCode
& status
)
776 return createInstance(Locale::getDefault(), UNUM_DECIMAL
, status
);
779 // -------------------------------------
780 // Create a number style NumberFormat instance with the inLocale locale.
782 NumberFormat
* U_EXPORT2
783 NumberFormat::createInstance(const Locale
& inLocale
, UErrorCode
& status
)
785 return createInstance(inLocale
, UNUM_DECIMAL
, status
);
788 // -------------------------------------
789 // Create a currency style NumberFormat instance with the default locale.
791 NumberFormat
* U_EXPORT2
792 NumberFormat::createCurrencyInstance(UErrorCode
& status
)
794 return createCurrencyInstance(Locale::getDefault(), status
);
797 // -------------------------------------
798 // Create a currency style NumberFormat instance with the inLocale locale.
800 NumberFormat
* U_EXPORT2
801 NumberFormat::createCurrencyInstance(const Locale
& inLocale
, UErrorCode
& status
)
803 return createInstance(inLocale
, UNUM_CURRENCY
, status
);
806 // -------------------------------------
807 // Create a percent style NumberFormat instance with the default locale.
809 NumberFormat
* U_EXPORT2
810 NumberFormat::createPercentInstance(UErrorCode
& status
)
812 return createInstance(Locale::getDefault(), UNUM_PERCENT
, status
);
815 // -------------------------------------
816 // Create a percent style NumberFormat instance with the inLocale locale.
818 NumberFormat
* U_EXPORT2
819 NumberFormat::createPercentInstance(const Locale
& inLocale
, UErrorCode
& status
)
821 return createInstance(inLocale
, UNUM_PERCENT
, status
);
824 // -------------------------------------
825 // Create a scientific style NumberFormat instance with the default locale.
827 NumberFormat
* U_EXPORT2
828 NumberFormat::createScientificInstance(UErrorCode
& status
)
830 return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC
, status
);
833 // -------------------------------------
834 // Create a scientific style NumberFormat instance with the inLocale locale.
836 NumberFormat
* U_EXPORT2
837 NumberFormat::createScientificInstance(const Locale
& inLocale
, UErrorCode
& status
)
839 return createInstance(inLocale
, UNUM_SCIENTIFIC
, status
);
842 // -------------------------------------
844 const Locale
* U_EXPORT2
845 NumberFormat::getAvailableLocales(int32_t& count
)
847 return Locale::getAvailableLocales(count
);
850 // ------------------------------------------
854 //-------------------------------------------
856 #if !UCONFIG_NO_SERVICE
858 // -------------------------------------
860 class ICUNumberFormatFactory
: public ICUResourceBundleFactory
{
862 virtual ~ICUNumberFormatFactory();
864 virtual UObject
* handleCreate(const Locale
& loc
, int32_t kind
, const ICUService
* /* service */, UErrorCode
& status
) const {
865 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
869 ICUNumberFormatFactory::~ICUNumberFormatFactory() {}
871 // -------------------------------------
873 class NFFactory
: public LocaleKeyFactory
{
875 NumberFormatFactory
* _delegate
;
879 NFFactory(NumberFormatFactory
* delegate
)
880 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
881 , _delegate(delegate
)
886 virtual ~NFFactory();
888 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const
890 if (handlesKey(key
, status
)) {
891 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
893 lkey
.canonicalLocale(loc
);
894 int32_t kind
= lkey
.kind();
896 UObject
* result
= _delegate
->createFormat(loc
, (UNumberFormatStyle
)kind
);
897 if (result
== NULL
) {
898 result
= service
->getKey((ICUServiceKey
&)key
/* cast away const */, NULL
, this, status
);
907 * Return the set of ids that this factory supports (visible or
908 * otherwise). This can be called often and might need to be
909 * cached if it is expensive to create.
911 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
913 if (U_SUCCESS(status
)) {
916 const UnicodeString
* const idlist
= _delegate
->getSupportedIDs(count
, status
);
917 ((NFFactory
*)this)->_ids
= new Hashtable(status
); /* cast away const */
919 for (int i
= 0; i
< count
; ++i
) {
920 _ids
->put(idlist
[i
], (void*)this, status
);
930 NFFactory::~NFFactory()
936 class ICUNumberFormatService
: public ICULocaleService
{
938 ICUNumberFormatService()
939 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
941 UErrorCode status
= U_ZERO_ERROR
;
942 registerFactory(new ICUNumberFormatFactory(), status
);
945 virtual ~ICUNumberFormatService();
947 virtual UObject
* cloneInstance(UObject
* instance
) const {
948 return ((NumberFormat
*)instance
)->clone();
951 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* /* actualID */, UErrorCode
& status
) const {
952 LocaleKey
& lkey
= (LocaleKey
&)key
;
953 int32_t kind
= lkey
.kind();
955 lkey
.currentLocale(loc
);
956 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
959 virtual UBool
isDefault() const {
960 return countFactories() == 1;
964 ICUNumberFormatService::~ICUNumberFormatService() {}
966 // -------------------------------------
968 static void U_CALLCONV
initNumberFormatService() {
969 U_ASSERT(gService
== NULL
);
970 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
971 gService
= new ICUNumberFormatService();
974 static ICULocaleService
*
975 getNumberFormatService(void)
977 umtx_initOnce(gServiceInitOnce
, &initNumberFormatService
);
981 static UBool
haveService() {
982 return !gServiceInitOnce
.isReset() && (getNumberFormatService() != NULL
);
985 // -------------------------------------
987 URegistryKey U_EXPORT2
988 NumberFormat::registerFactory(NumberFormatFactory
* toAdopt
, UErrorCode
& status
)
990 ICULocaleService
*service
= getNumberFormatService();
992 NFFactory
*tempnnf
= new NFFactory(toAdopt
);
993 if (tempnnf
!= NULL
) {
994 return service
->registerFactory(tempnnf
, status
);
997 status
= U_MEMORY_ALLOCATION_ERROR
;
1001 // -------------------------------------
1004 NumberFormat::unregister(URegistryKey key
, UErrorCode
& status
)
1006 if (U_FAILURE(status
)) {
1009 if (haveService()) {
1010 return gService
->unregister(key
, status
);
1012 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1017 // -------------------------------------
1018 StringEnumeration
* U_EXPORT2
1019 NumberFormat::getAvailableLocales(void)
1021 ICULocaleService
*service
= getNumberFormatService();
1023 return service
->getAvailableLocales();
1025 return NULL
; // no way to return error condition
1027 #endif /* UCONFIG_NO_SERVICE */
1028 // -------------------------------------
1031 NumberFormat::internalCreateInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1032 #if !UCONFIG_NO_SERVICE
1033 if (haveService()) {
1034 return (NumberFormat
*)gService
->get(loc
, kind
, status
);
1037 return makeInstance(loc
, kind
, status
);
1040 NumberFormat
* U_EXPORT2
1041 NumberFormat::createInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
) {
1042 if (kind
!= UNUM_DECIMAL
) {
1043 return internalCreateInstance(loc
, kind
, status
);
1045 const SharedNumberFormat
*shared
= createSharedInstance(loc
, kind
, status
);
1046 if (U_FAILURE(status
)) {
1049 NumberFormat
*result
= static_cast<NumberFormat
*>((*shared
)->clone());
1050 shared
->removeRef();
1051 if (result
== NULL
) {
1052 status
= U_MEMORY_ALLOCATION_ERROR
;
1058 // -------------------------------------
1059 // Checks if the thousand/10 thousand grouping is used in the
1060 // NumberFormat instance.
1063 NumberFormat::isGroupingUsed() const
1065 return fGroupingUsed
;
1068 // -------------------------------------
1069 // Sets to use the thousand/10 thousand grouping in the
1070 // NumberFormat instance.
1073 NumberFormat::setGroupingUsed(UBool newValue
)
1075 fGroupingUsed
= newValue
;
1078 // -------------------------------------
1079 // Gets the maximum number of digits for the integral part for
1080 // this NumberFormat instance.
1082 int32_t NumberFormat::getMaximumIntegerDigits() const
1084 return fMaxIntegerDigits
;
1087 // -------------------------------------
1088 // Sets the maximum number of digits for the integral part for
1089 // this NumberFormat instance.
1092 NumberFormat::setMaximumIntegerDigits(int32_t newValue
)
1094 fMaxIntegerDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMaxIntegerDigits
));
1095 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1096 fMinIntegerDigits
= fMaxIntegerDigits
;
1099 // -------------------------------------
1100 // Gets the minimum number of digits for the integral part for
1101 // this NumberFormat instance.
1104 NumberFormat::getMinimumIntegerDigits() const
1106 return fMinIntegerDigits
;
1109 // -------------------------------------
1110 // Sets the minimum number of digits for the integral part for
1111 // this NumberFormat instance.
1114 NumberFormat::setMinimumIntegerDigits(int32_t newValue
)
1116 fMinIntegerDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMinIntegerDigits
));
1117 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1118 fMaxIntegerDigits
= fMinIntegerDigits
;
1121 // -------------------------------------
1122 // Gets the maximum number of digits for the fractional part for
1123 // this NumberFormat instance.
1126 NumberFormat::getMaximumFractionDigits() const
1128 return fMaxFractionDigits
;
1131 // -------------------------------------
1132 // Sets the maximum number of digits for the fractional part for
1133 // this NumberFormat instance.
1136 NumberFormat::setMaximumFractionDigits(int32_t newValue
)
1138 fMaxFractionDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMaxIntegerDigits
));
1139 if(fMaxFractionDigits
< fMinFractionDigits
)
1140 fMinFractionDigits
= fMaxFractionDigits
;
1143 // -------------------------------------
1144 // Gets the minimum number of digits for the fractional part for
1145 // this NumberFormat instance.
1148 NumberFormat::getMinimumFractionDigits() const
1150 return fMinFractionDigits
;
1153 // -------------------------------------
1154 // Sets the minimum number of digits for the fractional part for
1155 // this NumberFormat instance.
1158 NumberFormat::setMinimumFractionDigits(int32_t newValue
)
1160 fMinFractionDigits
= uprv_max(0, uprv_min(newValue
, gDefaultMinIntegerDigits
));
1161 if (fMaxFractionDigits
< fMinFractionDigits
)
1162 fMaxFractionDigits
= fMinFractionDigits
;
1165 // -------------------------------------
1167 void NumberFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
1168 if (U_FAILURE(ec
)) {
1172 u_strncpy(fCurrency
, theCurrency
, 3);
1179 const UChar
* NumberFormat::getCurrency() const {
1183 void NumberFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
1184 const UChar
* c
= getCurrency();
1186 u_strncpy(result
, c
, 3);
1189 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
1191 loc
= uloc_getDefault();
1193 ucurr_forLocale(loc
, result
, 4, &ec
);
1197 //----------------------------------------------------------------------
1200 void NumberFormat::setContext(UDisplayContext value
, UErrorCode
& status
)
1202 if (U_FAILURE(status
))
1204 if ( (UDisplayContextType
)((uint32_t)value
>> 8) == UDISPCTX_TYPE_CAPITALIZATION
) {
1205 fCapitalizationContext
= value
;
1207 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1212 UDisplayContext
NumberFormat::getContext(UDisplayContextType type
, UErrorCode
& status
) const
1214 if (U_FAILURE(status
))
1215 return (UDisplayContext
)0;
1216 if (type
!= UDISPCTX_TYPE_CAPITALIZATION
) {
1217 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1218 return (UDisplayContext
)0;
1220 return fCapitalizationContext
;
1224 // -------------------------------------
1225 // Creates the NumberFormat instance of the specified style (number, currency,
1226 // or percent) for the desired locale.
1228 static void U_CALLCONV
nscacheInit() {
1229 U_ASSERT(NumberingSystem_cache
== NULL
);
1230 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
1231 UErrorCode status
= U_ZERO_ERROR
;
1232 NumberingSystem_cache
= uhash_open(uhash_hashLong
,
1236 if (U_FAILURE(status
)) {
1237 // Number Format code will run with no cache if creation fails.
1238 NumberingSystem_cache
= NULL
;
1241 uhash_setValueDeleter(NumberingSystem_cache
, deleteNumberingSystem
);
1244 static SharedObject
*U_CALLCONV
createSharedNumberFormat(
1245 const char *localeId
, UErrorCode
&status
) {
1246 if (U_FAILURE(status
)) {
1249 NumberFormat
*nf
= NumberFormat::internalCreateInstance(
1250 localeId
, UNUM_DECIMAL
, status
);
1251 if (U_FAILURE(status
)) {
1254 SharedObject
*result
= new SharedNumberFormat(nf
);
1255 if (result
== NULL
) {
1256 status
= U_MEMORY_ALLOCATION_ERROR
;
1263 static void U_CALLCONV
numberFormatCacheInit(UErrorCode
&status
) {
1264 U_ASSERT(gNumberFormatCache
== NULL
);
1265 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
1266 gNumberFormatCache
= new SimpleLRUCache(100, &createSharedNumberFormat
, status
);
1267 if (U_FAILURE(status
)) {
1268 delete gNumberFormatCache
;
1269 gNumberFormatCache
= NULL
;
1273 static void getSharedNumberFormatFromCache(
1275 const SharedNumberFormat
*&ptr
,
1276 UErrorCode
&status
) {
1277 umtx_initOnce(gNumberFormatCacheInitOnce
, &numberFormatCacheInit
, status
);
1278 if (U_FAILURE(status
)) {
1281 Mutex
lock(&gNumberFormatCacheMutex
);
1282 gNumberFormatCache
->get(locale
, ptr
, status
);
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 getSharedNumberFormatFromCache(loc
.getName(), 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) {
1341 Win32NumberFormat
*f
= NULL
;
1350 case UNUM_CURRENCY_ISO
: // do not support plural formatting here
1351 case UNUM_CURRENCY_PLURAL
:
1352 case UNUM_CURRENCY_ACCOUNTING
:
1353 f
= new Win32NumberFormat(desiredLocale
, curr
, status
);
1355 if (U_SUCCESS(status
)) {
1367 // Use numbering system cache hashtable
1368 umtx_initOnce(gNSCacheInitOnce
, &nscacheInit
);
1370 // Get cached numbering system
1371 LocalPointer
<NumberingSystem
> ownedNs
;
1372 NumberingSystem
*ns
= NULL
;
1373 if (NumberingSystem_cache
!= NULL
) {
1374 // TODO: Bad hash key usage, see ticket #8504.
1375 int32_t hashKey
= desiredLocale
.hashCode();
1377 Mutex
lock(&nscacheMutex
);
1378 ns
= (NumberingSystem
*)uhash_iget(NumberingSystem_cache
, hashKey
);
1380 ns
= NumberingSystem::createInstance(desiredLocale
,status
);
1381 uhash_iput(NumberingSystem_cache
, hashKey
, (void*)ns
, &status
);
1384 ownedNs
.adoptInstead(NumberingSystem::createInstance(desiredLocale
,status
));
1385 ns
= ownedNs
.getAlias();
1388 // check results of getting a numbering system
1389 if (U_FAILURE(status
)) {
1393 if (mustBeDecimalFormat
&& ns
->isAlgorithmic()) {
1394 status
= U_UNSUPPORTED_ERROR
;
1398 LocalPointer
<DecimalFormatSymbols
> symbolsToAdopt
;
1399 UnicodeString pattern
;
1400 LocalUResourceBundlePointer
ownedResource(ures_open(NULL
, desiredLocale
.getName(), &status
));
1401 if (U_FAILURE(status
)) {
1402 // We don't appear to have resource data available -- use the last-resort data
1403 status
= U_USING_FALLBACK_WARNING
;
1404 // When the data is unavailable, and locale isn't passed in, last resort data is used.
1405 symbolsToAdopt
.adoptInstead(new DecimalFormatSymbols(status
));
1406 if (symbolsToAdopt
.isNull()) {
1407 status
= U_MEMORY_ALLOCATION_ERROR
;
1411 // Creates a DecimalFormat instance with the last resort number patterns.
1412 pattern
.setTo(TRUE
, gLastResortNumberPatterns
[style
], -1);
1415 // Loads the decimal symbols of the desired locale.
1416 symbolsToAdopt
.adoptInstead(new DecimalFormatSymbols(desiredLocale
, status
));
1417 if (symbolsToAdopt
.isNull()) {
1418 status
= U_MEMORY_ALLOCATION_ERROR
;
1422 UResourceBundle
*resource
= ownedResource
.orphan();
1423 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, gNumberElements
, NULL
, &status
);
1424 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &status
);
1425 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1426 ownedResource
.adoptInstead(resource
);
1429 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[style
], &patLen
, &status
);
1431 // Didn't find a pattern specific to the numbering system, so fall back to "latn"
1432 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(gLatn
,ns
->getName())) {
1433 status
= U_ZERO_ERROR
;
1434 resource
= ures_getByKeyWithFallback(numElements
, gLatn
, resource
, &status
);
1435 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1436 patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[style
], &patLen
, &status
);
1439 ures_close(numElements
);
1441 // Creates the specified decimal format style of the desired locale.
1442 pattern
.setTo(TRUE
, patResStr
, patLen
);
1444 if (U_FAILURE(status
)) {
1447 if(style
==UNUM_CURRENCY
|| style
== UNUM_CURRENCY_ISO
|| style
== UNUM_CURRENCY_ACCOUNTING
){
1448 const UChar
* currPattern
= symbolsToAdopt
->getCurrencyPattern();
1449 if(currPattern
!=NULL
){
1450 pattern
.setTo(currPattern
, u_strlen(currPattern
));
1456 if (ns
->isAlgorithmic()) {
1457 UnicodeString nsDesc
;
1458 UnicodeString nsRuleSetGroup
;
1459 UnicodeString nsRuleSetName
;
1461 URBNFRuleSetTag desiredRulesType
= URBNF_NUMBERING_SYSTEM
;
1463 nsDesc
.setTo(ns
->getDescription());
1464 int32_t firstSlash
= nsDesc
.indexOf(gSlash
);
1465 int32_t lastSlash
= nsDesc
.lastIndexOf(gSlash
);
1466 if ( lastSlash
> firstSlash
) {
1469 nsLocID
.appendInvariantChars(nsDesc
.tempSubString(0, firstSlash
), status
);
1470 nsRuleSetGroup
.setTo(nsDesc
,firstSlash
+1,lastSlash
-firstSlash
-1);
1471 nsRuleSetName
.setTo(nsDesc
,lastSlash
+1);
1473 nsLoc
= Locale::createFromName(nsLocID
.data());
1475 UnicodeString SpelloutRules
= UNICODE_STRING_SIMPLE("SpelloutRules");
1476 if ( nsRuleSetGroup
.compare(SpelloutRules
) == 0 ) {
1477 desiredRulesType
= URBNF_SPELLOUT
;
1480 nsLoc
= desiredLocale
;
1481 nsRuleSetName
.setTo(nsDesc
);
1484 RuleBasedNumberFormat
*r
= new RuleBasedNumberFormat(desiredRulesType
,nsLoc
,status
);
1486 status
= U_MEMORY_ALLOCATION_ERROR
;
1489 r
->setDefaultRuleSet(nsRuleSetName
,status
);
1492 // replace single currency sign in the pattern with double currency sign
1493 // if the style is UNUM_CURRENCY_ISO
1494 if (style
== UNUM_CURRENCY_ISO
) {
1495 pattern
.findAndReplace(UnicodeString(TRUE
, gSingleCurrencySign
, 1),
1496 UnicodeString(TRUE
, gDoubleCurrencySign
, 2));
1499 // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails.
1500 DecimalFormatSymbols
*syms
= symbolsToAdopt
.orphan();
1501 f
= new DecimalFormat(pattern
, syms
, style
, status
);
1504 status
= U_MEMORY_ALLOCATION_ERROR
;
1509 f
->setLocaleIDs(ures_getLocaleByType(ownedResource
.getAlias(), ULOC_VALID_LOCALE
, &status
),
1510 ures_getLocaleByType(ownedResource
.getAlias(), ULOC_ACTUAL_LOCALE
, &status
));
1511 if (U_FAILURE(status
)) {
1520 #endif /* #if !UCONFIG_NO_FORMATTING */