• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 *******************************************************************************
3 * Copyright (C) 1997-2011, International Business Machines Corporation and    *
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 *
7 * File NUMFMT.CPP
8 *
9 * Modification History:
10 *
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 ********************************************************************************
23 */
24 
25 #include "unicode/utypes.h"
26 
27 #if !UCONFIG_NO_FORMATTING
28 
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 "charstr.h"
39 #include "winnmfmt.h"
40 #include "uresimp.h"
41 #include "uhash.h"
42 #include "cmemory.h"
43 #include "servloc.h"
44 #include "ucln_in.h"
45 #include "cstring.h"
46 #include "putilimp.h"
47 #include "umutex.h"
48 #include "mutex.h"
49 #include "digitlst.h"
50 #include <float.h>
51 
52 //#define FMT_DEBUG
53 
54 #ifdef FMT_DEBUG
55 #include <stdio.h>
debugout(UnicodeString s)56 static void debugout(UnicodeString s) {
57     char buf[2000];
58     s.extract((int32_t) 0, s.length(), buf);
59     printf("%s", buf);
60 }
61 #define debug(x) printf("%s", x);
62 #else
63 #define debugout(x)
64 #define debug(x)
65 #endif
66 
67 // If no number pattern can be located for a locale, this is the last
68 // resort.
69 static const UChar gLastResortDecimalPat[] = {
70     0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
71 };
72 static const UChar gLastResortCurrencyPat[] = {
73     0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
74 };
75 static const UChar gLastResortPercentPat[] = {
76     0x23, 0x30, 0x25, 0 /* "#0%" */
77 };
78 static const UChar gLastResortScientificPat[] = {
79     0x23, 0x45, 0x30, 0 /* "#E0" */
80 };
81 static const UChar gLastResortIsoCurrencyPat[] = {
82     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)" */
83 };
84 static const UChar gLastResortPluralCurrencyPat[] = {
85     0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/
86 };
87 
88 static const UChar gSingleCurrencySign[] = {0xA4, 0};
89 static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0};
90 
91 static const UChar gSlash = 0x2f;
92 
93 // If the maximum base 10 exponent were 4, then the largest number would
94 // be 99,999 which has 5 digits.
95 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
96 static const int32_t gMaxIntegerDigits = DBL_MAX_10_EXP + DBL_DIG + 1;
97 static const int32_t gMinIntegerDigits = 127;
98 
99 static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = {
100     NULL,  // UNUM_PATTERN_DECIMAL
101     gLastResortDecimalPat,  // UNUM_DECIMAL
102     gLastResortCurrencyPat,  // UNUM_CURRENCY
103     gLastResortPercentPat,  // UNUM_PERCENT
104     gLastResortScientificPat,  // UNUM_SCIENTIFIC
105     NULL,  // UNUM_SPELLOUT
106     NULL,  // UNUM_ORDINAL
107     NULL,  // UNUM_DURATION
108     NULL,  // UNUM_NUMBERING_SYSTEM
109     NULL,  // UNUM_PATTERN_RULEBASED
110     gLastResortIsoCurrencyPat,  // UNUM_CURRENCY_ISO
111     gLastResortPluralCurrencyPat  // UNUM_CURRENCY_PLURAL
112 };
113 
114 // Keys used for accessing resource bundles
115 
116 static const char *gNumberElements = "NumberElements";
117 static const char *gLatn = "latn";
118 static const char *gPatterns = "patterns";
119 static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = {
120     NULL,  // UNUM_PATTERN_DECIMAL
121     "decimalFormat",  // UNUM_DECIMAL
122     "currencyFormat",  // UNUM_CURRENCY
123     "percentFormat",  // UNUM_PERCENT
124     "scientificFormat",  // UNUM_SCIENTIFIC
125     NULL,  // UNUM_SPELLOUT
126     NULL,  // UNUM_ORDINAL
127     NULL,  // UNUM_DURATION
128     NULL,  // UNUM_NUMBERING_SYSTEM
129     NULL,  // UNUM_PATTERN_RULEBASED
130     // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL,
131     // the pattern is the same as the pattern of UNUM_CURRENCY
132     // except for replacing the single currency sign with
133     // double currency sign or triple currency sign.
134     "currencyFormat",  // UNUM_CURRENCY_ISO
135     "currencyFormat"  // UNUM_CURRENCY_PLURAL
136 };
137 
138 // Static hashtable cache of NumberingSystem objects used by NumberFormat
139 static UHashtable * NumberingSystem_cache = NULL;
140 
141 static UMTX nscacheMutex = NULL;
142 
143 #if !UCONFIG_NO_SERVICE
144 static U_NAMESPACE_QUALIFIER ICULocaleService* gService = NULL;
145 #endif
146 
147 /**
148  * Release all static memory held by Number Format.
149  */
150 U_CDECL_BEGIN
151 static void U_CALLCONV
deleteNumberingSystem(void * obj)152 deleteNumberingSystem(void *obj) {
153     delete (U_NAMESPACE_QUALIFIER NumberingSystem *)obj;
154 }
155 
numfmt_cleanup(void)156 static UBool U_CALLCONV numfmt_cleanup(void) {
157 #if !UCONFIG_NO_SERVICE
158     if (gService) {
159         delete gService;
160         gService = NULL;
161     }
162 #endif
163     if (NumberingSystem_cache) {
164         // delete NumberingSystem_cache;
165         uhash_close(NumberingSystem_cache);
166         NumberingSystem_cache = NULL;
167     }
168 
169     return TRUE;
170 }
171 U_CDECL_END
172 
173 // *****************************************************************************
174 // class NumberFormat
175 // *****************************************************************************
176 
177 U_NAMESPACE_BEGIN
178 
UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)179 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)
180 
181 #if !UCONFIG_NO_SERVICE
182 // -------------------------------------
183 // SimpleNumberFormatFactory implementation
184 NumberFormatFactory::~NumberFormatFactory() {}
SimpleNumberFormatFactory(const Locale & locale,UBool visible)185 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible)
186     : _visible(visible)
187 {
188     LocaleUtility::initNameFromLocale(locale, _id);
189 }
190 
~SimpleNumberFormatFactory()191 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
192 
visible(void) const193 UBool SimpleNumberFormatFactory::visible(void) const {
194     return _visible;
195 }
196 
197 const UnicodeString *
getSupportedIDs(int32_t & count,UErrorCode & status) const198 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const
199 {
200     if (U_SUCCESS(status)) {
201         count = 1;
202         return &_id;
203     }
204     count = 0;
205     return NULL;
206 }
207 #endif /* #if !UCONFIG_NO_SERVICE */
208 
209 // -------------------------------------
210 // default constructor
NumberFormat()211 NumberFormat::NumberFormat()
212 :   fGroupingUsed(TRUE),
213     fMaxIntegerDigits(gMaxIntegerDigits),
214     fMinIntegerDigits(1),
215     fMaxFractionDigits(3), // invariant, >= minFractionDigits
216     fMinFractionDigits(0),
217     fParseIntegerOnly(FALSE),
218     fLenient(FALSE)
219 {
220     fCurrency[0] = 0;
221 }
222 
223 // -------------------------------------
224 
~NumberFormat()225 NumberFormat::~NumberFormat()
226 {
227 }
228 
229 // -------------------------------------
230 // copy constructor
231 
NumberFormat(const NumberFormat & source)232 NumberFormat::NumberFormat(const NumberFormat &source)
233 :   Format(source)
234 {
235     *this = source;
236 }
237 
238 // -------------------------------------
239 // assignment operator
240 
241 NumberFormat&
operator =(const NumberFormat & rhs)242 NumberFormat::operator=(const NumberFormat& rhs)
243 {
244     if (this != &rhs)
245     {
246         Format::operator=(rhs);
247         fGroupingUsed = rhs.fGroupingUsed;
248         fMaxIntegerDigits = rhs.fMaxIntegerDigits;
249         fMinIntegerDigits = rhs.fMinIntegerDigits;
250         fMaxFractionDigits = rhs.fMaxFractionDigits;
251         fMinFractionDigits = rhs.fMinFractionDigits;
252         fParseIntegerOnly = rhs.fParseIntegerOnly;
253         u_strncpy(fCurrency, rhs.fCurrency, 4);
254         fLenient = rhs.fLenient;
255     }
256     return *this;
257 }
258 
259 // -------------------------------------
260 
261 UBool
operator ==(const Format & that) const262 NumberFormat::operator==(const Format& that) const
263 {
264     // Format::operator== guarantees this cast is safe
265     NumberFormat* other = (NumberFormat*)&that;
266 
267 #ifdef FMT_DEBUG
268     // This code makes it easy to determine why two format objects that should
269     // be equal aren't.
270     UBool first = TRUE;
271     if (!Format::operator==(that)) {
272         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
273         debug("Format::!=");
274     }
275     if (!(fMaxIntegerDigits == other->fMaxIntegerDigits &&
276           fMinIntegerDigits == other->fMinIntegerDigits)) {
277         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
278         debug("Integer digits !=");
279     }
280     if (!(fMaxFractionDigits == other->fMaxFractionDigits &&
281           fMinFractionDigits == other->fMinFractionDigits)) {
282         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
283         debug("Fraction digits !=");
284     }
285     if (!(fGroupingUsed == other->fGroupingUsed)) {
286         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
287         debug("fGroupingUsed != ");
288     }
289     if (!(fParseIntegerOnly == other->fParseIntegerOnly)) {
290         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
291         debug("fParseIntegerOnly != ");
292     }
293     if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) {
294         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
295         debug("fCurrency !=");
296     }
297     if (!(fLenient == other->fLenient)) {
298         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
299         debug("fLenient != ");
300     }
301     if (!first) { printf(" ]"); }
302 #endif
303 
304     return ((this == &that) ||
305             ((Format::operator==(that) &&
306               fMaxIntegerDigits == other->fMaxIntegerDigits &&
307               fMinIntegerDigits == other->fMinIntegerDigits &&
308               fMaxFractionDigits == other->fMaxFractionDigits &&
309               fMinFractionDigits == other->fMinFractionDigits &&
310               fGroupingUsed == other->fGroupingUsed &&
311               fParseIntegerOnly == other->fParseIntegerOnly &&
312               u_strcmp(fCurrency, other->fCurrency) == 0 &&
313               fLenient == other->fLenient)));
314 }
315 
316 // -------------------------------------
317 // Default implementation sets unsupported error; subclasses should
318 // override.
319 
320 UnicodeString&
format(double,UnicodeString & toAppendTo,FieldPositionIterator *,UErrorCode & status) const321 NumberFormat::format(double /* unused number */,
322                      UnicodeString& toAppendTo,
323                      FieldPositionIterator* /* unused posIter */,
324                      UErrorCode& status) const
325 {
326     if (!U_FAILURE(status)) {
327         status = U_UNSUPPORTED_ERROR;
328     }
329     return toAppendTo;
330 }
331 
332 // -------------------------------------
333 // Default implementation sets unsupported error; subclasses should
334 // override.
335 
336 UnicodeString&
format(int32_t,UnicodeString & toAppendTo,FieldPositionIterator *,UErrorCode & status) const337 NumberFormat::format(int32_t /* unused number */,
338                      UnicodeString& toAppendTo,
339                      FieldPositionIterator* /* unused posIter */,
340                      UErrorCode& status) const
341 {
342     if (!U_FAILURE(status)) {
343         status = U_UNSUPPORTED_ERROR;
344     }
345     return toAppendTo;
346 }
347 
348 // -------------------------------------
349 // Default implementation sets unsupported error; subclasses should
350 // override.
351 
352 UnicodeString&
format(int64_t,UnicodeString & toAppendTo,FieldPositionIterator *,UErrorCode & status) const353 NumberFormat::format(int64_t /* unused number */,
354                      UnicodeString& toAppendTo,
355                      FieldPositionIterator* /* unused posIter */,
356                      UErrorCode& status) const
357 {
358     if (!U_FAILURE(status)) {
359         status = U_UNSUPPORTED_ERROR;
360     }
361     return toAppendTo;
362 }
363 
364 // -------------------------------------
365 // Decimal Number format() default implementation
366 // Subclasses do not normally override this function, but rather the DigitList
367 // formatting functions..
368 //   The expected call chain from here is
369 //      this function ->
370 //      NumberFormat::format(Formattable  ->
371 //      DecimalFormat::format(DigitList
372 //
373 //   Or, for subclasses of Formattable that do not know about DigitList,
374 //       this Function ->
375 //       NumberFormat::format(Formattable  ->
376 //       NumberFormat::format(DigitList  ->
377 //       XXXFormat::format(double
378 
379 UnicodeString&
format(const StringPiece & decimalNum,UnicodeString & toAppendTo,FieldPositionIterator * fpi,UErrorCode & status) const380 NumberFormat::format(const StringPiece &decimalNum,
381                      UnicodeString& toAppendTo,
382                      FieldPositionIterator* fpi,
383                      UErrorCode& status) const
384 {
385     Formattable f;
386     f.setDecimalNumber(decimalNum, status);
387     format(f, toAppendTo, fpi, status);
388     return toAppendTo;
389 }
390 
391 // -------------------------------------
392 // Formats the number object and save the format
393 // result in the toAppendTo string buffer.
394 
395 // utility to save/restore state, used in two overloads
396 // of format(const Formattable&...) below.
397 
398 class ArgExtractor {
399   NumberFormat *ncnf;
400   const Formattable* num;
401   UBool setCurr;
402   UChar save[4];
403 
404  public:
405   ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status);
406   ~ArgExtractor();
407 
408   const Formattable* number(void) const;
409 };
410 
411 inline const Formattable*
number(void) const412 ArgExtractor::number(void) const {
413   return num;
414 }
415 
ArgExtractor(const NumberFormat & nf,const Formattable & obj,UErrorCode & status)416 ArgExtractor::ArgExtractor(const NumberFormat& nf, const Formattable& obj, UErrorCode& status)
417     : ncnf((NumberFormat*) &nf), num(&obj), setCurr(FALSE) {
418 
419     const UObject* o = obj.getObject(); // most commonly o==NULL
420     const CurrencyAmount* amt;
421     if (o != NULL && (amt = dynamic_cast<const CurrencyAmount*>(o)) != NULL) {
422         // getISOCurrency() returns a pointer to internal storage, so we
423         // copy it to retain it across the call to setCurrency().
424         const UChar* curr = amt->getISOCurrency();
425         u_strcpy(save, nf.getCurrency());
426         setCurr = (u_strcmp(curr, save) != 0);
427         if (setCurr) {
428             ncnf->setCurrency(curr, status);
429         }
430         num = &amt->getNumber();
431     }
432 }
433 
~ArgExtractor()434 ArgExtractor::~ArgExtractor() {
435     if (setCurr) {
436         UErrorCode ok = U_ZERO_ERROR;
437         ncnf->setCurrency(save, ok); // always restore currency
438     }
439 }
440 
format(const DigitList & number,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const441 UnicodeString& NumberFormat::format(const DigitList &number,
442                       UnicodeString& appendTo,
443                       FieldPositionIterator* posIter,
444                       UErrorCode& status) const {
445     // DecimalFormat overrides this function, and handles DigitList based big decimals.
446     // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
447     // so this default implementation falls back to formatting decimal numbers as doubles.
448     if (U_FAILURE(status)) {
449         return appendTo;
450     }
451     double dnum = number.getDouble();
452     format(dnum, appendTo, posIter, status);
453     return appendTo;
454 }
455 
456 
457 
458 UnicodeString&
format(const DigitList & number,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const459 NumberFormat::format(const DigitList &number,
460                      UnicodeString& appendTo,
461                      FieldPosition& pos,
462                      UErrorCode &status) const {
463     // DecimalFormat overrides this function, and handles DigitList based big decimals.
464     // Other subclasses (ChoiceFormat, RuleBasedNumberFormat) do not (yet) handle DigitLists,
465     // so this default implementation falls back to formatting decimal numbers as doubles.
466     if (U_FAILURE(status)) {
467         return appendTo;
468     }
469     double dnum = number.getDouble();
470     format(dnum, appendTo, pos, status);
471     return appendTo;
472 }
473 
474 UnicodeString&
format(const Formattable & obj,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const475 NumberFormat::format(const Formattable& obj,
476                         UnicodeString& appendTo,
477                         FieldPosition& pos,
478                         UErrorCode& status) const
479 {
480     if (U_FAILURE(status)) return appendTo;
481 
482     ArgExtractor arg(*this, obj, status);
483     const Formattable *n = arg.number();
484 
485     if (n->isNumeric() && n->getDigitList() != NULL) {
486         // Decimal Number.  We will have a DigitList available if the value was
487         //   set to a decimal number, or if the value originated with a parse.
488         //
489         // The default implementation for formatting a DigitList converts it
490         // to a double, and formats that, allowing formatting classes that don't
491         // know about DigitList to continue to operate as they had.
492         //
493         // DecimalFormat overrides the DigitList formatting functions.
494         format(*n->getDigitList(), appendTo, pos, status);
495     } else {
496         switch (n->getType()) {
497         case Formattable::kDouble:
498             format(n->getDouble(), appendTo, pos);
499             break;
500         case Formattable::kLong:
501             format(n->getLong(), appendTo, pos);
502             break;
503         case Formattable::kInt64:
504             format(n->getInt64(), appendTo, pos);
505             break;
506         default:
507             status = U_INVALID_FORMAT_ERROR;
508             break;
509         }
510     }
511 
512     return appendTo;
513 }
514 
515 // -------------------------------------x
516 // Formats the number object and save the format
517 // result in the toAppendTo string buffer.
518 
519 UnicodeString&
format(const Formattable & obj,UnicodeString & appendTo,FieldPositionIterator * posIter,UErrorCode & status) const520 NumberFormat::format(const Formattable& obj,
521                         UnicodeString& appendTo,
522                         FieldPositionIterator* posIter,
523                         UErrorCode& status) const
524 {
525     if (U_FAILURE(status)) return appendTo;
526 
527     ArgExtractor arg(*this, obj, status);
528     const Formattable *n = arg.number();
529 
530     if (n->isNumeric() && n->getDigitList() != NULL) {
531         // Decimal Number
532         format(*n->getDigitList(), appendTo, posIter, status);
533     } else {
534         switch (n->getType()) {
535         case Formattable::kDouble:
536             format(n->getDouble(), appendTo, posIter, status);
537             break;
538         case Formattable::kLong:
539             format(n->getLong(), appendTo, posIter, status);
540             break;
541         case Formattable::kInt64:
542             format(n->getInt64(), appendTo, posIter, status);
543             break;
544         default:
545             status = U_INVALID_FORMAT_ERROR;
546             break;
547         }
548     }
549 
550     return appendTo;
551 }
552 
553 // -------------------------------------
554 
555 UnicodeString&
format(int64_t number,UnicodeString & appendTo,FieldPosition & pos) const556 NumberFormat::format(int64_t number,
557                      UnicodeString& appendTo,
558                      FieldPosition& pos) const
559 {
560     // default so we don't introduce a new abstract method
561     return format((int32_t)number, appendTo, pos);
562 }
563 
564 // -------------------------------------
565 // Parses the string and save the result object as well
566 // as the final parsed position.
567 
568 void
parseObject(const UnicodeString & source,Formattable & result,ParsePosition & parse_pos) const569 NumberFormat::parseObject(const UnicodeString& source,
570                              Formattable& result,
571                              ParsePosition& parse_pos) const
572 {
573     parse(source, result, parse_pos);
574 }
575 
576 // -------------------------------------
577 // Formats a double number and save the result in a string.
578 
579 UnicodeString&
format(double number,UnicodeString & appendTo) const580 NumberFormat::format(double number, UnicodeString& appendTo) const
581 {
582     FieldPosition pos(0);
583     return format(number, appendTo, pos);
584 }
585 
586 // -------------------------------------
587 // Formats a long number and save the result in a string.
588 
589 UnicodeString&
format(int32_t number,UnicodeString & appendTo) const590 NumberFormat::format(int32_t number, UnicodeString& appendTo) const
591 {
592     FieldPosition pos(0);
593     return format(number, appendTo, pos);
594 }
595 
596 // -------------------------------------
597 // Formats a long number and save the result in a string.
598 
599 UnicodeString&
format(int64_t number,UnicodeString & appendTo) const600 NumberFormat::format(int64_t number, UnicodeString& appendTo) const
601 {
602     FieldPosition pos(0);
603     return format(number, appendTo, pos);
604 }
605 
606 // -------------------------------------
607 // Parses the text and save the result object.  If the returned
608 // parse position is 0, that means the parsing failed, the status
609 // code needs to be set to failure.  Ignores the returned parse
610 // position, otherwise.
611 
612 void
parse(const UnicodeString & text,Formattable & result,UErrorCode & status) const613 NumberFormat::parse(const UnicodeString& text,
614                         Formattable& result,
615                         UErrorCode& status) const
616 {
617     if (U_FAILURE(status)) return;
618 
619     ParsePosition parsePosition(0);
620     parse(text, result, parsePosition);
621     if (parsePosition.getIndex() == 0) {
622         status = U_INVALID_FORMAT_ERROR;
623     }
624 }
625 
parseCurrency(const UnicodeString & text,Formattable & result,ParsePosition & pos) const626 Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
627                                          Formattable& result,
628                                          ParsePosition& pos) const {
629     // Default implementation only -- subclasses should override
630     int32_t start = pos.getIndex();
631     parse(text, result, pos);
632     if (pos.getIndex() != start) {
633         UChar curr[4];
634         UErrorCode ec = U_ZERO_ERROR;
635         getEffectiveCurrency(curr, ec);
636         if (U_SUCCESS(ec)) {
637             Formattable n(result);
638             CurrencyAmount *tempCurAmnt = new CurrencyAmount(n, curr, ec);  // Use for null testing.
639             if (U_FAILURE(ec) || tempCurAmnt == NULL) {
640                 pos.setIndex(start); // indicate failure
641             } else {
642             	result.adoptObject(tempCurAmnt);
643             }
644         }
645     }
646     return result;
647 }
648 
649 // -------------------------------------
650 // Sets to only parse integers.
651 
652 void
setParseIntegerOnly(UBool value)653 NumberFormat::setParseIntegerOnly(UBool value)
654 {
655     fParseIntegerOnly = value;
656 }
657 
658 // -------------------------------------
659 // Sets whether lenient parse is enabled.
660 
661 void
setLenient(UBool enable)662 NumberFormat::setLenient(UBool enable)
663 {
664     fLenient = enable;
665 }
666 
667 // -------------------------------------
668 // Create a number style NumberFormat instance with the default locale.
669 
670 NumberFormat* U_EXPORT2
createInstance(UErrorCode & status)671 NumberFormat::createInstance(UErrorCode& status)
672 {
673     return createInstance(Locale::getDefault(), UNUM_DECIMAL, status);
674 }
675 
676 // -------------------------------------
677 // Create a number style NumberFormat instance with the inLocale locale.
678 
679 NumberFormat* U_EXPORT2
createInstance(const Locale & inLocale,UErrorCode & status)680 NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status)
681 {
682     return createInstance(inLocale, UNUM_DECIMAL, status);
683 }
684 
685 // -------------------------------------
686 // Create a currency style NumberFormat instance with the default locale.
687 
688 NumberFormat* U_EXPORT2
createCurrencyInstance(UErrorCode & status)689 NumberFormat::createCurrencyInstance(UErrorCode& status)
690 {
691     return createCurrencyInstance(Locale::getDefault(),  status);
692 }
693 
694 // -------------------------------------
695 // Create a currency style NumberFormat instance with the inLocale locale.
696 
697 NumberFormat* U_EXPORT2
createCurrencyInstance(const Locale & inLocale,UErrorCode & status)698 NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status)
699 {
700     return createInstance(inLocale, UNUM_CURRENCY, status);
701 }
702 
703 // -------------------------------------
704 // Create a percent style NumberFormat instance with the default locale.
705 
706 NumberFormat* U_EXPORT2
createPercentInstance(UErrorCode & status)707 NumberFormat::createPercentInstance(UErrorCode& status)
708 {
709     return createInstance(Locale::getDefault(), UNUM_PERCENT, status);
710 }
711 
712 // -------------------------------------
713 // Create a percent style NumberFormat instance with the inLocale locale.
714 
715 NumberFormat* U_EXPORT2
createPercentInstance(const Locale & inLocale,UErrorCode & status)716 NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status)
717 {
718     return createInstance(inLocale, UNUM_PERCENT, status);
719 }
720 
721 // -------------------------------------
722 // Create a scientific style NumberFormat instance with the default locale.
723 
724 NumberFormat* U_EXPORT2
createScientificInstance(UErrorCode & status)725 NumberFormat::createScientificInstance(UErrorCode& status)
726 {
727     return createInstance(Locale::getDefault(), UNUM_SCIENTIFIC, status);
728 }
729 
730 // -------------------------------------
731 // Create a scientific style NumberFormat instance with the inLocale locale.
732 
733 NumberFormat* U_EXPORT2
createScientificInstance(const Locale & inLocale,UErrorCode & status)734 NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status)
735 {
736     return createInstance(inLocale, UNUM_SCIENTIFIC, status);
737 }
738 
739 // -------------------------------------
740 
741 const Locale* U_EXPORT2
getAvailableLocales(int32_t & count)742 NumberFormat::getAvailableLocales(int32_t& count)
743 {
744     return Locale::getAvailableLocales(count);
745 }
746 
747 // ------------------------------------------
748 //
749 // Registration
750 //
751 //-------------------------------------------
752 
753 #if !UCONFIG_NO_SERVICE
754 
755 // -------------------------------------
756 
757 class ICUNumberFormatFactory : public ICUResourceBundleFactory {
758 protected:
handleCreate(const Locale & loc,int32_t kind,const ICUService *,UErrorCode & status) const759     virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const {
760         return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status);
761     }
762 };
763 
764 // -------------------------------------
765 
766 class NFFactory : public LocaleKeyFactory {
767 private:
768     NumberFormatFactory* _delegate;
769     Hashtable* _ids;
770 
771 public:
NFFactory(NumberFormatFactory * delegate)772     NFFactory(NumberFormatFactory* delegate)
773         : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
774         , _delegate(delegate)
775         , _ids(NULL)
776     {
777     }
778 
~NFFactory()779     virtual ~NFFactory()
780     {
781         delete _delegate;
782         delete _ids;
783     }
784 
create(const ICUServiceKey & key,const ICUService * service,UErrorCode & status) const785     virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
786     {
787         if (handlesKey(key, status)) {
788             const LocaleKey& lkey = (const LocaleKey&)key;
789             Locale loc;
790             lkey.canonicalLocale(loc);
791             int32_t kind = lkey.kind();
792 
793             UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)kind);
794             if (result == NULL) {
795                 result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status);
796             }
797             return result;
798         }
799         return NULL;
800     }
801 
802 protected:
803     /**
804      * Return the set of ids that this factory supports (visible or
805      * otherwise).  This can be called often and might need to be
806      * cached if it is expensive to create.
807      */
getSupportedIDs(UErrorCode & status) const808     virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
809     {
810         if (U_SUCCESS(status)) {
811             if (!_ids) {
812                 int32_t count = 0;
813                 const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status);
814                 ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */
815                 if (_ids) {
816                     for (int i = 0; i < count; ++i) {
817                         _ids->put(idlist[i], (void*)this, status);
818                     }
819                 }
820             }
821             return _ids;
822         }
823         return NULL;
824     }
825 };
826 
827 class ICUNumberFormatService : public ICULocaleService {
828 public:
ICUNumberFormatService()829     ICUNumberFormatService()
830         : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
831     {
832         UErrorCode status = U_ZERO_ERROR;
833         registerFactory(new ICUNumberFormatFactory(), status);
834     }
835 
cloneInstance(UObject * instance) const836     virtual UObject* cloneInstance(UObject* instance) const {
837         return ((NumberFormat*)instance)->clone();
838     }
839 
handleDefault(const ICUServiceKey & key,UnicodeString *,UErrorCode & status) const840     virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const {
841         LocaleKey& lkey = (LocaleKey&)key;
842         int32_t kind = lkey.kind();
843         Locale loc;
844         lkey.currentLocale(loc);
845         return NumberFormat::makeInstance(loc, (UNumberFormatStyle)kind, status);
846     }
847 
isDefault() const848     virtual UBool isDefault() const {
849         return countFactories() == 1;
850     }
851 };
852 
853 // -------------------------------------
854 
855 static ICULocaleService*
getNumberFormatService(void)856 getNumberFormatService(void)
857 {
858     UBool needInit;
859     UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
860     if (needInit) {
861         ICULocaleService * newservice = new ICUNumberFormatService();
862         if (newservice) {
863             umtx_lock(NULL);
864             if (gService == NULL) {
865                 gService = newservice;
866                 newservice = NULL;
867             }
868             umtx_unlock(NULL);
869         }
870         if (newservice) {
871             delete newservice;
872         } else {
873             // we won the contention, this thread can register cleanup.
874             ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
875         }
876     }
877     return gService;
878 }
879 
880 // -------------------------------------
881 
882 URegistryKey U_EXPORT2
registerFactory(NumberFormatFactory * toAdopt,UErrorCode & status)883 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
884 {
885   ICULocaleService *service = getNumberFormatService();
886   if (service) {
887 	  NFFactory *tempnnf = new NFFactory(toAdopt);
888 	  if (tempnnf != NULL) {
889 		  return service->registerFactory(tempnnf, status);
890 	  }
891   }
892   status = U_MEMORY_ALLOCATION_ERROR;
893   return NULL;
894 }
895 
896 // -------------------------------------
897 
898 UBool U_EXPORT2
unregister(URegistryKey key,UErrorCode & status)899 NumberFormat::unregister(URegistryKey key, UErrorCode& status)
900 {
901     if (U_SUCCESS(status)) {
902         UBool haveService;
903         UMTX_CHECK(NULL, gService != NULL, haveService);
904         if (haveService) {
905             return gService->unregister(key, status);
906         }
907         status = U_ILLEGAL_ARGUMENT_ERROR;
908     }
909     return FALSE;
910 }
911 
912 // -------------------------------------
913 StringEnumeration* U_EXPORT2
getAvailableLocales(void)914 NumberFormat::getAvailableLocales(void)
915 {
916   ICULocaleService *service = getNumberFormatService();
917   if (service) {
918     return service->getAvailableLocales();
919   }
920   return NULL; // no way to return error condition
921 }
922 #endif /* UCONFIG_NO_SERVICE */
923 // -------------------------------------
924 
925 NumberFormat* U_EXPORT2
createInstance(const Locale & loc,UNumberFormatStyle kind,UErrorCode & status)926 NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status)
927 {
928 #if !UCONFIG_NO_SERVICE
929     UBool haveService;
930     UMTX_CHECK(NULL, gService != NULL, haveService);
931     if (haveService) {
932         return (NumberFormat*)gService->get(loc, kind, status);
933     }
934     else
935 #endif
936     {
937         return makeInstance(loc, kind, status);
938     }
939 }
940 
941 
942 // -------------------------------------
943 // Checks if the thousand/10 thousand grouping is used in the
944 // NumberFormat instance.
945 
946 UBool
isGroupingUsed() const947 NumberFormat::isGroupingUsed() const
948 {
949     return fGroupingUsed;
950 }
951 
952 // -------------------------------------
953 // Sets to use the thousand/10 thousand grouping in the
954 // NumberFormat instance.
955 
956 void
setGroupingUsed(UBool newValue)957 NumberFormat::setGroupingUsed(UBool newValue)
958 {
959     fGroupingUsed = newValue;
960 }
961 
962 // -------------------------------------
963 // Gets the maximum number of digits for the integral part for
964 // this NumberFormat instance.
965 
getMaximumIntegerDigits() const966 int32_t NumberFormat::getMaximumIntegerDigits() const
967 {
968     return fMaxIntegerDigits;
969 }
970 
971 // -------------------------------------
972 // Sets the maximum number of digits for the integral part for
973 // this NumberFormat instance.
974 
975 void
setMaximumIntegerDigits(int32_t newValue)976 NumberFormat::setMaximumIntegerDigits(int32_t newValue)
977 {
978     fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
979     if(fMinIntegerDigits > fMaxIntegerDigits)
980         fMinIntegerDigits = fMaxIntegerDigits;
981 }
982 
983 // -------------------------------------
984 // Gets the minimum number of digits for the integral part for
985 // this NumberFormat instance.
986 
987 int32_t
getMinimumIntegerDigits() const988 NumberFormat::getMinimumIntegerDigits() const
989 {
990     return fMinIntegerDigits;
991 }
992 
993 // -------------------------------------
994 // Sets the minimum number of digits for the integral part for
995 // this NumberFormat instance.
996 
997 void
setMinimumIntegerDigits(int32_t newValue)998 NumberFormat::setMinimumIntegerDigits(int32_t newValue)
999 {
1000     fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
1001     if(fMinIntegerDigits > fMaxIntegerDigits)
1002         fMaxIntegerDigits = fMinIntegerDigits;
1003 }
1004 
1005 // -------------------------------------
1006 // Gets the maximum number of digits for the fractional part for
1007 // this NumberFormat instance.
1008 
1009 int32_t
getMaximumFractionDigits() const1010 NumberFormat::getMaximumFractionDigits() const
1011 {
1012     return fMaxFractionDigits;
1013 }
1014 
1015 // -------------------------------------
1016 // Sets the maximum number of digits for the fractional part for
1017 // this NumberFormat instance.
1018 
1019 void
setMaximumFractionDigits(int32_t newValue)1020 NumberFormat::setMaximumFractionDigits(int32_t newValue)
1021 {
1022     fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
1023     if(fMaxFractionDigits < fMinFractionDigits)
1024         fMinFractionDigits = fMaxFractionDigits;
1025 }
1026 
1027 // -------------------------------------
1028 // Gets the minimum number of digits for the fractional part for
1029 // this NumberFormat instance.
1030 
1031 int32_t
getMinimumFractionDigits() const1032 NumberFormat::getMinimumFractionDigits() const
1033 {
1034     return fMinFractionDigits;
1035 }
1036 
1037 // -------------------------------------
1038 // Sets the minimum number of digits for the fractional part for
1039 // this NumberFormat instance.
1040 
1041 void
setMinimumFractionDigits(int32_t newValue)1042 NumberFormat::setMinimumFractionDigits(int32_t newValue)
1043 {
1044     fMinFractionDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
1045     if (fMaxFractionDigits < fMinFractionDigits)
1046         fMaxFractionDigits = fMinFractionDigits;
1047 }
1048 
1049 // -------------------------------------
1050 
setCurrency(const UChar * theCurrency,UErrorCode & ec)1051 void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
1052     if (U_FAILURE(ec)) {
1053         return;
1054     }
1055     if (theCurrency) {
1056         u_strncpy(fCurrency, theCurrency, 3);
1057         fCurrency[3] = 0;
1058     } else {
1059         fCurrency[0] = 0;
1060     }
1061 }
1062 
getCurrency() const1063 const UChar* NumberFormat::getCurrency() const {
1064     return fCurrency;
1065 }
1066 
getEffectiveCurrency(UChar * result,UErrorCode & ec) const1067 void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
1068     const UChar* c = getCurrency();
1069     if (*c != 0) {
1070         u_strncpy(result, c, 3);
1071         result[3] = 0;
1072     } else {
1073         const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
1074         if (loc == NULL) {
1075             loc = uloc_getDefault();
1076         }
1077         ucurr_forLocale(loc, result, 4, &ec);
1078     }
1079 }
1080 
1081 // -------------------------------------
1082 // Creates the NumberFormat instance of the specified style (number, currency,
1083 // or percent) for the desired locale.
1084 
1085 UBool
isStyleSupported(UNumberFormatStyle style)1086 NumberFormat::isStyleSupported(UNumberFormatStyle style) {
1087     return gLastResortNumberPatterns[style] != NULL;
1088 }
1089 
1090 NumberFormat*
makeInstance(const Locale & desiredLocale,UNumberFormatStyle style,UErrorCode & status)1091 NumberFormat::makeInstance(const Locale& desiredLocale,
1092                            UNumberFormatStyle style,
1093                            UErrorCode& status)
1094 {
1095     if (U_FAILURE(status)) return NULL;
1096 
1097     if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) {
1098         status = U_ILLEGAL_ARGUMENT_ERROR;
1099         return NULL;
1100     }
1101 
1102     // Some styles are not supported. This is a result of merging
1103     // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
1104     // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
1105     // this one and unum_open().
1106     // The UNUM_PATTERN_ styles are not supported here
1107     // because this method does not take a pattern string.
1108     if (!isStyleSupported(style)) {
1109         status = U_UNSUPPORTED_ERROR;
1110         return NULL;
1111     }
1112 
1113 #ifdef U_WINDOWS
1114     char buffer[8];
1115     int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);
1116 
1117     // if the locale has "@compat=host", create a host-specific NumberFormat
1118     if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) {
1119         Win32NumberFormat *f = NULL;
1120         UBool curr = TRUE;
1121 
1122         switch (style) {
1123         case UNUM_DECIMAL:
1124             curr = FALSE;
1125             // fall-through
1126 
1127         case UNUM_CURRENCY:
1128         case UNUM_CURRENCY_ISO: // do not support plural formatting here
1129         case UNUM_CURRENCY_PLURAL:
1130             f = new Win32NumberFormat(desiredLocale, curr, status);
1131 
1132             if (U_SUCCESS(status)) {
1133                 return f;
1134             }
1135 
1136             delete f;
1137             break;
1138 
1139         default:
1140             break;
1141         }
1142     }
1143 #endif
1144 
1145     LocalPointer<DecimalFormatSymbols> symbolsToAdopt;
1146     UnicodeString pattern;
1147     LocalUResourceBundlePointer ownedResource(ures_open(NULL, desiredLocale.getName(), &status));
1148     if (U_FAILURE(status)) {
1149         // We don't appear to have resource data available -- use the last-resort data
1150         status = U_USING_FALLBACK_WARNING;
1151         // When the data is unavailable, and locale isn't passed in, last resort data is used.
1152         symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(status));
1153         if (symbolsToAdopt.isNull()) {
1154             status = U_MEMORY_ALLOCATION_ERROR;
1155             return NULL;
1156         }
1157 
1158         // Creates a DecimalFormat instance with the last resort number patterns.
1159         pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1);
1160     }
1161     else {
1162         // Loads the decimal symbols of the desired locale.
1163         symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(desiredLocale, status));
1164         if (symbolsToAdopt.isNull()) {
1165             status = U_MEMORY_ALLOCATION_ERROR;
1166             return NULL;
1167         }
1168 
1169         UResourceBundle *resource = ownedResource.orphan();
1170         resource = ures_getByKeyWithFallback(resource, gNumberElements, resource, &status);
1171         // TODO : Get patterns on a per numbering system basis, for right now assumes "latn" for patterns
1172         resource = ures_getByKeyWithFallback(resource, gLatn, resource, &status);
1173         resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status);
1174         ownedResource.adoptInstead(resource);
1175 
1176         int32_t patLen = 0;
1177         const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status);
1178 
1179         // Creates the specified decimal format style of the desired locale.
1180         pattern.setTo(TRUE, patResStr, patLen);
1181     }
1182     if (U_FAILURE(status)) {
1183         return NULL;
1184     }
1185     if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO){
1186         const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
1187         if(currPattern!=NULL){
1188             pattern.setTo(currPattern, u_strlen(currPattern));
1189         }
1190     }
1191 
1192     // Use numbering system cache hashtable
1193     UHashtable *cache;
1194     UMTX_CHECK(&nscacheMutex, NumberingSystem_cache, cache);
1195 
1196     // Check cache we got, create if non-existant
1197     if (cache == NULL) {
1198         cache = uhash_open(uhash_hashLong,
1199                            uhash_compareLong,
1200                            NULL,
1201                            &status);
1202 
1203         if (U_FAILURE(status)) {
1204             // cache not created - out of memory
1205             status = U_ZERO_ERROR;  // work without the cache
1206             cache = NULL;
1207         } else {
1208             // cache created
1209             uhash_setValueDeleter(cache, deleteNumberingSystem);
1210 
1211             // set final NumberingSystem_cache value
1212             Mutex lock(&nscacheMutex);
1213             if (NumberingSystem_cache == NULL) {
1214                 NumberingSystem_cache = cache;
1215                 ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
1216             } else {
1217                 uhash_close(cache);
1218                 cache = NumberingSystem_cache;
1219             }
1220         }
1221     }
1222 
1223     // Get cached numbering system
1224     LocalPointer<NumberingSystem> ownedNs;
1225     NumberingSystem *ns = NULL;
1226     if (cache != NULL) {
1227         // TODO: Bad hash key usage, see ticket #8504.
1228         int32_t hashKey = desiredLocale.hashCode();
1229 
1230         Mutex lock(&nscacheMutex);
1231         ns = (NumberingSystem *)uhash_iget(cache, hashKey);
1232         if (ns == NULL) {
1233             ns = NumberingSystem::createInstance(desiredLocale,status);
1234             uhash_iput(cache, hashKey, (void*)ns, &status);
1235         }
1236     } else {
1237         ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status));
1238         ns = ownedNs.getAlias();
1239     }
1240 
1241     // check results of getting a numbering system
1242     if (U_FAILURE(status)) {
1243         return NULL;
1244     }
1245 
1246     NumberFormat *f;
1247     if (ns->isAlgorithmic()) {
1248         UnicodeString nsDesc;
1249         UnicodeString nsRuleSetGroup;
1250         UnicodeString nsRuleSetName;
1251         Locale nsLoc;
1252         URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;
1253 
1254         nsDesc.setTo(ns->getDescription());
1255         int32_t firstSlash = nsDesc.indexOf(gSlash);
1256         int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
1257         if ( lastSlash > firstSlash ) {
1258             CharString nsLocID;
1259 
1260             nsLocID.appendInvariantChars(nsDesc.tempSubString(0, firstSlash), status);
1261             nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
1262             nsRuleSetName.setTo(nsDesc,lastSlash+1);
1263 
1264             nsLoc = Locale::createFromName(nsLocID.data());
1265 
1266             UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
1267             if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
1268                 desiredRulesType = URBNF_SPELLOUT;
1269             }
1270         } else {
1271             nsLoc = desiredLocale;
1272             nsRuleSetName.setTo(nsDesc);
1273         }
1274 
1275         RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
1276         if (r == NULL) {
1277             status = U_MEMORY_ALLOCATION_ERROR;
1278             return NULL;
1279         }
1280         r->setDefaultRuleSet(nsRuleSetName,status);
1281         f = r;
1282     } else {
1283         // replace single currency sign in the pattern with double currency sign
1284         // if the style is UNUM_CURRENCY_ISO
1285         if (style == UNUM_CURRENCY_ISO) {
1286             pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign);
1287         }
1288 
1289         // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails.
1290         DecimalFormatSymbols *syms = symbolsToAdopt.orphan();
1291         f = new DecimalFormat(pattern, syms, style, status);
1292         if (f == NULL) {
1293             delete syms;
1294             status = U_MEMORY_ALLOCATION_ERROR;
1295             return NULL;
1296         }
1297     }
1298 
1299     f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status),
1300                     ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status));
1301     if (U_FAILURE(status)) {
1302         delete f;
1303         return NULL;
1304     }
1305     return f;
1306 }
1307 
1308 U_NAMESPACE_END
1309 
1310 #endif /* #if !UCONFIG_NO_FORMATTING */
1311 
1312 //eof
1313