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