2 *******************************************************************************
3 * Copyright (C) 1997-2004, 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/ures.h"
32 #include "unicode/dcfmtsym.h"
33 #include "unicode/decimfmt.h"
34 #include "unicode/ustring.h"
35 #include "unicode/ucurr.h"
36 #include "unicode/curramt.h"
49 static void debugout(UnicodeString s
) {
51 s
.extract((int32_t) 0, s
.length(), buf
);
54 #define debug(x) printf("%s", x);
60 // If no number pattern can be located for a locale, this is the last
62 static const UChar gLastResortDecimalPat
[] = {
63 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
65 static const UChar gLastResortCurrencyPat
[] = {
66 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
68 static const UChar gLastResortPercentPat
[] = {
69 0x23, 0x30, 0x25, 0 /* "#0%" */
71 static const UChar gLastResortScientificPat
[] = {
72 0x23, 0x45, 0x30, 0 /* "#E0" */
74 // *****************************************************************************
76 // *****************************************************************************
80 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat
)
81 // If the maximum base 10 exponent were 4, then the largest number would
82 // be 99,999 which has 5 digits.
83 const int32_t NumberFormat::fgMaxIntegerDigits
= DBL_MAX_10_EXP
+ 1; // Should be ~40 ? --srl
84 const int32_t NumberFormat::fgMinIntegerDigits
= 127;
86 const int32_t NumberFormat::fgNumberPatternsCount
= 3;
88 const UChar
* const NumberFormat::fgLastResortNumberPatterns
[] =
90 gLastResortDecimalPat
,
91 gLastResortCurrencyPat
,
92 gLastResortPercentPat
,
93 gLastResortScientificPat
96 #if !UCONFIG_NO_SERVICE
97 // -------------------------------------
98 // SimpleNumberFormatFactory implementation
99 NumberFormatFactory::~NumberFormatFactory() {}
100 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale
& locale
, UBool visible
)
102 , _id(locale
.getName())
106 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
108 UBool
SimpleNumberFormatFactory::visible(void) const {
112 const UnicodeString
*
113 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count
, UErrorCode
& status
) const
115 if (U_SUCCESS(status
)) {
122 #endif /* #if !UCONFIG_NO_SERVICE */
124 // -------------------------------------
125 // default constructor
126 NumberFormat::NumberFormat()
127 : fGroupingUsed(TRUE
),
128 fMaxIntegerDigits(fgMaxIntegerDigits
),
129 fMinIntegerDigits(1),
130 fMaxFractionDigits(3), // invariant, >= minFractionDigits
131 fMinFractionDigits(0),
132 fParseIntegerOnly(FALSE
)
137 // -------------------------------------
139 NumberFormat::~NumberFormat()
143 // -------------------------------------
146 NumberFormat::NumberFormat(const NumberFormat
&source
)
152 // -------------------------------------
153 // assignment operator
156 NumberFormat::operator=(const NumberFormat
& rhs
)
160 fGroupingUsed
= rhs
.fGroupingUsed
;
161 fMaxIntegerDigits
= rhs
.fMaxIntegerDigits
;
162 fMinIntegerDigits
= rhs
.fMinIntegerDigits
;
163 fMaxFractionDigits
= rhs
.fMaxFractionDigits
;
164 fMinFractionDigits
= rhs
.fMinFractionDigits
;
165 fParseIntegerOnly
= rhs
.fParseIntegerOnly
;
166 u_strncpy(fCurrency
, rhs
.fCurrency
, 4);
171 // -------------------------------------
174 NumberFormat::operator==(const Format
& that
) const
176 // Format::operator== guarantees this cast is safe
177 NumberFormat
* other
= (NumberFormat
*)&that
;
180 // This code makes it easy to determine why two format objects that should
183 if (!Format::operator==(that
)) {
184 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
187 if (!(fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
188 fMinIntegerDigits
== other
->fMinIntegerDigits
)) {
189 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
190 debug("Integer digits !=");
192 if (!(fMaxFractionDigits
== other
->fMaxFractionDigits
&&
193 fMinFractionDigits
== other
->fMinFractionDigits
)) {
194 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
195 debug("Fraction digits !=");
197 if (!(fGroupingUsed
== other
->fGroupingUsed
)) {
198 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
199 debug("fGroupingUsed != ");
201 if (!(fParseIntegerOnly
== other
->fParseIntegerOnly
)) {
202 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
203 debug("fParseIntegerOnly != ");
205 if (!(u_strcmp(fCurrency
, other
->fCurrency
) == 0)) {
206 if (first
) { printf("[ "); first
= FALSE
; } else { printf(", "); }
207 debug("fCurrency !=");
209 if (!first
) { printf(" ]"); }
212 return ((this == &that
) ||
213 ((Format::operator==(that
) &&
214 fMaxIntegerDigits
== other
->fMaxIntegerDigits
&&
215 fMinIntegerDigits
== other
->fMinIntegerDigits
&&
216 fMaxFractionDigits
== other
->fMaxFractionDigits
&&
217 fMinFractionDigits
== other
->fMinFractionDigits
&&
218 fGroupingUsed
== other
->fGroupingUsed
&&
219 fParseIntegerOnly
== other
->fParseIntegerOnly
&&
220 u_strcmp(fCurrency
, other
->fCurrency
) == 0)));
223 // -------------------------------------x
224 // Formats the number object and save the format
225 // result in the toAppendTo string buffer.
228 NumberFormat::format(const Formattable
& obj
,
229 UnicodeString
& appendTo
,
231 UErrorCode
& status
) const
233 if (U_FAILURE(status
)) return appendTo
;
235 NumberFormat
* nonconst
= (NumberFormat
*) this;
236 const Formattable
* n
= &obj
;
239 UBool setCurr
= FALSE
;
240 const UObject
* o
= obj
.getObject(); // most commonly o==NULL
242 o
->getDynamicClassID() == CurrencyAmount::getStaticClassID()) {
243 // getISOCurrency() returns a pointer to internal storage, so we
244 // copy it to retain it across the call to setCurrency().
245 const CurrencyAmount
* amt
= (const CurrencyAmount
*) o
;
246 const UChar
* curr
= amt
->getISOCurrency();
247 u_strcpy(save
, getCurrency());
248 setCurr
= (u_strcmp(curr
, save
) != 0);
250 nonconst
->setCurrency(curr
, status
);
252 n
= &amt
->getNumber();
255 switch (n
->getType()) {
256 case Formattable::kDouble
:
257 format(n
->getDouble(), appendTo
, pos
);
259 case Formattable::kLong
:
260 format(n
->getLong(), appendTo
, pos
);
262 case Formattable::kInt64
:
263 format(n
->getInt64(), appendTo
, pos
);
266 status
= U_INVALID_FORMAT_ERROR
;
271 UErrorCode ok
= U_ZERO_ERROR
;
272 nonconst
->setCurrency(save
, ok
); // always restore currency
277 // -------------------------------------
280 NumberFormat::format(int64_t number
,
281 UnicodeString
& appendTo
,
282 FieldPosition
& pos
) const
284 // default so we don't introduce a new abstract method
285 return format((int32_t)number
, appendTo
, pos
);
288 // -------------------------------------
289 // Parses the string and save the result object as well
290 // as the final parsed position.
293 NumberFormat::parseObject(const UnicodeString
& source
,
295 ParsePosition
& parse_pos
) const
297 parse(source
, result
, parse_pos
);
300 // -------------------------------------
301 // Formats a double number and save the result in a string.
304 NumberFormat::format(double number
, UnicodeString
& appendTo
) const
306 FieldPosition
pos(0);
307 return format(number
, appendTo
, pos
);
310 // -------------------------------------
311 // Formats a long number and save the result in a string.
314 NumberFormat::format(int32_t number
, UnicodeString
& appendTo
) const
316 FieldPosition
pos(0);
317 return format(number
, appendTo
, pos
);
320 // -------------------------------------
321 // Formats a long number and save the result in a string.
324 NumberFormat::format(int64_t number
, UnicodeString
& appendTo
) const
326 FieldPosition
pos(0);
327 return format(number
, appendTo
, pos
);
330 // -------------------------------------
331 // Parses the text and save the result object. If the returned
332 // parse position is 0, that means the parsing failed, the status
333 // code needs to be set to failure. Ignores the returned parse
334 // position, otherwise.
337 NumberFormat::parse(const UnicodeString
& text
,
339 UErrorCode
& status
) const
341 if (U_FAILURE(status
)) return;
343 ParsePosition
parsePosition(0);
344 parse(text
, result
, parsePosition
);
345 if (parsePosition
.getIndex() == 0) {
346 status
= U_INVALID_FORMAT_ERROR
;
350 Formattable
& NumberFormat::parseCurrency(const UnicodeString
& text
,
352 ParsePosition
& pos
) const {
353 // Default implementation only -- subclasses should override
354 int32_t start
= pos
.getIndex();
355 parse(text
, result
, pos
);
356 if (pos
.getIndex() != start
) {
358 UErrorCode ec
= U_ZERO_ERROR
;
359 getEffectiveCurrency(curr
, ec
);
361 Formattable
n(result
);
362 result
.adoptObject(new CurrencyAmount(n
, curr
, ec
));
364 pos
.setIndex(start
); // indicate failure
371 // -------------------------------------
372 // Sets to only parse integers.
375 NumberFormat::setParseIntegerOnly(UBool value
)
377 fParseIntegerOnly
= value
;
380 // -------------------------------------
381 // Create a number style NumberFormat instance with the default locale.
383 NumberFormat
* U_EXPORT2
384 NumberFormat::createInstance(UErrorCode
& status
)
386 return createInstance(Locale::getDefault(), kNumberStyle
, status
);
389 // -------------------------------------
390 // Create a number style NumberFormat instance with the inLocale locale.
392 NumberFormat
* U_EXPORT2
393 NumberFormat::createInstance(const Locale
& inLocale
, UErrorCode
& status
)
395 return createInstance(inLocale
, kNumberStyle
, status
);
398 // -------------------------------------
399 // Create a currency style NumberFormat instance with the default locale.
401 NumberFormat
* U_EXPORT2
402 NumberFormat::createCurrencyInstance(UErrorCode
& status
)
404 return createCurrencyInstance(Locale::getDefault(), status
);
407 // -------------------------------------
408 // Create a currency style NumberFormat instance with the inLocale locale.
410 NumberFormat
* U_EXPORT2
411 NumberFormat::createCurrencyInstance(const Locale
& inLocale
, UErrorCode
& status
)
413 return createInstance(inLocale
, kCurrencyStyle
, status
);
416 // -------------------------------------
417 // Create a percent style NumberFormat instance with the default locale.
419 NumberFormat
* U_EXPORT2
420 NumberFormat::createPercentInstance(UErrorCode
& status
)
422 return createInstance(Locale::getDefault(), kPercentStyle
, status
);
425 // -------------------------------------
426 // Create a percent style NumberFormat instance with the inLocale locale.
428 NumberFormat
* U_EXPORT2
429 NumberFormat::createPercentInstance(const Locale
& inLocale
, UErrorCode
& status
)
431 return createInstance(inLocale
, kPercentStyle
, status
);
434 // -------------------------------------
435 // Create a scientific style NumberFormat instance with the default locale.
437 NumberFormat
* U_EXPORT2
438 NumberFormat::createScientificInstance(UErrorCode
& status
)
440 return createInstance(Locale::getDefault(), kScientificStyle
, status
);
443 // -------------------------------------
444 // Create a scientific style NumberFormat instance with the inLocale locale.
446 NumberFormat
* U_EXPORT2
447 NumberFormat::createScientificInstance(const Locale
& inLocale
, UErrorCode
& status
)
449 return createInstance(inLocale
, kScientificStyle
, status
);
452 // -------------------------------------
454 const Locale
* U_EXPORT2
455 NumberFormat::getAvailableLocales(int32_t& count
)
457 return Locale::getAvailableLocales(count
);
460 // ------------------------------------------
464 //-------------------------------------------
466 #if !UCONFIG_NO_SERVICE
467 static ICULocaleService
* gService
= NULL
;
470 * Release all static memory held by numberformat.
473 static UBool U_CALLCONV
numfmt_cleanup(void) {
482 // -------------------------------------
484 class ICUNumberFormatFactory
: public ICUResourceBundleFactory
{
486 virtual UObject
* handleCreate(const Locale
& loc
, int32_t kind
, const ICUService
* /* service */, UErrorCode
& status
) const {
487 // !!! kind is not an EStyles, need to determine how to handle this
488 return NumberFormat::makeInstance(loc
, (NumberFormat::EStyles
)kind
, status
);
492 // -------------------------------------
494 class NFFactory
: public LocaleKeyFactory
{
496 NumberFormatFactory
* _delegate
;
500 NFFactory(NumberFormatFactory
* delegate
)
501 : LocaleKeyFactory(delegate
->visible() ? VISIBLE
: INVISIBLE
)
502 , _delegate(delegate
)
513 virtual UObject
* create(const ICUServiceKey
& key
, const ICUService
* service
, UErrorCode
& status
) const
515 if (handlesKey(key
, status
)) {
516 const LocaleKey
& lkey
= (const LocaleKey
&)key
;
518 lkey
.canonicalLocale(loc
);
519 int32_t kind
= lkey
.kind();
521 UObject
* result
= _delegate
->createFormat(loc
, (UNumberFormatStyle
)(kind
+1));
522 if (result
== NULL
) {
523 result
= service
->getKey((ICUServiceKey
&)key
/* cast away const */, NULL
, this, status
);
532 * Return the set of ids that this factory supports (visible or
533 * otherwise). This can be called often and might need to be
534 * cached if it is expensive to create.
536 virtual const Hashtable
* getSupportedIDs(UErrorCode
& status
) const
538 if (U_SUCCESS(status
)) {
541 const UnicodeString
* const idlist
= _delegate
->getSupportedIDs(count
, status
);
542 ((NFFactory
*)this)->_ids
= new Hashtable(status
); /* cast away const */
544 for (int i
= 0; i
< count
; ++i
) {
545 _ids
->put(idlist
[i
], (void*)this, status
);
555 class ICUNumberFormatService
: public ICULocaleService
{
557 ICUNumberFormatService()
558 : ICULocaleService("Number Format")
560 UErrorCode status
= U_ZERO_ERROR
;
561 registerFactory(new ICUNumberFormatFactory(), status
);
564 virtual UObject
* cloneInstance(UObject
* instance
) const {
565 return ((NumberFormat
*)instance
)->clone();
568 virtual UObject
* handleDefault(const ICUServiceKey
& key
, UnicodeString
* /* actualID */, UErrorCode
& status
) const {
569 LocaleKey
& lkey
= (LocaleKey
&)key
;
570 int32_t kind
= lkey
.kind();
572 lkey
.currentLocale(loc
);
573 return NumberFormat::makeInstance(loc
, (NumberFormat::EStyles
)kind
, status
);
576 virtual UBool
isDefault() const {
577 return countFactories() == 1;
581 // -------------------------------------
583 static ICULocaleService
*
584 getNumberFormatService(void)
589 needInit
= (UBool
)(gService
== NULL
);
592 ICULocaleService
* newservice
= new ICUNumberFormatService();
595 if (gService
== NULL
) {
596 gService
= newservice
;
603 // we won the contention, this thread can register cleanup.
604 #if !UCONFIG_NO_SERVICE
605 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT
, numfmt_cleanup
);
612 // -------------------------------------
614 URegistryKey U_EXPORT2
615 NumberFormat::registerFactory(NumberFormatFactory
* toAdopt
, UErrorCode
& status
)
617 ICULocaleService
*service
= getNumberFormatService();
619 return service
->registerFactory(new NFFactory(toAdopt
), status
);
621 status
= U_MEMORY_ALLOCATION_ERROR
;
625 // -------------------------------------
628 NumberFormat::unregister(URegistryKey key
, UErrorCode
& status
)
630 if (U_SUCCESS(status
)) {
632 UBool haveService
= gService
!= NULL
;
635 return gService
->unregister(key
, status
);
637 status
= U_ILLEGAL_ARGUMENT_ERROR
;
642 // -------------------------------------
643 StringEnumeration
* U_EXPORT2
644 NumberFormat::getAvailableLocales(void)
646 ICULocaleService
*service
= getNumberFormatService();
648 return service
->getAvailableLocales();
650 return NULL
; // no way to return error condition
652 #endif /* UCONFIG_NO_SERVICE */
653 // -------------------------------------
655 NumberFormat
* U_EXPORT2
656 NumberFormat::createInstance(const Locale
& loc
, EStyles kind
, UErrorCode
& status
)
658 #if !UCONFIG_NO_SERVICE
660 UBool haveService
= gService
!= NULL
;
663 return (NumberFormat
*)gService
->get(loc
, kind
, status
);
668 return makeInstance(loc
, kind
, status
);
673 // -------------------------------------
674 // Checks if the thousand/10 thousand grouping is used in the
675 // NumberFormat instance.
678 NumberFormat::isGroupingUsed() const
680 return fGroupingUsed
;
683 // -------------------------------------
684 // Sets to use the thousand/10 thousand grouping in the
685 // NumberFormat instance.
688 NumberFormat::setGroupingUsed(UBool newValue
)
690 fGroupingUsed
= newValue
;
693 // -------------------------------------
694 // Gets the maximum number of digits for the integral part for
695 // this NumberFormat instance.
697 int32_t NumberFormat::getMaximumIntegerDigits() const
699 return fMaxIntegerDigits
;
702 // -------------------------------------
703 // Sets the maximum number of digits for the integral part for
704 // this NumberFormat instance.
707 NumberFormat::setMaximumIntegerDigits(int32_t newValue
)
709 fMaxIntegerDigits
= uprv_max(0, uprv_min(newValue
, fgMaxIntegerDigits
));
710 if(fMinIntegerDigits
> fMaxIntegerDigits
)
711 fMinIntegerDigits
= fMaxIntegerDigits
;
714 // -------------------------------------
715 // Gets the minimum number of digits for the integral part for
716 // this NumberFormat instance.
719 NumberFormat::getMinimumIntegerDigits() const
721 return fMinIntegerDigits
;
724 // -------------------------------------
725 // Sets the minimum number of digits for the integral part for
726 // this NumberFormat instance.
729 NumberFormat::setMinimumIntegerDigits(int32_t newValue
)
731 fMinIntegerDigits
= uprv_max(0, uprv_min(newValue
, fgMinIntegerDigits
));
732 if(fMinIntegerDigits
> fMaxIntegerDigits
)
733 fMaxIntegerDigits
= fMinIntegerDigits
;
736 // -------------------------------------
737 // Gets the maximum number of digits for the fractional part for
738 // this NumberFormat instance.
741 NumberFormat::getMaximumFractionDigits() const
743 return fMaxFractionDigits
;
746 // -------------------------------------
747 // Sets the maximum number of digits for the fractional part for
748 // this NumberFormat instance.
751 NumberFormat::setMaximumFractionDigits(int32_t newValue
)
753 fMaxFractionDigits
= uprv_max(0, uprv_min(newValue
, fgMaxIntegerDigits
));
754 if(fMaxFractionDigits
< fMinFractionDigits
)
755 fMinFractionDigits
= fMaxFractionDigits
;
758 // -------------------------------------
759 // Gets the minimum number of digits for the fractional part for
760 // this NumberFormat instance.
763 NumberFormat::getMinimumFractionDigits() const
765 return fMinFractionDigits
;
768 // -------------------------------------
769 // Sets the minimum number of digits for the fractional part for
770 // this NumberFormat instance.
773 NumberFormat::setMinimumFractionDigits(int32_t newValue
)
775 fMinFractionDigits
= uprv_max(0, uprv_min(newValue
, fgMinIntegerDigits
));
776 if (fMaxFractionDigits
< fMinFractionDigits
)
777 fMaxFractionDigits
= fMinFractionDigits
;
780 // -------------------------------------
782 void NumberFormat::setCurrency(const UChar
* theCurrency
, UErrorCode
& ec
) {
787 u_strncpy(fCurrency
, theCurrency
, 3);
794 const UChar
* NumberFormat::getCurrency() const {
798 void NumberFormat::getEffectiveCurrency(UChar
* result
, UErrorCode
& ec
) const {
799 const UChar
* c
= getCurrency();
801 u_strncpy(result
, c
, 3);
804 const char* loc
= getLocaleID(ULOC_VALID_LOCALE
, ec
);
806 loc
= uloc_getDefault();
808 ucurr_forLocale(loc
, result
, 4, &ec
);
812 // -------------------------------------
813 // Creates the NumberFormat instance of the specified style (number, currency,
814 // or percent) for the desired locale.
817 NumberFormat::makeInstance(const Locale
& desiredLocale
,
821 if (U_FAILURE(status
)) return NULL
;
823 if (style
< 0 || style
>= kStyleCount
) {
824 status
= U_ILLEGAL_ARGUMENT_ERROR
;
828 NumberFormat
* f
= NULL
;
829 DecimalFormatSymbols
* symbolsToAdopt
= NULL
;
830 UnicodeString pattern
;
831 UResourceBundle
*resource
= ures_open((char *)0, desiredLocale
.getName(), &status
);
832 UResourceBundle
*numberPatterns
= ures_getByKey(resource
, DecimalFormat::fgNumberPatterns
, NULL
, &status
);
834 if (U_FAILURE(status
)) {
835 // We don't appear to have resource data available -- use the last-resort data
836 status
= U_USING_FALLBACK_WARNING
;
837 // When the data is unavailable, and locale isn't passed in, last resort data is used.
838 symbolsToAdopt
= new DecimalFormatSymbols(status
);
840 // Creates a DecimalFormat instance with the last resort number patterns.
841 pattern
.setTo(TRUE
, fgLastResortNumberPatterns
[style
], -1);
844 // If not all the styled patterns exists for the NumberFormat in this locale,
845 // sets the status code to failure and returns nil.
846 if (ures_getSize(numberPatterns
) < fgNumberPatternsCount
) {
847 status
= U_INVALID_FORMAT_ERROR
;
851 // Loads the decimal symbols of the desired locale.
852 symbolsToAdopt
= new DecimalFormatSymbols(desiredLocale
, status
);
855 const UChar
*patResStr
= ures_getStringByIndex(numberPatterns
, (int32_t)style
, &patLen
, &status
);
856 // Creates the specified decimal format style of the desired locale.
857 pattern
.setTo(TRUE
, patResStr
, patLen
);
859 if (U_FAILURE(status
) || symbolsToAdopt
== NULL
) {
863 // Here we assume that the locale passed in is in the canonical
864 // form, e.g: pt_PT_@currency=PTE not pt_PT_PREEURO
865 if(style
==kCurrencyStyle
){
866 char currencyCode
[8]={0};
867 int32_t currencyCodeCap
= sizeof(currencyCode
);
868 const char* locName
= desiredLocale
.getName();
869 currencyCodeCap
= uloc_getKeywordValue(locName
, "currency", currencyCode
, currencyCodeCap
, &status
);
870 if(U_SUCCESS(status
) && currencyCodeCap
> 0) {
871 /* An explicit currency was requested */
872 UErrorCode localStatus
= U_ZERO_ERROR
;
873 UResourceBundle
*currency
= ures_getByKeyWithFallback(resource
, "Currencies", NULL
, &localStatus
);
874 currency
= ures_getByKeyWithFallback(currency
, currencyCode
, currency
, &localStatus
);
875 if(U_SUCCESS(localStatus
) && ures_getSize(currency
)>2) {
876 currency
= ures_getByIndex(currency
, 2, currency
, &localStatus
);
877 int32_t currPatternLen
= 0;
878 const UChar
*currPattern
= ures_getStringByIndex(currency
, (int32_t)0, &currPatternLen
, &localStatus
);
879 UnicodeString decimalSep
= ures_getStringByIndex(currency
, (int32_t)1, NULL
, &localStatus
);
880 UnicodeString groupingSep
= ures_getStringByIndex(currency
, (int32_t)2, NULL
, &localStatus
);
881 if(U_SUCCESS(localStatus
)){
882 symbolsToAdopt
->setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol
, groupingSep
);
883 symbolsToAdopt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, decimalSep
);
884 pattern
.setTo(TRUE
, currPattern
, currPatternLen
);
885 status
= localStatus
;
888 ures_close(currency
);
889 /* else An explicit currency was requested and is unknown or locale data is malformed. */
890 /* ucurr_* API will get the correct value later on. */
892 /* else no currency keyword used. */
894 f
= new DecimalFormat(pattern
, symbolsToAdopt
, status
);
895 if (U_FAILURE(status
) || f
== NULL
) {
899 f
->setLocaleIDs(ures_getLocaleByType(numberPatterns
, ULOC_VALID_LOCALE
, &status
),
900 ures_getLocaleByType(numberPatterns
, ULOC_ACTUAL_LOCALE
, &status
));
902 ures_close(numberPatterns
);
903 ures_close(resource
);
904 if (U_FAILURE(status
)) {
905 /* If f exists, then it will delete the symbols */
907 delete symbolsToAdopt
;
914 if (f
== NULL
|| symbolsToAdopt
== NULL
) {
915 status
= U_MEMORY_ALLOCATION_ERROR
;
923 #endif /* #if !UCONFIG_NO_FORMATTING */