LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - numfmt.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 527 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 96 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13