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