2 *******************************************************************************
3 * Copyright (C) 1997-2010, 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"
54 static void debugout(UnicodeString s
) {
56 s
.extract((int32_t) 0, s
.length(), buf
);
59 #define debug(x) printf("%s", x);
65 // If no number pattern can be located for a locale, this is the last
67 static const UChar gLastResortDecimalPat
[] = {
68 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
70 static const UChar gLastResortCurrencyPat
[] = {
71 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
73 static const UChar gLastResortPercentPat
[] = {
74 0x23, 0x30, 0x25, 0 /* "#0%" */
76 static const UChar gLastResortScientificPat
[] = {
77 0x23, 0x45, 0x30, 0 /* "#E0" */
79 static const UChar gLastResortIsoCurrencyPat
[] = {
80 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)" */
82 static const UChar gLastResortPluralCurrencyPat
[] = {
83 0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/
86 static const UChar gSingleCurrencySign
[] = {0xA4, 0};
87 static const UChar gDoubleCurrencySign
[] = {0xA4, 0xA4, 0};
89 static const UChar gSlash
= 0x2f;
91 // If the maximum base 10 exponent were 4, then the largest number would
92 // be 99,999 which has 5 digits.
93 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
94 static const int32_t gMaxIntegerDigits
= DBL_MAX_10_EXP
+ DBL_DIG
+ 1;
95 static const int32_t gMinIntegerDigits
= 127;
97 static const UChar
* const gLastResortNumberPatterns
[] =
99 gLastResortDecimalPat
,
100 gLastResortCurrencyPat
,
101 gLastResortPercentPat
,
102 gLastResortScientificPat
,
103 gLastResortIsoCurrencyPat
,
104 gLastResortPluralCurrencyPat
,
107 // Keys used for accessing resource bundles
109 static const char *gNumberElements
= "NumberElements";
110 static const char *gLatn
= "latn";
111 static const char *gPatterns
= "patterns";
112 static const char *gFormatKeys
[] = { "decimalFormat", "currencyFormat", "percentFormat", "scientificFormat" };
114 // Static hashtable cache of NumberingSystem objects used by NumberFormat
115 static UHashtable
* NumberingSystem_cache
= NULL
;
117 static UMTX nscacheMutex
= NULL
;
119 #if !UCONFIG_NO_SERVICE
120 static U_NAMESPACE_QUALIFIER ICULocaleService
* gService
= NULL
;
124 * Release all static memory held by Number Format.
127 static void U_CALLCONV
128 deleteNumberingSystem(void *obj
) {
129 delete (U_NAMESPACE_QUALIFIER NumberingSystem
*)obj
;
132 static UBool U_CALLCONV
numfmt_cleanup(void) {
133 #if !UCONFIG_NO_SERVICE
139 if (NumberingSystem_cache
) {
140 // delete NumberingSystem_cache;
141 uhash_close(NumberingSystem_cache
);
142 NumberingSystem_cache
= NULL
;
149 // *****************************************************************************
150 // class NumberFormat
151 // *****************************************************************************
155 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat
)
157 #if !UCONFIG_NO_SERVICE
158 // -------------------------------------
159 // SimpleNumberFormatFactory implementation
160 NumberFormatFactory::~NumberFormatFactory() {}
161 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale
& locale
, UBool visible
)
164 LocaleUtility::initNameFromLocale(locale
, _id
);
167 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
169 UBool
SimpleNumberFormatFactory::visible(void) const {
173 const UnicodeString
*
174 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count
, UErrorCode
& status
) const
176 if (U_SUCCESS(status
)) {
183 #endif /* #if !UCONFIG_NO_SERVICE */
185 // -------------------------------------
186 // default constructor
187 NumberFormat::NumberFormat()
188 : fGroupingUsed(TRUE
),
189 fMaxIntegerDigits(gMaxIntegerDigits
),
190 fMinIntegerDigits(1),
191 fMaxFractionDigits(3), // invariant, >= minFractionDigits
192 fMinFractionDigits(0),
193 fParseIntegerOnly(FALSE
),
194 fParseStrict(TRUE
) // TODO: Should this be FALSE?
199 // -------------------------------------
201 NumberFormat::~NumberFormat()
205 // -------------------------------------
208 NumberFormat::NumberFormat(const NumberFormat
&source
)
214 // -------------------------------------
215 // assignment operator
218 NumberFormat::operator=(const NumberFormat
& rhs
)
222 Format::operator=(rhs
);
223 fGroupingUsed
= rhs
.fGroupingUsed
;
224 fMaxIntegerDigits
= rhs
.fMaxIntegerDigits
;
225 fMinIntegerDigits
= rhs
.fMinIntegerDigits
;
226 fMaxFractionDigits
= rhs
.fMaxFractionDigits
;
227 fMinFractionDigits
= rhs
.fMinFractionDigits
;
228 fParseIntegerOnly
= rhs
.fParseIntegerOnly
;
229 u_strncpy(fCurrency
, rhs
.fCurrency
, 4);
234 // -------------------------------------
237 NumberFormat::operator==(const Format
& that
) const
239 // Format::operator== guarantees this cast is safe
240 NumberFormat
* other
= (NumberFormat
*)&that
;
243 // This code makes it easy to determine why two format objects that should
246 if (!Format::operator==(that
)) {
247 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
250 if (!(fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
251 fMinIntegerDigits
== other
->fMinIntegerDigits
)) {
252 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
253 debug("Integer digits !=");
255 if (!(fMaxFractionDigits
== other
->fMaxFractionDigits
&&
256 fMinFractionDigits
== other
->fMinFractionDigits
)) {
257 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
258 debug("Fraction digits !=");
260 if (!(fGroupingUsed
== other
->fGroupingUsed
)) {
261 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
262 debug("fGroupingUsed != ");
264 if (!(fParseIntegerOnly
== other
->fParseIntegerOnly
)) {
265 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
266 debug("fParseIntegerOnly != ");
268 if (!(u_strcmp(fCurrency
, other
->fCurrency
) == 0)) {
269 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
270 debug("fCurrency !=");
272 if (!first
) { printf(" ]"); }
275 return ((this == &that
) ||
276 ((Format::operator==(that
) &&
277 fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
278 fMinIntegerDigits
== other
->fMinIntegerDigits
&&
279 fMaxFractionDigits
== other
->fMaxFractionDigits
&&
280 fMinFractionDigits
== other
->fMinFractionDigits
&&
281 fGroupingUsed
== other
->fGroupingUsed
&&
282 fParseIntegerOnly
== other
->fParseIntegerOnly
&&
283 u_strcmp(fCurrency
, other
->fCurrency
) == 0)));
286 // -------------------------------------
287 // Default implementation sets unsupported error; subclasses should
291 NumberFormat::format(double /* unused number */,
292 UnicodeString
& toAppendTo
,
293 FieldPositionIterator
* /* unused posIter */,
294 UErrorCode
& status
) const
296 if (!U_FAILURE(status
)) {
297 status
= U_UNSUPPORTED_ERROR
;
302 // -------------------------------------
303 // Default implementation sets unsupported error; subclasses should
307 NumberFormat::format(int32_t /* unused number */,
308 UnicodeString
& toAppendTo
,
309 FieldPositionIterator
* /* unused posIter */,
310 UErrorCode
& status
) const
312 if (!U_FAILURE(status
)) {
313 status
= U_UNSUPPORTED_ERROR
;
318 // -------------------------------------
319 // Default implementation sets unsupported error; subclasses should
323 NumberFormat::format(int64_t /* unused number */,
324 UnicodeString
& toAppendTo
,
325 FieldPositionIterator
* /* unused posIter */,
326 UErrorCode
& status
) const
328 if (!U_FAILURE(status
)) {
329 status
= U_UNSUPPORTED_ERROR
;
334 // -------------------------------------
335 // Decimal Number format() default implementation
336 // Subclasses do not normally override this function, but rather the DigitList
337 // formatting functions..
338 // The expected call chain from here is
340 // NumberFormat::format(Formattable ->
341 // DecimalFormat::format(DigitList
343 // Or, for subclasses of Formattable that do not know about DigitList,
345 // NumberFormat::format(Formattable ->
346 // NumberFormat::format(DigitList ->
347 // XXXFormat::format(double
350 NumberFormat::format(const StringPiece
&decimalNum
,
351 UnicodeString
& toAppendTo
,
352 FieldPositionIterator
* fpi
,
353 UErrorCode
& status
) const
356 f
.setDecimalNumber(decimalNum
, status
);
357 format(f
, toAppendTo
, fpi
, status
);
361 // -------------------------------------
362 // Formats the number object and save the format
363 // result in the toAppendTo string buffer.
365 // utility to save/restore state, used in two overloads
366 // of format(const Formattable&...) below.
370 const Formattable
* num
;
375 ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
);
378 const Formattable
* number(void) const;
381 inline const Formattable
*
382 ArgExtractor::number(void) const {
386 ArgExtractor::ArgExtractor(const NumberFormat
& nf
, const Formattable
& obj
, UErrorCode
& status
)
387 : ncnf((NumberFormat
*) &nf
), num(&obj
), setCurr(FALSE
) {
389 const UObject
* o
= obj
.getObject(); // most commonly o==NULL
390 const CurrencyAmount
* amt
;
391 if (o
!= NULL
&& (amt
= dynamic_cast<const CurrencyAmount
*>(o
)) != NULL
) {
392 // getISOCurrency() returns a pointer to internal storage, so we
393 // copy it to retain it across the call to setCurrency().
394 const UChar
* curr
= amt
->getISOCurrency();
395 u_strcpy(save
, nf
.getCurrency());
396 setCurr
= (u_strcmp(curr
, save
) != 0);
398 ncnf
->setCurrency(curr
, status
);
400 num
= &amt
->getNumber();
404 ArgExtractor::~ArgExtractor() {
406 UErrorCode ok
= U_ZERO_ERROR
;
407 ncnf
->setCurrency(save
, ok
); // always restore currency
411 UnicodeString
& NumberFormat::format(const DigitList
&number
,
412 UnicodeString
& appendTo
,
413 FieldPositionIterator
* posIter
,
414 UErrorCode
& status
) const {
415 // DecimalFormat overrides this function, and handles DigitList based big decimals.
416 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
417 // so this default implementation falls back to formatting decimal numbers as doubles.
418 if (U_FAILURE(status
)) {
421 double dnum
= number
.getDouble();
422 format(dnum
, appendTo
, posIter
, status
);
429 NumberFormat::format(const DigitList
&number
,
430 UnicodeString
& appendTo
,
432 UErrorCode
&status
) const {
433 // DecimalFormat overrides this function, and handles DigitList based big decimals.
434 // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
435 // so this default implementation falls back to formatting decimal numbers as doubles.
436 if (U_FAILURE(status
)) {
439 double dnum
= number
.getDouble();
440 format(dnum
, appendTo
, pos
, status
);
445 NumberFormat::format(const Formattable
& obj
,
446 UnicodeString
& appendTo
,
448 UErrorCode
& status
) const
450 if (U_FAILURE(status
)) return appendTo
;
452 ArgExtractor
arg(*this, obj
, status
);
453 const Formattable
*n
= arg
.number();
455 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
456 // Decimal Number. We will have a DigitList available if the value was
457 // set to a decimal number, or if the value originated with a parse.
459 // The default implementation for formatting a DigitList converts it
460 // to a double, and formats that, allowing formatting classes that don't
461 // know about DigitList to continue to operate as they had.
463 // DecimalFormat overrides the DigitList formatting functions.
464 format(*n
->getDigitList(), appendTo
, pos
, status
);
466 switch (n
->getType()) {
467 case Formattable::kDouble
:
468 format(n
->getDouble(), appendTo
, pos
);
470 case Formattable::kLong
:
471 format(n
->getLong(), appendTo
, pos
);
473 case Formattable::kInt64
:
474 format(n
->getInt64(), appendTo
, pos
);
477 status
= U_INVALID_FORMAT_ERROR
;
485 // -------------------------------------x
486 // Formats the number object and save the format
487 // result in the toAppendTo string buffer.
490 NumberFormat::format(const Formattable
& obj
,
491 UnicodeString
& appendTo
,
492 FieldPositionIterator
* posIter
,
493 UErrorCode
& status
) const
495 if (U_FAILURE(status
)) return appendTo
;
497 ArgExtractor
arg(*this, obj
, status
);
498 const Formattable
*n
= arg
.number();
500 if (n
->isNumeric() && n
->getDigitList() != NULL
) {
502 format(*n
->getDigitList(), appendTo
, posIter
, status
);
504 switch (n
->getType()) {
505 case Formattable::kDouble
:
506 format(n
->getDouble(), appendTo
, posIter
, status
);
508 case Formattable::kLong
:
509 format(n
->getLong(), appendTo
, posIter
, status
);
511 case Formattable::kInt64
:
512 format(n
->getInt64(), appendTo
, posIter
, status
);
515 status
= U_INVALID_FORMAT_ERROR
;
523 // -------------------------------------
526 NumberFormat::format(int64_t number
,
527 UnicodeString
& appendTo
,
528 FieldPosition
& pos
) const
530 // default so we don't introduce a new abstract method
531 return format((int32_t)number
, appendTo
, pos
);
534 // -------------------------------------
535 // Parses the string and save the result object as well
536 // as the final parsed position.
539 NumberFormat::parseObject(const UnicodeString
& source
,
541 ParsePosition
& parse_pos
) const
543 parse(source
, result
, parse_pos
);
546 // -------------------------------------
547 // Formats a double number and save the result in a string.
550 NumberFormat::format(double number
, UnicodeString
& appendTo
) const
552 FieldPosition
pos(0);
553 return format(number
, appendTo
, pos
);
556 // -------------------------------------
557 // Formats a long number and save the result in a string.
560 NumberFormat::format(int32_t number
, UnicodeString
& appendTo
) const
562 FieldPosition
pos(0);
563 return format(number
, appendTo
, pos
);
566 // -------------------------------------
567 // Formats a long number and save the result in a string.
570 NumberFormat::format(int64_t number
, UnicodeString
& appendTo
) const
572 FieldPosition
pos(0);
573 return format(number
, appendTo
, pos
);
576 // -------------------------------------
577 // Parses the text and save the result object. If the returned
578 // parse position is 0, that means the parsing failed, the status
579 // code needs to be set to failure. Ignores the returned parse
580 // position, otherwise.
583 NumberFormat::parse(const UnicodeString
& text
,
585 UErrorCode
& status
) const
587 if (U_FAILURE(status
)) return;
589 ParsePosition
parsePosition(0);
590 parse(text
, result
, parsePosition
);
591 if (parsePosition
.getIndex() == 0) {
592 status
= U_INVALID_FORMAT_ERROR
;
596 Formattable
& NumberFormat::parseCurrency(const UnicodeString
& text
,
598 ParsePosition
& pos
) const {
599 // Default implementation only -- subclasses should override
600 int32_t start
= pos
.getIndex();
601 parse(text
, result
, pos
);
602 if (pos
.getIndex() != start
) {
604 UErrorCode ec
= U_ZERO_ERROR
;
605 getEffectiveCurrency(curr
, ec
);
607 Formattable
n(result
);
608 CurrencyAmount
*tempCurAmnt
= new CurrencyAmount(n
, curr
, ec
); // Use for null testing.
609 if (U_FAILURE(ec
) || tempCurAmnt
== NULL
) {
610 pos
.setIndex(start
); // indicate failure
612 result
.adoptObject(tempCurAmnt
);
619 // -------------------------------------
620 // Sets to only parse integers.
623 NumberFormat::setParseIntegerOnly(UBool value
)
625 fParseIntegerOnly
= value
;
628 // -------------------------------------
629 // Sets whether or not parse is strict.
632 NumberFormat::setParseStrict(UBool value
)
634 fParseStrict
= value
;
637 // -------------------------------------
638 // Create a number style NumberFormat instance with the default locale.
640 NumberFormat
* U_EXPORT2
641 NumberFormat::createInstance(UErrorCode
& status
)
643 return createInstance(Locale::getDefault(), kNumberStyle
, status
);
646 // -------------------------------------
647 // Create a number style NumberFormat instance with the inLocale locale.
649 NumberFormat
* U_EXPORT2
650 NumberFormat::createInstance(const Locale
& inLocale
, UErrorCode
& status
)
652 return createInstance(inLocale
, kNumberStyle
, status
);
655 // -------------------------------------
656 // Create a currency style NumberFormat instance with the default locale.
658 NumberFormat
* U_EXPORT2
659 NumberFormat::createCurrencyInstance(UErrorCode
& status
)
661 return createCurrencyInstance(Locale::getDefault(), status
);
664 // -------------------------------------
665 // Create a currency style NumberFormat instance with the inLocale locale.
667 NumberFormat
* U_EXPORT2
668 NumberFormat::createCurrencyInstance(const Locale
& inLocale
, UErrorCode
& status
)
670 return createInstance(inLocale
, kCurrencyStyle
, status
);
673 // -------------------------------------
674 // Create a percent style NumberFormat instance with the default locale.
676 NumberFormat
* U_EXPORT2
677 NumberFormat::createPercentInstance(UErrorCode
& status
)
679 return createInstance(Locale::getDefault(), kPercentStyle
, status
);
682 // -------------------------------------
683 // Create a percent style NumberFormat instance with the inLocale locale.
685 NumberFormat
* U_EXPORT2
686 NumberFormat::createPercentInstance(const Locale
& inLocale
, UErrorCode
& status
)
688 return createInstance(inLocale
, kPercentStyle
, status
);
691 // -------------------------------------
692 // Create a scientific style NumberFormat instance with the default locale.
694 NumberFormat
* U_EXPORT2
695 NumberFormat::createScientificInstance(UErrorCode
& status
)
697 return createInstance(Locale::getDefault(), kScientificStyle
, status
);
700 // -------------------------------------
701 // Create a scientific style NumberFormat instance with the inLocale locale.
703 NumberFormat
* U_EXPORT2
704 NumberFormat::createScientificInstance(const Locale
& inLocale
, UErrorCode
& status
)
706 return createInstance(inLocale
, kScientificStyle
, status
);
709 // -------------------------------------
711 const Locale
* U_EXPORT2
712 NumberFormat::getAvailableLocales(int32_t& count
)
714 return Locale::getAvailableLocales(count
);
717 // ------------------------------------------
721 //-------------------------------------------
723 #if !UCONFIG_NO_SERVICE
725 // -------------------------------------
727 class ICUNumberFormatFactory
: public ICUResourceBundleFactory
{
729 virtual UObject
* handleCreate(const Locale
& loc
, int32_t kind
, const ICUService
* /* service */, UErrorCode
& status
) const {
730 // !!! kind is not an EStyles, need to determine how to handle this
731 return NumberFormat::makeInstance(loc
, (NumberFormat::EStyles
)kind
, status
);
735 // -------------------------------------
737 class NFFactory
: public LocaleKeyFactory
{
739 NumberFormatFactory
* _delegate
;
743 NFFactory(NumberFormatFactory
* delegate
)
744 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
745 , _delegate(delegate
)
756 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const
758 if (handlesKey(key
, status
)) {
759 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
761 lkey
.canonicalLocale(loc
);
762 int32_t kind
= lkey
.kind();
764 UObject
* result
= _delegate
->createFormat(loc
, (UNumberFormatStyle
)(kind
+1));
765 if (result
== NULL
) {
766 result
= service
->getKey((ICUServiceKey
&)key
/* cast away const */, NULL
, this, status
);
775 * Return the set of ids that this factory supports (visible or
776 * otherwise). This can be called often and might need to be
777 * cached if it is expensive to create.
779 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
781 if (U_SUCCESS(status
)) {
784 const UnicodeString
* const idlist
= _delegate
->getSupportedIDs(count
, status
);
785 ((NFFactory
*)this)->_ids
= new Hashtable(status
); /* cast away const */
787 for (int i
= 0; i
< count
; ++i
) {
788 _ids
->put(idlist
[i
], (void*)this, status
);
798 class ICUNumberFormatService
: public ICULocaleService
{
800 ICUNumberFormatService()
801 : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
803 UErrorCode status
= U_ZERO_ERROR
;
804 registerFactory(new ICUNumberFormatFactory(), status
);
807 virtual UObject
* cloneInstance(UObject
* instance
) const {
808 return ((NumberFormat
*)instance
)->clone();
811 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* /* actualID */, UErrorCode
& status
) const {
812 LocaleKey
& lkey
= (LocaleKey
&)key
;
813 int32_t kind
= lkey
.kind();
815 lkey
.currentLocale(loc
);
816 return NumberFormat::makeInstance(loc
, (NumberFormat::EStyles
)kind
, status
);
819 virtual UBool
isDefault() const {
820 return countFactories() == 1;
824 // -------------------------------------
826 static ICULocaleService
*
827 getNumberFormatService(void)
830 UMTX_CHECK(NULL
, (UBool
)(gService
== NULL
), needInit
);
832 ICULocaleService
* newservice
= new ICUNumberFormatService();
835 if (gService
== NULL
) {
836 gService
= newservice
;
844 // we won the contention, this thread can register cleanup.
845 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
851 // -------------------------------------
853 URegistryKey U_EXPORT2
854 NumberFormat::registerFactory(NumberFormatFactory
* toAdopt
, UErrorCode
& status
)
856 ICULocaleService
*service
= getNumberFormatService();
858 NFFactory
*tempnnf
= new NFFactory(toAdopt
);
859 if (tempnnf
!= NULL
) {
860 return service
->registerFactory(tempnnf
, status
);
863 status
= U_MEMORY_ALLOCATION_ERROR
;
867 // -------------------------------------
870 NumberFormat::unregister(URegistryKey key
, UErrorCode
& status
)
872 if (U_SUCCESS(status
)) {
874 UMTX_CHECK(NULL
, gService
!= NULL
, haveService
);
876 return gService
->unregister(key
, status
);
878 status
= U_ILLEGAL_ARGUMENT_ERROR
;
883 // -------------------------------------
884 StringEnumeration
* U_EXPORT2
885 NumberFormat::getAvailableLocales(void)
887 ICULocaleService
*service
= getNumberFormatService();
889 return service
->getAvailableLocales();
891 return NULL
; // no way to return error condition
893 #endif /* UCONFIG_NO_SERVICE */
894 // -------------------------------------
896 NumberFormat
* U_EXPORT2
897 NumberFormat::createInstance(const Locale
& loc
, EStyles kind
, UErrorCode
& status
)
899 #if !UCONFIG_NO_SERVICE
901 UMTX_CHECK(NULL
, gService
!= NULL
, haveService
);
903 return (NumberFormat
*)gService
->get(loc
, kind
, status
);
908 return makeInstance(loc
, kind
, status
);
913 // -------------------------------------
914 // Checks if the thousand/10 thousand grouping is used in the
915 // NumberFormat instance.
918 NumberFormat::isGroupingUsed() const
920 return fGroupingUsed
;
923 // -------------------------------------
924 // Sets to use the thousand/10 thousand grouping in the
925 // NumberFormat instance.
928 NumberFormat::setGroupingUsed(UBool newValue
)
930 fGroupingUsed
= newValue
;
933 // -------------------------------------
934 // Gets the maximum number of digits for the integral part for
935 // this NumberFormat instance.
937 int32_t NumberFormat::getMaximumIntegerDigits() const
939 return fMaxIntegerDigits
;
942 // -------------------------------------
943 // Sets the maximum number of digits for the integral part for
944 // this NumberFormat instance.
947 NumberFormat::setMaximumIntegerDigits(int32_t newValue
)
949 fMaxIntegerDigits
= uprv_max(0, uprv_min(newValue
, gMaxIntegerDigits
));
950 if(fMinIntegerDigits
> fMaxIntegerDigits
)
951 fMinIntegerDigits
= fMaxIntegerDigits
;
954 // -------------------------------------
955 // Gets the minimum number of digits for the integral part for
956 // this NumberFormat instance.
959 NumberFormat::getMinimumIntegerDigits() const
961 return fMinIntegerDigits
;
964 // -------------------------------------
965 // Sets the minimum number of digits for the integral part for
966 // this NumberFormat instance.
969 NumberFormat::setMinimumIntegerDigits(int32_t newValue
)
971 fMinIntegerDigits
= uprv_max(0, uprv_min(newValue
, gMinIntegerDigits
));
972 if(fMinIntegerDigits
> fMaxIntegerDigits
)
973 fMaxIntegerDigits
= fMinIntegerDigits
;
976 // -------------------------------------
977 // Gets the maximum number of digits for the fractional part for
978 // this NumberFormat instance.
981 NumberFormat::getMaximumFractionDigits() const
983 return fMaxFractionDigits
;
986 // -------------------------------------
987 // Sets the maximum number of digits for the fractional part for
988 // this NumberFormat instance.
991 NumberFormat::setMaximumFractionDigits(int32_t newValue
)
993 fMaxFractionDigits
= uprv_max(0, uprv_min(newValue
, gMaxIntegerDigits
));
994 if(fMaxFractionDigits
< fMinFractionDigits
)
995 fMinFractionDigits
= fMaxFractionDigits
;
998 // -------------------------------------
999 // Gets the minimum number of digits for the fractional part for
1000 // this NumberFormat instance.
1003 NumberFormat::getMinimumFractionDigits() const
1005 return fMinFractionDigits
;
1008 // -------------------------------------
1009 // Sets the minimum number of digits for the fractional part for
1010 // this NumberFormat instance.
1013 NumberFormat::setMinimumFractionDigits(int32_t newValue
)
1015 fMinFractionDigits
= uprv_max(0, uprv_min(newValue
, gMinIntegerDigits
));
1016 if (fMaxFractionDigits
< fMinFractionDigits
)
1017 fMaxFractionDigits
= fMinFractionDigits
;
1020 // -------------------------------------
1022 void NumberFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
1023 if (U_FAILURE(ec
)) {
1027 u_strncpy(fCurrency
, theCurrency
, 3);
1034 const UChar
* NumberFormat::getCurrency() const {
1038 void NumberFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
1039 const UChar
* c
= getCurrency();
1041 u_strncpy(result
, c
, 3);
1044 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
1046 loc
= uloc_getDefault();
1048 ucurr_forLocale(loc
, result
, 4, &ec
);
1052 // -------------------------------------
1053 // Creates the NumberFormat instance of the specified style (number, currency,
1054 // or percent) for the desired locale.
1057 NumberFormat::makeInstance(const Locale
& desiredLocale
,
1061 if (U_FAILURE(status
)) return NULL
;
1063 if (style
< 0 || style
>= kStyleCount
) {
1064 status
= U_ILLEGAL_ARGUMENT_ERROR
;
1070 int32_t count
= desiredLocale
.getKeywordValue("compat", buffer
, sizeof(buffer
), status
);
1072 // if the locale has "@compat=host", create a host-specific NumberFormat
1073 if (count
> 0 && uprv_strcmp(buffer
, "host") == 0) {
1074 Win32NumberFormat
*f
= NULL
;
1082 case kCurrencyStyle
:
1083 case kIsoCurrencyStyle
: // do not support plural formatting here
1084 case kPluralCurrencyStyle
:
1085 f
= new Win32NumberFormat(desiredLocale
, curr
, status
);
1087 if (U_SUCCESS(status
)) {
1100 NumberFormat
* f
= NULL
;
1101 DecimalFormatSymbols
* symbolsToAdopt
= NULL
;
1102 UnicodeString pattern
;
1103 UResourceBundle
*resource
= ures_open(NULL
, desiredLocale
.getName(), &status
);
1104 NumberingSystem
*ns
= NULL
;
1105 UBool deleteSymbols
= TRUE
;
1106 UHashtable
* cache
= NULL
;
1108 UBool getCache
= FALSE
;
1109 UBool deleteNS
= FALSE
;
1111 if (U_FAILURE(status
)) {
1112 // We don't appear to have resource data available -- use the last-resort data
1113 status
= U_USING_FALLBACK_WARNING
;
1114 // When the data is unavailable, and locale isn't passed in, last resort data is used.
1115 symbolsToAdopt
= new DecimalFormatSymbols(status
);
1117 // Creates a DecimalFormat instance with the last resort number patterns.
1118 pattern
.setTo(TRUE
, gLastResortNumberPatterns
[style
], -1);
1121 // Loads the decimal symbols of the desired locale.
1122 symbolsToAdopt
= new DecimalFormatSymbols(desiredLocale
, status
);
1126 /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
1127 * the pattern is the same as the pattern of CURRENCYSTYLE
1128 * but by replacing the single currency sign with
1129 * double currency sign or triple currency sign.
1131 int styleInNumberPattern
= ((style
== kIsoCurrencyStyle
||
1132 style
== kPluralCurrencyStyle
) ?
1133 kCurrencyStyle
: style
);
1135 resource
= ures_getByKeyWithFallback(resource
, gNumberElements
, resource
, &status
);
1136 // TODO : Get patterns on a per numbering system basis, for right now assumes "latn" for patterns
1137 resource
= ures_getByKeyWithFallback(resource
, gLatn
, resource
, &status
);
1138 resource
= ures_getByKeyWithFallback(resource
, gPatterns
, resource
, &status
);
1140 const UChar
*patResStr
= ures_getStringByKeyWithFallback(resource
, gFormatKeys
[styleInNumberPattern
], &patLen
, &status
);
1142 // Creates the specified decimal format style of the desired locale.
1143 pattern
.setTo(TRUE
, patResStr
, patLen
);
1145 if (U_FAILURE(status
) || symbolsToAdopt
== NULL
) {
1148 if(style
==kCurrencyStyle
|| style
== kIsoCurrencyStyle
){
1149 const UChar
* currPattern
= symbolsToAdopt
->getCurrencyPattern();
1150 if(currPattern
!=NULL
){
1151 pattern
.setTo(currPattern
, u_strlen(currPattern
));
1155 // Use numbering system cache hashtable
1156 UMTX_CHECK(&nscacheMutex
, (UBool
)(cache
!= NumberingSystem_cache
), getCache
);
1158 umtx_lock(&nscacheMutex
);
1159 cache
= NumberingSystem_cache
;
1160 umtx_unlock(&nscacheMutex
);
1163 // Check cache we got, create if non-existant
1164 status
= U_ZERO_ERROR
;
1165 if (cache
== NULL
) {
1166 cache
= uhash_open(uhash_hashLong
,
1171 if (cache
== NULL
|| U_FAILURE(status
)) {
1172 // cache not created - out of memory
1177 uhash_setValueDeleter(cache
, deleteNumberingSystem
);
1179 // set final NumberingSystem_cache value
1180 UHashtable
* h
= NULL
;
1182 UMTX_CHECK(&nscacheMutex
, (UBool
)(h
!= NumberingSystem_cache
), getCache
);
1184 umtx_lock(&nscacheMutex
);
1185 h
= NumberingSystem_cache
;
1186 umtx_unlock(&nscacheMutex
);
1189 umtx_lock(&nscacheMutex
);
1190 NumberingSystem_cache
= h
= cache
;
1192 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
1193 umtx_unlock(&nscacheMutex
);
1203 // Get cached numbering system
1204 if (cache
!= NULL
) {
1205 hashKey
= desiredLocale
.hashCode();
1207 umtx_lock(&nscacheMutex
);
1208 ns
= (NumberingSystem
*)uhash_iget(cache
, hashKey
);
1210 ns
= NumberingSystem::createInstance(desiredLocale
,status
);
1211 uhash_iput(cache
, hashKey
, (void*)ns
, &status
);
1213 umtx_unlock(&nscacheMutex
);
1216 ns
= NumberingSystem::createInstance(desiredLocale
,status
);
1220 // check results of getting a numbering system
1221 if ((ns
== NULL
) || (U_FAILURE(status
))) {
1225 if (ns
->isAlgorithmic()) {
1226 UnicodeString nsDesc
;
1227 UnicodeString nsRuleSetGroup
;
1228 UnicodeString nsRuleSetName
;
1230 URBNFRuleSetTag desiredRulesType
= URBNF_NUMBERING_SYSTEM
;
1232 nsDesc
.setTo(ns
->getDescription());
1233 int32_t firstSlash
= nsDesc
.indexOf(gSlash
);
1234 int32_t lastSlash
= nsDesc
.lastIndexOf(gSlash
);
1235 if ( lastSlash
> firstSlash
) {
1236 char nsLocID
[ULOC_FULLNAME_CAPACITY
];
1238 nsDesc
.extract(0,firstSlash
,nsLocID
,ULOC_FULLNAME_CAPACITY
,US_INV
);
1239 nsRuleSetGroup
.setTo(nsDesc
,firstSlash
+1,lastSlash
-firstSlash
-1);
1240 nsRuleSetName
.setTo(nsDesc
,lastSlash
+1);
1242 nsLoc
= Locale::createFromName(nsLocID
);
1244 UnicodeString SpelloutRules
= UNICODE_STRING_SIMPLE("SpelloutRules");
1245 if ( nsRuleSetGroup
.compare(SpelloutRules
) == 0 ) {
1246 desiredRulesType
= URBNF_SPELLOUT
;
1249 nsLoc
= desiredLocale
;
1250 nsRuleSetName
.setTo(nsDesc
);
1253 RuleBasedNumberFormat
*r
= new RuleBasedNumberFormat(desiredRulesType
,nsLoc
,status
);
1255 if (U_FAILURE(status
) || r
== NULL
) {
1258 r
->setDefaultRuleSet(nsRuleSetName
,status
);
1259 f
= (NumberFormat
*) r
;
1262 // replace single currency sign in the pattern with double currency sign
1263 // if the style is kIsoCurrencyStyle
1264 if (style
== kIsoCurrencyStyle
) {
1265 pattern
.findAndReplace(gSingleCurrencySign
, gDoubleCurrencySign
);
1268 f
= new DecimalFormat(pattern
, symbolsToAdopt
, style
, status
);
1269 if (U_FAILURE(status
) || f
== NULL
) {
1272 deleteSymbols
= FALSE
;
1275 f
->setLocaleIDs(ures_getLocaleByType(resource
, ULOC_VALID_LOCALE
, &status
),
1276 ures_getLocaleByType(resource
, ULOC_ACTUAL_LOCALE
, &status
));
1279 ures_close(resource
);
1281 if (deleteNS
&& ns
) {
1285 if (U_FAILURE(status
)) {
1286 /* If f exists, then it will delete the symbols */
1288 delete symbolsToAdopt
;
1295 if (f
== NULL
|| symbolsToAdopt
== NULL
) {
1296 status
= U_MEMORY_ALLOCATION_ERROR
;
1299 if (deleteSymbols
&& symbolsToAdopt
!= NULL
) {
1300 delete symbolsToAdopt
;
1307 #endif /* #if !UCONFIG_NO_FORMATTING */