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