2 *******************************************************************************
3 * Copyright (C) 1997-2012, 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"
57 static inline void debugout(UnicodeString s
) {
59 s
.extract((int32_t) 0, s
.length(), buf
);
62 #define debug(x) printf("%s", x);
68 // If no number pattern can be located for a locale, this is the last
70 static const UChar gLastResortDecimalPat
[] = {
71 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
73 static const UChar gLastResortCurrencyPat
[] = {
74 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
76 static const UChar gLastResortPercentPat
[] = {
77 0x23, 0x30, 0x25, 0 /* "#0%" */
79 static const UChar gLastResortScientificPat
[] = {
80 0x23, 0x45, 0x30, 0 /* "#E0" */
82 static const UChar gLastResortIsoCurrencyPat
[] = {
83 0xA4, 0xA4, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0xA4, 0xA4, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "\u00A4\u00A4#0.00;(\u00A4\u00A4#0.00)" */
85 static const UChar gLastResortPluralCurrencyPat
[] = {
86 0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/
89 static const UChar gSingleCurrencySign
[] = {0xA4, 0};
90 static const UChar gDoubleCurrencySign
[] = {0xA4, 0xA4, 0};
92 static const UChar gSlash
= 0x2f;
94 // If the maximum base 10 exponent were 4, then the largest number would
95 // be 99,999 which has 5 digits.
96 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
97 static const int32_t gMaxIntegerDigits
= DBL_MAX_10_EXP
+ DBL_DIG
+ 1;
98 static const int32_t gMinIntegerDigits
= 127;
100 static const UChar
* const gLastResortNumberPatterns
[UNUM_FORMAT_STYLE_COUNT
] = {
101 NULL
, // UNUM_PATTERN_DECIMAL
102 gLastResortDecimalPat
, // UNUM_DECIMAL
103 gLastResortCurrencyPat
, // UNUM_CURRENCY
104 gLastResortPercentPat
, // UNUM_PERCENT
105 gLastResortScientificPat
, // UNUM_SCIENTIFIC
106 NULL
, // UNUM_SPELLOUT
107 NULL
, // UNUM_ORDINAL
108 NULL
, // UNUM_DURATION
109 NULL
, // UNUM_NUMBERING_SYSTEM
110 NULL
, // UNUM_PATTERN_RULEBASED
111 gLastResortIsoCurrencyPat
, // UNUM_CURRENCY_ISO
112 gLastResortPluralCurrencyPat
// UNUM_CURRENCY_PLURAL
115 // Keys used for accessing resource bundles
117 static const char *gNumberElements
= "NumberElements";
118 static const char *gLatn
= "latn";
119 static const char *gPatterns
= "patterns";
120 static const char *gFormatKeys
[UNUM_FORMAT_STYLE_COUNT
] = {
121 NULL
, // UNUM_PATTERN_DECIMAL
122 "decimalFormat", // UNUM_DECIMAL
123 "currencyFormat", // UNUM_CURRENCY
124 "percentFormat", // UNUM_PERCENT
125 "scientificFormat", // UNUM_SCIENTIFIC
126 NULL
, // UNUM_SPELLOUT
127 NULL
, // UNUM_ORDINAL
128 NULL
, // UNUM_DURATION
129 NULL
, // UNUM_NUMBERING_SYSTEM
130 NULL
, // UNUM_PATTERN_RULEBASED
131 // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
132 // the pattern is the same as the pattern of UNUM_CURRENCY
133 // except for replacing the single currency sign with
134 // double currency sign or triple currency sign.
135 "currencyFormat", // UNUM_CURRENCY_ISO
136 "currencyFormat" // UNUM_CURRENCY_PLURAL
139 // Static hashtable cache of NumberingSystem objects used by NumberFormat
140 static UHashtable
* NumberingSystem_cache
= NULL
;
142 static UMutex nscacheMutex
= U_MUTEX_INITIALIZER
;
144 #if !UCONFIG_NO_SERVICE
145 static icu::ICULocaleService
* gService
= NULL
;
149 * Release all static memory held by Number Format.
152 static void U_CALLCONV
153 deleteNumberingSystem(void *obj
) {
154 delete (icu::NumberingSystem
*)obj
;
157 static UBool U_CALLCONV
numfmt_cleanup(void) {
158 #if !UCONFIG_NO_SERVICE
164 if (NumberingSystem_cache
) {
165 // delete NumberingSystem_cache;
166 uhash_close(NumberingSystem_cache
);
167 NumberingSystem_cache
= NULL
;
174 // *****************************************************************************
175 // class NumberFormat
176 // *****************************************************************************
180 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat
)
182 #if !UCONFIG_NO_SERVICE
183 // -------------------------------------
184 // SimpleNumberFormatFactory implementation
185 NumberFormatFactory::~NumberFormatFactory() {}
186 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale
& locale
, UBool visible
)
189 LocaleUtility::initNameFromLocale(locale
, _id
);
192 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
194 UBool
SimpleNumberFormatFactory::visible(void) const {
198 const UnicodeString
*
199 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count
, UErrorCode
& status
) const
201 if (U_SUCCESS(status
)) {
208 #endif /* #if !UCONFIG_NO_SERVICE */
210 // -------------------------------------
211 // default constructor
212 NumberFormat::NumberFormat()
213 : fGroupingUsed(TRUE
),
214 fMaxIntegerDigits(gMaxIntegerDigits
),
215 fMinIntegerDigits(1),
216 fMaxFractionDigits(3), // invariant, >= minFractionDigits
217 fMinFractionDigits(0),
218 fParseIntegerOnly(FALSE
),
224 // -------------------------------------
226 NumberFormat::~NumberFormat()
230 // -------------------------------------
233 NumberFormat::NumberFormat(const NumberFormat
&source
)
239 // -------------------------------------
240 // assignment operator
243 NumberFormat::operator=(const NumberFormat
& rhs
)
247 Format::operator=(rhs
);
248 fGroupingUsed
= rhs
.fGroupingUsed
;
249 fMaxIntegerDigits
= rhs
.fMaxIntegerDigits
;
250 fMinIntegerDigits
= rhs
.fMinIntegerDigits
;
251 fMaxFractionDigits
= rhs
.fMaxFractionDigits
;
252 fMinFractionDigits
= rhs
.fMinFractionDigits
;
253 fParseIntegerOnly
= rhs
.fParseIntegerOnly
;
254 u_strncpy(fCurrency
, rhs
.fCurrency
, 4);
255 fLenient
= rhs
.fLenient
;
260 // -------------------------------------
263 NumberFormat::operator==(const Format
& that
) const
265 // Format::operator== guarantees this cast is safe
266 NumberFormat
* other
= (NumberFormat
*)&that
;
269 // This code makes it easy to determine why two format objects that should
272 if (!Format::operator==(that
)) {
273 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
276 if (!(fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
277 fMinIntegerDigits
== other
->fMinIntegerDigits
)) {
278 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
279 debug("Integer digits !=");
281 if (!(fMaxFractionDigits
== other
->fMaxFractionDigits
&&
282 fMinFractionDigits
== other
->fMinFractionDigits
)) {
283 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
284 debug("Fraction digits !=");
286 if (!(fGroupingUsed
== other
->fGroupingUsed
)) {
287 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
288 debug("fGroupingUsed != ");
290 if (!(fParseIntegerOnly
== other
->fParseIntegerOnly
)) {
291 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
292 debug("fParseIntegerOnly != ");
294 if (!(u_strcmp(fCurrency
, other
->fCurrency
) == 0)) {
295 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
296 debug("fCurrency !=");
298 if (!(fLenient
== other
->fLenient
)) {
299 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
300 debug("fLenient != ");
302 if (!first
) { printf(" ]"); }
305 return ((this == &that
) ||
306 ((Format::operator==(that
) &&
307 fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
308 fMinIntegerDigits
== other
->fMinIntegerDigits
&&
309 fMaxFractionDigits
== other
->fMaxFractionDigits
&&
310 fMinFractionDigits
== other
->fMinFractionDigits
&&
311 fGroupingUsed
== other
->fGroupingUsed
&&
312 fParseIntegerOnly
== other
->fParseIntegerOnly
&&
313 u_strcmp(fCurrency
, other
->fCurrency
) == 0 &&
314 fLenient
== other
->fLenient
)));
317 // -------------------------------------
318 // Default implementation sets unsupported error; subclasses should
322 NumberFormat::format(double /* unused number */,
323 UnicodeString
& toAppendTo
,
324 FieldPositionIterator
* /* unused posIter */,
325 UErrorCode
& status
) const
327 if (!U_FAILURE(status
)) {
328 status
= U_UNSUPPORTED_ERROR
;
333 // -------------------------------------
334 // Default implementation sets unsupported error; subclasses should
338 NumberFormat::format(int32_t /* unused number */,
339 UnicodeString
& toAppendTo
,
340 FieldPositionIterator
* /* unused posIter */,
341 UErrorCode
& status
) const
343 if (!U_FAILURE(status
)) {
344 status
= U_UNSUPPORTED_ERROR
;
349 // -------------------------------------
350 // Default implementation sets unsupported error; subclasses should
354 NumberFormat::format(int64_t /* 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 // These functions add the status code, just fall back to the non-status versions
368 NumberFormat::format(double number
,
369 UnicodeString
& appendTo
,
371 UErrorCode
&status
) const {
372 if(U_SUCCESS(status
)) {
373 return format(number
,appendTo
,pos
);
380 NumberFormat::format(int32_t number
,
381 UnicodeString
& appendTo
,
383 UErrorCode
&status
) const {
384 if(U_SUCCESS(status
)) {
385 return format(number
,appendTo
,pos
);
392 NumberFormat::format(int64_t number
,
393 UnicodeString
& appendTo
,
395 UErrorCode
&status
) const {
396 if(U_SUCCESS(status
)) {
397 return format(number
,appendTo
,pos
);
405 // -------------------------------------
406 // Decimal Number format() default implementation
407 // Subclasses do not normally override this function, but rather the DigitList
408 // formatting functions..
409 // The expected call chain from here is
411 // NumberFormat::format(Formattable ->
412 // DecimalFormat::format(DigitList
414 // Or, for subclasses of Formattable that do not know about DigitList,
416 // NumberFormat::format(Formattable ->
417 // NumberFormat::format(DigitList ->
418 // XXXFormat::format(double
421 NumberFormat::format(const StringPiece
&decimalNum
,
422 UnicodeString
& toAppendTo
,
423 FieldPositionIterator
* fpi
,
424 UErrorCode
& status
) const
427 f
.setDecimalNumber(decimalNum
, status
);
428 format(f
, toAppendTo
, fpi
, status
);
432 // -------------------------------------
433 // Formats the number object and save the format
434 // result in the toAppendTo string buffer.
436 // utility to save/restore state, used in two overloads
437 // of format(const Formattable&...) below.
441 const Formattable
* num
;
446 ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
);
449 const Formattable
* number(void) const;
452 inline const Formattable
*
453 ArgExtractor::number(void) const {
457 ArgExtractor::ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
)
458 : ncnf((NumberFormat
*) &nf
), num(&obj
), setCurr(FALSE
) {
460 const UObject
* o
= obj
.getObject(); // most commonly o==NULL
461 const CurrencyAmount
* amt
;
462 if (o
!= NULL
&& (amt
= dynamic_cast<const CurrencyAmount
*>(o
)) != NULL
) {
463 // getISOCurrency() returns a pointer to internal storage, so we
464 // copy it to retain it across the call to setCurrency().
465 const UChar
* curr
= amt
->getISOCurrency();
466 u_strcpy(save
, nf
.getCurrency());
467 setCurr
= (u_strcmp(curr
, save
) != 0);
469 ncnf
->setCurrency(curr
, status
);
471 num
= &amt
->getNumber();
475 ArgExtractor::~ArgExtractor() {
477 UErrorCode ok
= U_ZERO_ERROR
;
478 ncnf
->setCurrency(save
, ok
); // always restore currency
482 UnicodeString
& NumberFormat::format(const DigitList
&number
,
483 UnicodeString
& appendTo
,
484 FieldPositionIterator
* posIter
,
485 UErrorCode
& status
) const {
486 // DecimalFormat overrides this function, and handles DigitList based big decimals.
487 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
488 // so this default implementation falls back to formatting decimal numbers as doubles.
489 if (U_FAILURE(status
)) {
492 double dnum
= number
.getDouble();
493 format(dnum
, appendTo
, posIter
, status
);
500 NumberFormat::format(const DigitList
&number
,
501 UnicodeString
& appendTo
,
503 UErrorCode
&status
) const {
504 // DecimalFormat overrides this function, and handles DigitList based big decimals.
505 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
506 // so this default implementation falls back to formatting decimal numbers as doubles.
507 if (U_FAILURE(status
)) {
510 double dnum
= number
.getDouble();
511 format(dnum
, appendTo
, pos
, status
);
516 NumberFormat::format(const Formattable
& obj
,
517 UnicodeString
& appendTo
,
519 UErrorCode
& status
) const
521 if (U_FAILURE(status
)) return appendTo
;
523 ArgExtractor
arg(*this, obj
, status
);
524 const Formattable
*n
= arg
.number();
526 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
527 // Decimal Number. We will have a DigitList available if the value was
528 // set to a decimal number, or if the value originated with a parse.
530 // The default implementation for formatting a DigitList converts it
531 // to a double, and formats that, allowing formatting classes that don't
532 // know about DigitList to continue to operate as they had.
534 // DecimalFormat overrides the DigitList formatting functions.
535 format(*n
->getDigitList(), appendTo
, pos
, status
);
537 switch (n
->getType()) {
538 case Formattable::kDouble
:
539 format(n
->getDouble(), appendTo
, pos
);
541 case Formattable::kLong
:
542 format(n
->getLong(), appendTo
, pos
);
544 case Formattable::kInt64
:
545 format(n
->getInt64(), appendTo
, pos
);
548 status
= U_INVALID_FORMAT_ERROR
;
556 // -------------------------------------x
557 // Formats the number object and save the format
558 // result in the toAppendTo string buffer.
561 NumberFormat::format(const Formattable
& obj
,
562 UnicodeString
& appendTo
,
563 FieldPositionIterator
* posIter
,
564 UErrorCode
& status
) const
566 if (U_FAILURE(status
)) return appendTo
;
568 ArgExtractor
arg(*this, obj
, status
);
569 const Formattable
*n
= arg
.number();
571 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
573 format(*n
->getDigitList(), appendTo
, posIter
, status
);
575 switch (n
->getType()) {
576 case Formattable::kDouble
:
577 format(n
->getDouble(), appendTo
, posIter
, status
);
579 case Formattable::kLong
:
580 format(n
->getLong(), appendTo
, posIter
, status
);
582 case Formattable::kInt64
:
583 format(n
->getInt64(), appendTo
, posIter
, status
);
586 status
= U_INVALID_FORMAT_ERROR
;
594 // -------------------------------------
597 NumberFormat::format(int64_t number
,
598 UnicodeString
& appendTo
,
599 FieldPosition
& pos
) const
601 // default so we don't introduce a new abstract method
602 return format((int32_t)number
, appendTo
, pos
);
605 // -------------------------------------
606 // Parses the string and save the result object as well
607 // as the final parsed position.
610 NumberFormat::parseObject(const UnicodeString
& source
,
612 ParsePosition
& parse_pos
) const
614 parse(source
, result
, parse_pos
);
617 // -------------------------------------
618 // Formats a double number and save the result in a string.
621 NumberFormat::format(double number
, UnicodeString
& appendTo
) const
623 FieldPosition
pos(0);
624 return format(number
, appendTo
, pos
);
627 // -------------------------------------
628 // Formats a long number and save the result in a string.
631 NumberFormat::format(int32_t number
, UnicodeString
& appendTo
) const
633 FieldPosition
pos(0);
634 return format(number
, appendTo
, pos
);
637 // -------------------------------------
638 // Formats a long number and save the result in a string.
641 NumberFormat::format(int64_t number
, UnicodeString
& appendTo
) const
643 FieldPosition
pos(0);
644 return format(number
, appendTo
, pos
);
647 // -------------------------------------
648 // Parses the text and save the result object. If the returned
649 // parse position is 0, that means the parsing failed, the status
650 // code needs to be set to failure. Ignores the returned parse
651 // position, otherwise.
654 NumberFormat::parse(const UnicodeString
& text
,
656 UErrorCode
& status
) const
658 if (U_FAILURE(status
)) return;
660 ParsePosition
parsePosition(0);
661 parse(text
, result
, parsePosition
);
662 if (parsePosition
.getIndex() == 0) {
663 status
= U_INVALID_FORMAT_ERROR
;
667 CurrencyAmount
* NumberFormat::parseCurrency(const UnicodeString
& text
,
668 ParsePosition
& pos
) const {
669 // Default implementation only -- subclasses should override
670 Formattable parseResult
;
671 int32_t start
= pos
.getIndex();
672 parse(text
, parseResult
, pos
);
673 if (pos
.getIndex() != start
) {
675 UErrorCode ec
= U_ZERO_ERROR
;
676 getEffectiveCurrency(curr
, ec
);
678 LocalPointer
<CurrencyAmount
> currAmt(new CurrencyAmount(parseResult
, curr
, ec
));
680 pos
.setIndex(start
); // indicate failure
682 return currAmt
.orphan();
689 // -------------------------------------
690 // Sets to only parse integers.
693 NumberFormat::setParseIntegerOnly(UBool value
)
695 fParseIntegerOnly
= value
;
698 // -------------------------------------
699 // Sets whether lenient parse is enabled.
702 NumberFormat::setLenient(UBool enable
)
707 // -------------------------------------
708 // Create a number style NumberFormat instance with the default locale.
710 NumberFormat
* U_EXPORT2
711 NumberFormat::createInstance(UErrorCode
& status
)
713 return createInstance(Locale::getDefault(), UNUM_DECIMAL
, status
);
716 // -------------------------------------
717 // Create a number style NumberFormat instance with the inLocale locale.
719 NumberFormat
* U_EXPORT2
720 NumberFormat::createInstance(const Locale
& inLocale
, UErrorCode
& status
)
722 return createInstance(inLocale
, UNUM_DECIMAL
, status
);
725 // -------------------------------------
726 // Create a currency style NumberFormat instance with the default locale.
728 NumberFormat
* U_EXPORT2
729 NumberFormat::createCurrencyInstance(UErrorCode
& status
)
731 return createCurrencyInstance(Locale::getDefault(), status
);
734 // -------------------------------------
735 // Create a currency style NumberFormat instance with the inLocale locale.
737 NumberFormat
* U_EXPORT2
738 NumberFormat::createCurrencyInstance(const Locale
& inLocale
, UErrorCode
& status
)
740 return createInstance(inLocale
, UNUM_CURRENCY
, status
);
743 // -------------------------------------
744 // Create a percent style NumberFormat instance with the default locale.
746 NumberFormat
* U_EXPORT2
747 NumberFormat::createPercentInstance(UErrorCode
& status
)
749 return createInstance(Locale::getDefault(), UNUM_PERCENT
, status
);
752 // -------------------------------------
753 // Create a percent style NumberFormat instance with the inLocale locale.
755 NumberFormat
* U_EXPORT2
756 NumberFormat::createPercentInstance(const Locale
& inLocale
, UErrorCode
& status
)
758 return createInstance(inLocale
, UNUM_PERCENT
, status
);
761 // -------------------------------------
762 // Create a scientific style NumberFormat instance with the default locale.
764 NumberFormat
* U_EXPORT2
765 NumberFormat::createScientificInstance(UErrorCode
& status
)
767 return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC
, status
);
770 // -------------------------------------
771 // Create a scientific style NumberFormat instance with the inLocale locale.
773 NumberFormat
* U_EXPORT2
774 NumberFormat::createScientificInstance(const Locale
& inLocale
, UErrorCode
& status
)
776 return createInstance(inLocale
, UNUM_SCIENTIFIC
, status
);
779 // -------------------------------------
781 const Locale
* U_EXPORT2
782 NumberFormat::getAvailableLocales(int32_t& count
)
784 return Locale::getAvailableLocales(count
);
787 // ------------------------------------------
791 //-------------------------------------------
793 #if !UCONFIG_NO_SERVICE
795 // -------------------------------------
797 class ICUNumberFormatFactory
: public ICUResourceBundleFactory
{
799 virtual ~ICUNumberFormatFactory();
801 virtual UObject
* handleCreate(const Locale
& loc
, int32_t kind
, const ICUService
* /* service */, UErrorCode
& status
) const {
802 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
806 ICUNumberFormatFactory::~ICUNumberFormatFactory() {}
808 // -------------------------------------
810 class NFFactory
: public LocaleKeyFactory
{
812 NumberFormatFactory
* _delegate
;
816 NFFactory(NumberFormatFactory
* delegate
)
817 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
818 , _delegate(delegate
)
823 virtual ~NFFactory();
825 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const
827 if (handlesKey(key
, status
)) {
828 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
830 lkey
.canonicalLocale(loc
);
831 int32_t kind
= lkey
.kind();
833 UObject
* result
= _delegate
->createFormat(loc
, (UNumberFormatStyle
)kind
);
834 if (result
== NULL
) {
835 result
= service
->getKey((ICUServiceKey
&)key
/* cast away const */, NULL
, this, status
);
844 * Return the set of ids that this factory supports (visible or
845 * otherwise). This can be called often and might need to be
846 * cached if it is expensive to create.
848 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
850 if (U_SUCCESS(status
)) {
853 const UnicodeString
* const idlist
= _delegate
->getSupportedIDs(count
, status
);
854 ((NFFactory
*)this)->_ids
= new Hashtable(status
); /* cast away const */
856 for (int i
= 0; i
< count
; ++i
) {
857 _ids
->put(idlist
[i
], (void*)this, status
);
867 NFFactory::~NFFactory()
873 class ICUNumberFormatService
: public ICULocaleService
{
875 ICUNumberFormatService()
876 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
878 UErrorCode status
= U_ZERO_ERROR
;
879 registerFactory(new ICUNumberFormatFactory(), status
);
882 virtual ~ICUNumberFormatService();
884 virtual UObject
* cloneInstance(UObject
* instance
) const {
885 return ((NumberFormat
*)instance
)->clone();
888 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* /* actualID */, UErrorCode
& status
) const {
889 LocaleKey
& lkey
= (LocaleKey
&)key
;
890 int32_t kind
= lkey
.kind();
892 lkey
.currentLocale(loc
);
893 return NumberFormat::makeInstance(loc
, (UNumberFormatStyle
)kind
, status
);
896 virtual UBool
isDefault() const {
897 return countFactories() == 1;
901 ICUNumberFormatService::~ICUNumberFormatService() {}
903 // -------------------------------------
905 static ICULocaleService
*
906 getNumberFormatService(void)
909 UMTX_CHECK(NULL
, (UBool
)(gService
== NULL
), needInit
);
911 ICULocaleService
* newservice
= new ICUNumberFormatService();
914 if (gService
== NULL
) {
915 gService
= newservice
;
923 // we won the contention, this thread can register cleanup.
924 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
930 // -------------------------------------
932 URegistryKey U_EXPORT2
933 NumberFormat::registerFactory(NumberFormatFactory
* toAdopt
, UErrorCode
& status
)
935 ICULocaleService
*service
= getNumberFormatService();
937 NFFactory
*tempnnf
= new NFFactory(toAdopt
);
938 if (tempnnf
!= NULL
) {
939 return service
->registerFactory(tempnnf
, status
);
942 status
= U_MEMORY_ALLOCATION_ERROR
;
946 // -------------------------------------
949 NumberFormat::unregister(URegistryKey key
, UErrorCode
& status
)
951 if (U_SUCCESS(status
)) {
953 UMTX_CHECK(NULL
, gService
!= NULL
, haveService
);
955 return gService
->unregister(key
, status
);
957 status
= U_ILLEGAL_ARGUMENT_ERROR
;
962 // -------------------------------------
963 StringEnumeration
* U_EXPORT2
964 NumberFormat::getAvailableLocales(void)
966 ICULocaleService
*service
= getNumberFormatService();
968 return service
->getAvailableLocales();
970 return NULL
; // no way to return error condition
972 #endif /* UCONFIG_NO_SERVICE */
973 // -------------------------------------
975 NumberFormat
* U_EXPORT2
976 NumberFormat::createInstance(const Locale
& loc
, UNumberFormatStyle kind
, UErrorCode
& status
)
978 #if !UCONFIG_NO_SERVICE
980 UMTX_CHECK(NULL
, gService
!= NULL
, haveService
);
982 return (NumberFormat
*)gService
->get(loc
, kind
, status
);
987 return makeInstance(loc
, kind
, status
);
992 // -------------------------------------
993 // Checks if the thousand/10 thousand grouping is used in the
994 // NumberFormat instance.
997 NumberFormat::isGroupingUsed() const
999 return fGroupingUsed
;
1002 // -------------------------------------
1003 // Sets to use the thousand/10 thousand grouping in the
1004 // NumberFormat instance.
1007 NumberFormat::setGroupingUsed(UBool newValue
)
1009 fGroupingUsed
= newValue
;
1012 // -------------------------------------
1013 // Gets the maximum number of digits for the integral part for
1014 // this NumberFormat instance.
1016 int32_t NumberFormat::getMaximumIntegerDigits() const
1018 return fMaxIntegerDigits
;
1021 // -------------------------------------
1022 // Sets the maximum number of digits for the integral part for
1023 // this NumberFormat instance.
1026 NumberFormat::setMaximumIntegerDigits(int32_t newValue
)
1028 fMaxIntegerDigits
= uprv_max(0, uprv_min(newValue
, gMaxIntegerDigits
));
1029 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1030 fMinIntegerDigits
= fMaxIntegerDigits
;
1033 // -------------------------------------
1034 // Gets the minimum number of digits for the integral part for
1035 // this NumberFormat instance.
1038 NumberFormat::getMinimumIntegerDigits() const
1040 return fMinIntegerDigits
;
1043 // -------------------------------------
1044 // Sets the minimum number of digits for the integral part for
1045 // this NumberFormat instance.
1048 NumberFormat::setMinimumIntegerDigits(int32_t newValue
)
1050 fMinIntegerDigits
= uprv_max(0, uprv_min(newValue
, gMinIntegerDigits
));
1051 if(fMinIntegerDigits
> fMaxIntegerDigits
)
1052 fMaxIntegerDigits
= fMinIntegerDigits
;
1055 // -------------------------------------
1056 // Gets the maximum number of digits for the fractional part for
1057 // this NumberFormat instance.
1060 NumberFormat::getMaximumFractionDigits() const
1062 return fMaxFractionDigits
;
1065 // -------------------------------------
1066 // Sets the maximum number of digits for the fractional part for
1067 // this NumberFormat instance.
1070 NumberFormat::setMaximumFractionDigits(int32_t newValue
)
1072 fMaxFractionDigits
= uprv_max(0, uprv_min(newValue
, gMaxIntegerDigits
));
1073 if(fMaxFractionDigits
< fMinFractionDigits
)
1074 fMinFractionDigits
= fMaxFractionDigits
;
1077 // -------------------------------------
1078 // Gets the minimum number of digits for the fractional part for
1079 // this NumberFormat instance.
1082 NumberFormat::getMinimumFractionDigits() const
1084 return fMinFractionDigits
;
1087 // -------------------------------------
1088 // Sets the minimum number of digits for the fractional part for
1089 // this NumberFormat instance.
1092 NumberFormat::setMinimumFractionDigits(int32_t newValue
)
1094 fMinFractionDigits
= uprv_max(0, uprv_min(newValue
, gMinIntegerDigits
));
1095 if (fMaxFractionDigits
< fMinFractionDigits
)
1096 fMaxFractionDigits
= fMinFractionDigits
;
1099 // -------------------------------------
1101 void NumberFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
1102 if (U_FAILURE(ec
)) {
1106 u_strncpy(fCurrency
, theCurrency
, 3);
1113 const UChar
* NumberFormat::getCurrency() const {
1117 void NumberFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
1118 const UChar
* c
= getCurrency();
1120 u_strncpy(result
, c
, 3);
1123 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
1125 loc
= uloc_getDefault();
1127 ucurr_forLocale(loc
, result
, 4, &ec
);
1131 // -------------------------------------
1132 // Creates the NumberFormat instance of the specified style (number, currency,
1133 // or percent) for the desired locale.
1136 NumberFormat::isStyleSupported(UNumberFormatStyle style
) {
1137 return gLastResortNumberPatterns
[style
] != NULL
;
1141 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1142 UNumberFormatStyle style
,
1143 UErrorCode
& status
) {
1144 return makeInstance(desiredLocale
, style
, false, status
);
1148 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1149 UNumberFormatStyle style
,
1150 UBool mustBeDecimalFormat
,
1151 UErrorCode
& status
) {
1152 if (U_FAILURE(status
)) return NULL
;
1154 if (style
< 0 || style
>= UNUM_FORMAT_STYLE_COUNT
) {
1155 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1159 // Some styles are not supported. This is a result of merging
1160 // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
1161 // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
1162 // this one and unum_open().
1163 // The UNUM_PATTERN_ styles are not supported here
1164 // because this method does not take a pattern string.
1165 if (!isStyleSupported(style
)) {
1166 status
= U_UNSUPPORTED_ERROR
;
1170 #if U_PLATFORM_USES_ONLY_WIN32_API
1171 if (!mustBeDecimalFormat
) {
1173 int32_t count
= desiredLocale
.getKeywordValue("compat", buffer
, sizeof(buffer
), status
);
1175 // if the locale has "@compat=host", create a host-specific NumberFormat
1176 if (U_SUCCESS(status
) && count
> 0 && uprv_strcmp(buffer
, "host") == 0) {
1177 Win32NumberFormat
*f
= NULL
;
1186 case UNUM_CURRENCY_ISO
: // do not support plural formatting here
1187 case UNUM_CURRENCY_PLURAL
:
1188 f
= new Win32NumberFormat(desiredLocale
, curr
, status
);
1190 if (U_SUCCESS(status
)) {
1202 // Use numbering system cache hashtable
1204 UMTX_CHECK(&nscacheMutex
, NumberingSystem_cache
, cache
);
1206 // Check cache we got, create if non-existant
1207 if (cache
== NULL
) {
1208 cache
= uhash_open(uhash_hashLong
,
1213 if (U_FAILURE(status
)) {
1214 // cache not created - out of memory
1215 status
= U_ZERO_ERROR
; // work without the cache
1219 uhash_setValueDeleter(cache
, deleteNumberingSystem
);
1221 // set final NumberingSystem_cache value
1222 Mutex
lock(&nscacheMutex
);
1223 if (NumberingSystem_cache
== NULL
) {
1224 NumberingSystem_cache
= cache
;
1225 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
1228 cache
= NumberingSystem_cache
;
1233 // Get cached numbering system
1234 LocalPointer
<NumberingSystem
> ownedNs
;
1235 NumberingSystem
*ns
= NULL
;
1236 if (cache
!= NULL
) {
1237 // TODO: Bad hash key usage, see ticket #8504.
1238 int32_t hashKey
= desiredLocale
.hashCode();
1240 Mutex
lock(&nscacheMutex
);
1241 ns
= (NumberingSystem
*)uhash_iget(cache
, hashKey
);
1243 ns
= NumberingSystem::createInstance(desiredLocale
,status
);
1244 uhash_iput(cache
, hashKey
, (void*)ns
, &status
);
1247 ownedNs
.adoptInstead(NumberingSystem::createInstance(desiredLocale
,status
));
1248 ns
= ownedNs
.getAlias();
1251 // check results of getting a numbering system
1252 if (U_FAILURE(status
)) {
1256 if (mustBeDecimalFormat
&& ns
->isAlgorithmic()) {
1257 status
= U_UNSUPPORTED_ERROR
;
1261 LocalPointer
<DecimalFormatSymbols
> symbolsToAdopt
;
1262 UnicodeString pattern
;
1263 LocalUResourceBundlePointer
ownedResource(ures_open(NULL
, desiredLocale
.getName(), &status
));
1264 if (U_FAILURE(status
)) {
1265 // We don't appear to have resource data available -- use the last-resort data
1266 status
= U_USING_FALLBACK_WARNING
;
1267 // When the data is unavailable, and locale isn't passed in, last resort data is used.
1268 symbolsToAdopt
.adoptInstead(new DecimalFormatSymbols(status
));
1269 if (symbolsToAdopt
.isNull()) {
1270 status
= U_MEMORY_ALLOCATION_ERROR
;
1274 // Creates a DecimalFormat instance with the last resort number patterns.
1275 pattern
.setTo(TRUE
, gLastResortNumberPatterns
[style
], -1);
1278 // Loads the decimal symbols of the desired locale.
1279 symbolsToAdopt
.adoptInstead(new DecimalFormatSymbols(desiredLocale
, status
));
1280 if (symbolsToAdopt
.isNull()) {
1281 status
= U_MEMORY_ALLOCATION_ERROR
;
1285 UResourceBundle
*resource
= ownedResource
.orphan();
1286 UResourceBundle
*numElements
= ures_getByKeyWithFallback(resource
, gNumberElements
, NULL
, &status
);
1287 resource
= ures_getByKeyWithFallback(numElements
, ns
->getName(), resource
, &status
);
1288 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1289 ownedResource
.adoptInstead(resource
);
1292 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[style
], &patLen
, &status
);
1294 // Didn't find a pattern specific to the numbering system, so fall back to "latn"
1295 if ( status
== U_MISSING_RESOURCE_ERROR
&& uprv_strcmp(gLatn
,ns
->getName())) {
1296 status
= U_ZERO_ERROR
;
1297 resource
= ures_getByKeyWithFallback(numElements
, gLatn
, resource
, &status
);
1298 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1299 patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[style
], &patLen
, &status
);
1302 ures_close(numElements
);
1304 // Creates the specified decimal format style of the desired locale.
1305 pattern
.setTo(TRUE
, patResStr
, patLen
);
1307 if (U_FAILURE(status
)) {
1310 if(style
==UNUM_CURRENCY
|| style
== UNUM_CURRENCY_ISO
){
1311 const UChar
* currPattern
= symbolsToAdopt
->getCurrencyPattern();
1312 if(currPattern
!=NULL
){
1313 pattern
.setTo(currPattern
, u_strlen(currPattern
));
1319 if (ns
->isAlgorithmic()) {
1320 UnicodeString nsDesc
;
1321 UnicodeString nsRuleSetGroup
;
1322 UnicodeString nsRuleSetName
;
1324 URBNFRuleSetTag desiredRulesType
= URBNF_NUMBERING_SYSTEM
;
1326 nsDesc
.setTo(ns
->getDescription());
1327 int32_t firstSlash
= nsDesc
.indexOf(gSlash
);
1328 int32_t lastSlash
= nsDesc
.lastIndexOf(gSlash
);
1329 if ( lastSlash
> firstSlash
) {
1332 nsLocID
.appendInvariantChars(nsDesc
.tempSubString(0, firstSlash
), status
);
1333 nsRuleSetGroup
.setTo(nsDesc
,firstSlash
+1,lastSlash
-firstSlash
-1);
1334 nsRuleSetName
.setTo(nsDesc
,lastSlash
+1);
1336 nsLoc
= Locale::createFromName(nsLocID
.data());
1338 UnicodeString SpelloutRules
= UNICODE_STRING_SIMPLE("SpelloutRules");
1339 if ( nsRuleSetGroup
.compare(SpelloutRules
) == 0 ) {
1340 desiredRulesType
= URBNF_SPELLOUT
;
1343 nsLoc
= desiredLocale
;
1344 nsRuleSetName
.setTo(nsDesc
);
1347 RuleBasedNumberFormat
*r
= new RuleBasedNumberFormat(desiredRulesType
,nsLoc
,status
);
1349 status
= U_MEMORY_ALLOCATION_ERROR
;
1352 r
->setDefaultRuleSet(nsRuleSetName
,status
);
1355 // replace single currency sign in the pattern with double currency sign
1356 // if the style is UNUM_CURRENCY_ISO
1357 if (style
== UNUM_CURRENCY_ISO
) {
1358 pattern
.findAndReplace(UnicodeString(TRUE
, gSingleCurrencySign
, 1),
1359 UnicodeString(TRUE
, gDoubleCurrencySign
, 2));
1362 // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails.
1363 DecimalFormatSymbols
*syms
= symbolsToAdopt
.orphan();
1364 f
= new DecimalFormat(pattern
, syms
, style
, status
);
1367 status
= U_MEMORY_ALLOCATION_ERROR
;
1372 f
->setLocaleIDs(ures_getLocaleByType(ownedResource
.getAlias(), ULOC_VALID_LOCALE
, &status
),
1373 ures_getLocaleByType(ownedResource
.getAlias(), ULOC_ACTUAL_LOCALE
, &status
));
1374 if (U_FAILURE(status
)) {
1383 #endif /* #if !UCONFIG_NO_FORMATTING */