intl/icu/source/i18n/numfmt.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial