Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 1997-2009, 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 <float.h>
     47 
     48 //#define FMT_DEBUG
     49 
     50 #ifdef FMT_DEBUG
     51 #include <stdio.h>
     52 static void debugout(UnicodeString s) {
     53     char buf[2000];
     54     s.extract((int32_t) 0, s.length(), buf);
     55     printf("%s", buf);
     56 }
     57 #define debug(x) printf("%s", x);
     58 #else
     59 #define debugout(x)
     60 #define debug(x)
     61 #endif
     62 
     63 // If no number pattern can be located for a locale, this is the last
     64 // resort.
     65 static const UChar gLastResortDecimalPat[] = {
     66     0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */
     67 };
     68 static const UChar gLastResortCurrencyPat[] = {
     69     0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */
     70 };
     71 static const UChar gLastResortPercentPat[] = {
     72     0x23, 0x30, 0x25, 0 /* "#0%" */
     73 };
     74 static const UChar gLastResortScientificPat[] = {
     75     0x23, 0x45, 0x30, 0 /* "#E0" */
     76 };
     77 static const UChar gLastResortIsoCurrencyPat[] = {
     78     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)" */
     79 };
     80 static const UChar gLastResortPluralCurrencyPat[] = {
     81     0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/
     82 };
     83 
     84 static const UChar gSingleCurrencySign[] = {0xA4, 0};
     85 static const UChar gDoubleCurrencySign[] = {0xA4, 0xA4, 0};
     86 
     87 static const UChar gSlash = 0x2f;
     88 
     89 // If the maximum base 10 exponent were 4, then the largest number would
     90 // be 99,999 which has 5 digits.
     91 // On IEEE754 systems gMaxIntegerDigits is 308 + possible denormalized 15 digits + rounding digit
     92 static const int32_t gMaxIntegerDigits = DBL_MAX_10_EXP + DBL_DIG + 1;
     93 static const int32_t gMinIntegerDigits = 127;
     94 
     95 static const UChar * const gLastResortNumberPatterns[] =
     96 {
     97     gLastResortDecimalPat,
     98     gLastResortCurrencyPat,
     99     gLastResortPercentPat,
    100     gLastResortScientificPat,
    101     gLastResortIsoCurrencyPat,
    102     gLastResortPluralCurrencyPat,
    103 };
    104 
    105 // *****************************************************************************
    106 // class NumberFormat
    107 // *****************************************************************************
    108 
    109 U_NAMESPACE_BEGIN
    110 
    111 UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(NumberFormat)
    112 
    113 #if !UCONFIG_NO_SERVICE
    114 // -------------------------------------
    115 // SimpleNumberFormatFactory implementation
    116 NumberFormatFactory::~NumberFormatFactory() {}
    117 SimpleNumberFormatFactory::SimpleNumberFormatFactory(const Locale& locale, UBool visible)
    118     : _visible(visible)
    119 {
    120     LocaleUtility::initNameFromLocale(locale, _id);
    121 }
    122 
    123 SimpleNumberFormatFactory::~SimpleNumberFormatFactory() {}
    124 
    125 UBool SimpleNumberFormatFactory::visible(void) const {
    126     return _visible;
    127 }
    128 
    129 const UnicodeString *
    130 SimpleNumberFormatFactory::getSupportedIDs(int32_t &count, UErrorCode& status) const
    131 {
    132     if (U_SUCCESS(status)) {
    133         count = 1;
    134         return &_id;
    135     }
    136     count = 0;
    137     return NULL;
    138 }
    139 #endif /* #if !UCONFIG_NO_SERVICE */
    140 
    141 // -------------------------------------
    142 // default constructor
    143 NumberFormat::NumberFormat()
    144 :   fGroupingUsed(TRUE),
    145     fMaxIntegerDigits(gMaxIntegerDigits),
    146     fMinIntegerDigits(1),
    147     fMaxFractionDigits(3), // invariant, >= minFractionDigits
    148     fMinFractionDigits(0),
    149     fParseIntegerOnly(FALSE)
    150 {
    151     fCurrency[0] = 0;
    152 }
    153 
    154 // -------------------------------------
    155 
    156 NumberFormat::~NumberFormat()
    157 {
    158 }
    159 
    160 // -------------------------------------
    161 // copy constructor
    162 
    163 NumberFormat::NumberFormat(const NumberFormat &source)
    164 :   Format(source)
    165 {
    166     *this = source;
    167 }
    168 
    169 // -------------------------------------
    170 // assignment operator
    171 
    172 NumberFormat&
    173 NumberFormat::operator=(const NumberFormat& rhs)
    174 {
    175     if (this != &rhs)
    176     {
    177         fGroupingUsed = rhs.fGroupingUsed;
    178         fMaxIntegerDigits = rhs.fMaxIntegerDigits;
    179         fMinIntegerDigits = rhs.fMinIntegerDigits;
    180         fMaxFractionDigits = rhs.fMaxFractionDigits;
    181         fMinFractionDigits = rhs.fMinFractionDigits;
    182         fParseIntegerOnly = rhs.fParseIntegerOnly;
    183         u_strncpy(fCurrency, rhs.fCurrency, 4);
    184     }
    185     return *this;
    186 }
    187 
    188 // -------------------------------------
    189 
    190 UBool
    191 NumberFormat::operator==(const Format& that) const
    192 {
    193     // Format::operator== guarantees this cast is safe
    194     NumberFormat* other = (NumberFormat*)&that;
    195 
    196 #ifdef FMT_DEBUG
    197     // This code makes it easy to determine why two format objects that should
    198     // be equal aren't.
    199     UBool first = TRUE;
    200     if (!Format::operator==(that)) {
    201         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
    202         debug("Format::!=");
    203     }
    204     if (!(fMaxIntegerDigits == other->fMaxIntegerDigits &&
    205           fMinIntegerDigits == other->fMinIntegerDigits)) {
    206         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
    207         debug("Integer digits !=");
    208     }
    209     if (!(fMaxFractionDigits == other->fMaxFractionDigits &&
    210           fMinFractionDigits == other->fMinFractionDigits)) {
    211         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
    212         debug("Fraction digits !=");
    213     }
    214     if (!(fGroupingUsed == other->fGroupingUsed)) {
    215         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
    216         debug("fGroupingUsed != ");
    217     }
    218     if (!(fParseIntegerOnly == other->fParseIntegerOnly)) {
    219         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
    220         debug("fParseIntegerOnly != ");
    221     }
    222     if (!(u_strcmp(fCurrency, other->fCurrency) == 0)) {
    223         if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
    224         debug("fCurrency !=");
    225     }
    226     if (!first) { printf(" ]"); }
    227 #endif
    228 
    229     return ((this == &that) ||
    230             ((Format::operator==(that) &&
    231               fMaxIntegerDigits == other->fMaxIntegerDigits &&
    232               fMinIntegerDigits == other->fMinIntegerDigits &&
    233               fMaxFractionDigits == other->fMaxFractionDigits &&
    234               fMinFractionDigits == other->fMinFractionDigits &&
    235               fGroupingUsed == other->fGroupingUsed &&
    236               fParseIntegerOnly == other->fParseIntegerOnly &&
    237               u_strcmp(fCurrency, other->fCurrency) == 0)));
    238 }
    239 
    240 // -------------------------------------x
    241 // Formats the number object and save the format
    242 // result in the toAppendTo string buffer.
    243 
    244 UnicodeString&
    245 NumberFormat::format(const Formattable& obj,
    246                         UnicodeString& appendTo,
    247                         FieldPosition& pos,
    248                         UErrorCode& status) const
    249 {
    250     if (U_FAILURE(status)) return appendTo;
    251 
    252     NumberFormat* nonconst = (NumberFormat*) this;
    253     const Formattable* n = &obj;
    254 
    255     UChar save[4];
    256     UBool setCurr = FALSE;
    257     const UObject* o = obj.getObject(); // most commonly o==NULL
    258     if (o != NULL &&
    259         o->getDynamicClassID() == CurrencyAmount::getStaticClassID()) {
    260         // getISOCurrency() returns a pointer to internal storage, so we
    261         // copy it to retain it across the call to setCurrency().
    262         const CurrencyAmount* amt = (const CurrencyAmount*) o;
    263         const UChar* curr = amt->getISOCurrency();
    264         u_strcpy(save, getCurrency());
    265         setCurr = (u_strcmp(curr, save) != 0);
    266         if (setCurr) {
    267             nonconst->setCurrency(curr, status);
    268         }
    269         n = &amt->getNumber();
    270     }
    271 
    272     switch (n->getType()) {
    273     case Formattable::kDouble:
    274         format(n->getDouble(), appendTo, pos);
    275         break;
    276     case Formattable::kLong:
    277         format(n->getLong(), appendTo, pos);
    278         break;
    279     case Formattable::kInt64:
    280         format(n->getInt64(), appendTo, pos);
    281         break;
    282     default:
    283         status = U_INVALID_FORMAT_ERROR;
    284         break;
    285     }
    286 
    287     if (setCurr) {
    288         UErrorCode ok = U_ZERO_ERROR;
    289         nonconst->setCurrency(save, ok); // always restore currency
    290     }
    291     return appendTo;
    292 }
    293 
    294 // -------------------------------------
    295 
    296 UnicodeString&
    297 NumberFormat::format(int64_t number,
    298                      UnicodeString& appendTo,
    299                      FieldPosition& pos) const
    300 {
    301     // default so we don't introduce a new abstract method
    302     return format((int32_t)number, appendTo, pos);
    303 }
    304 
    305 // -------------------------------------
    306 // Parses the string and save the result object as well
    307 // as the final parsed position.
    308 
    309 void
    310 NumberFormat::parseObject(const UnicodeString& source,
    311                              Formattable& result,
    312                              ParsePosition& parse_pos) const
    313 {
    314     parse(source, result, parse_pos);
    315 }
    316 
    317 // -------------------------------------
    318 // Formats a double number and save the result in a string.
    319 
    320 UnicodeString&
    321 NumberFormat::format(double number, UnicodeString& appendTo) const
    322 {
    323     FieldPosition pos(0);
    324     return format(number, appendTo, pos);
    325 }
    326 
    327 // -------------------------------------
    328 // Formats a long number and save the result in a string.
    329 
    330 UnicodeString&
    331 NumberFormat::format(int32_t number, UnicodeString& appendTo) const
    332 {
    333     FieldPosition pos(0);
    334     return format(number, appendTo, pos);
    335 }
    336 
    337 // -------------------------------------
    338 // Formats a long number and save the result in a string.
    339 
    340 UnicodeString&
    341 NumberFormat::format(int64_t number, UnicodeString& appendTo) const
    342 {
    343     FieldPosition pos(0);
    344     return format(number, appendTo, pos);
    345 }
    346 
    347 // -------------------------------------
    348 // Parses the text and save the result object.  If the returned
    349 // parse position is 0, that means the parsing failed, the status
    350 // code needs to be set to failure.  Ignores the returned parse
    351 // position, otherwise.
    352 
    353 void
    354 NumberFormat::parse(const UnicodeString& text,
    355                         Formattable& result,
    356                         UErrorCode& status) const
    357 {
    358     if (U_FAILURE(status)) return;
    359 
    360     ParsePosition parsePosition(0);
    361     parse(text, result, parsePosition);
    362     if (parsePosition.getIndex() == 0) {
    363         status = U_INVALID_FORMAT_ERROR;
    364     }
    365 }
    366 
    367 Formattable& NumberFormat::parseCurrency(const UnicodeString& text,
    368                                          Formattable& result,
    369                                          ParsePosition& pos) const {
    370     // Default implementation only -- subclasses should override
    371     int32_t start = pos.getIndex();
    372     parse(text, result, pos);
    373     if (pos.getIndex() != start) {
    374         UChar curr[4];
    375         UErrorCode ec = U_ZERO_ERROR;
    376         getEffectiveCurrency(curr, ec);
    377         if (U_SUCCESS(ec)) {
    378             Formattable n(result);
    379             CurrencyAmount *tempCurAmnt = new CurrencyAmount(n, curr, ec);  // Use for null testing.
    380             if (U_FAILURE(ec) || tempCurAmnt == NULL) {
    381                 pos.setIndex(start); // indicate failure
    382             } else {
    383             	result.adoptObject(tempCurAmnt);
    384             }
    385         }
    386     }
    387     return result;
    388 }
    389 
    390 // -------------------------------------
    391 // Sets to only parse integers.
    392 
    393 void
    394 NumberFormat::setParseIntegerOnly(UBool value)
    395 {
    396     fParseIntegerOnly = value;
    397 }
    398 
    399 // -------------------------------------
    400 // Create a number style NumberFormat instance with the default locale.
    401 
    402 NumberFormat* U_EXPORT2
    403 NumberFormat::createInstance(UErrorCode& status)
    404 {
    405     return createInstance(Locale::getDefault(), kNumberStyle, status);
    406 }
    407 
    408 // -------------------------------------
    409 // Create a number style NumberFormat instance with the inLocale locale.
    410 
    411 NumberFormat* U_EXPORT2
    412 NumberFormat::createInstance(const Locale& inLocale, UErrorCode& status)
    413 {
    414     return createInstance(inLocale, kNumberStyle, status);
    415 }
    416 
    417 // -------------------------------------
    418 // Create a currency style NumberFormat instance with the default locale.
    419 
    420 NumberFormat* U_EXPORT2
    421 NumberFormat::createCurrencyInstance(UErrorCode& status)
    422 {
    423     return createCurrencyInstance(Locale::getDefault(),  status);
    424 }
    425 
    426 // -------------------------------------
    427 // Create a currency style NumberFormat instance with the inLocale locale.
    428 
    429 NumberFormat* U_EXPORT2
    430 NumberFormat::createCurrencyInstance(const Locale& inLocale, UErrorCode& status)
    431 {
    432     return createInstance(inLocale, kCurrencyStyle, status);
    433 }
    434 
    435 // -------------------------------------
    436 // Create a percent style NumberFormat instance with the default locale.
    437 
    438 NumberFormat* U_EXPORT2
    439 NumberFormat::createPercentInstance(UErrorCode& status)
    440 {
    441     return createInstance(Locale::getDefault(), kPercentStyle, status);
    442 }
    443 
    444 // -------------------------------------
    445 // Create a percent style NumberFormat instance with the inLocale locale.
    446 
    447 NumberFormat* U_EXPORT2
    448 NumberFormat::createPercentInstance(const Locale& inLocale, UErrorCode& status)
    449 {
    450     return createInstance(inLocale, kPercentStyle, status);
    451 }
    452 
    453 // -------------------------------------
    454 // Create a scientific style NumberFormat instance with the default locale.
    455 
    456 NumberFormat* U_EXPORT2
    457 NumberFormat::createScientificInstance(UErrorCode& status)
    458 {
    459     return createInstance(Locale::getDefault(), kScientificStyle, status);
    460 }
    461 
    462 // -------------------------------------
    463 // Create a scientific style NumberFormat instance with the inLocale locale.
    464 
    465 NumberFormat* U_EXPORT2
    466 NumberFormat::createScientificInstance(const Locale& inLocale, UErrorCode& status)
    467 {
    468     return createInstance(inLocale, kScientificStyle, status);
    469 }
    470 
    471 // -------------------------------------
    472 
    473 const Locale* U_EXPORT2
    474 NumberFormat::getAvailableLocales(int32_t& count)
    475 {
    476     return Locale::getAvailableLocales(count);
    477 }
    478 
    479 // ------------------------------------------
    480 //
    481 // Registration
    482 //
    483 //-------------------------------------------
    484 
    485 #if !UCONFIG_NO_SERVICE
    486 static ICULocaleService* gService = NULL;
    487 
    488 /**
    489  * Release all static memory held by numberformat.
    490  */
    491 U_CDECL_BEGIN
    492 static UBool U_CALLCONV numfmt_cleanup(void) {
    493     if (gService) {
    494         delete gService;
    495         gService = NULL;
    496     }
    497     return TRUE;
    498 }
    499 U_CDECL_END
    500 
    501 // -------------------------------------
    502 
    503 class ICUNumberFormatFactory : public ICUResourceBundleFactory {
    504 protected:
    505     virtual UObject* handleCreate(const Locale& loc, int32_t kind, const ICUService* /* service */, UErrorCode& status) const {
    506         // !!! kind is not an EStyles, need to determine how to handle this
    507         return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
    508     }
    509 };
    510 
    511 // -------------------------------------
    512 
    513 class NFFactory : public LocaleKeyFactory {
    514 private:
    515     NumberFormatFactory* _delegate;
    516     Hashtable* _ids;
    517 
    518 public:
    519     NFFactory(NumberFormatFactory* delegate)
    520         : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
    521         , _delegate(delegate)
    522         , _ids(NULL)
    523     {
    524     }
    525 
    526     virtual ~NFFactory()
    527     {
    528         delete _delegate;
    529         delete _ids;
    530     }
    531 
    532     virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const
    533     {
    534         if (handlesKey(key, status)) {
    535             const LocaleKey& lkey = (const LocaleKey&)key;
    536             Locale loc;
    537             lkey.canonicalLocale(loc);
    538             int32_t kind = lkey.kind();
    539 
    540             UObject* result = _delegate->createFormat(loc, (UNumberFormatStyle)(kind+1));
    541             if (result == NULL) {
    542                 result = service->getKey((ICUServiceKey&)key /* cast away const */, NULL, this, status);
    543             }
    544             return result;
    545         }
    546         return NULL;
    547     }
    548 
    549 protected:
    550     /**
    551      * Return the set of ids that this factory supports (visible or
    552      * otherwise).  This can be called often and might need to be
    553      * cached if it is expensive to create.
    554      */
    555     virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
    556     {
    557         if (U_SUCCESS(status)) {
    558             if (!_ids) {
    559                 int32_t count = 0;
    560                 const UnicodeString * const idlist = _delegate->getSupportedIDs(count, status);
    561                 ((NFFactory*)this)->_ids = new Hashtable(status); /* cast away const */
    562                 if (_ids) {
    563                     for (int i = 0; i < count; ++i) {
    564                         _ids->put(idlist[i], (void*)this, status);
    565                     }
    566                 }
    567             }
    568             return _ids;
    569         }
    570         return NULL;
    571     }
    572 };
    573 
    574 class ICUNumberFormatService : public ICULocaleService {
    575 public:
    576     ICUNumberFormatService()
    577         : ICULocaleService(UNICODE_STRING_SIMPLE("Number Format"))
    578     {
    579         UErrorCode status = U_ZERO_ERROR;
    580         registerFactory(new ICUNumberFormatFactory(), status);
    581     }
    582 
    583     virtual UObject* cloneInstance(UObject* instance) const {
    584         return ((NumberFormat*)instance)->clone();
    585     }
    586 
    587     virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* /* actualID */, UErrorCode& status) const {
    588         LocaleKey& lkey = (LocaleKey&)key;
    589         int32_t kind = lkey.kind();
    590         Locale loc;
    591         lkey.currentLocale(loc);
    592         return NumberFormat::makeInstance(loc, (NumberFormat::EStyles)kind, status);
    593     }
    594 
    595     virtual UBool isDefault() const {
    596         return countFactories() == 1;
    597     }
    598 };
    599 
    600 // -------------------------------------
    601 
    602 static ICULocaleService*
    603 getNumberFormatService(void)
    604 {
    605     UBool needInit;
    606     UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
    607     if (needInit) {
    608         ICULocaleService * newservice = new ICUNumberFormatService();
    609         if (newservice) {
    610             umtx_lock(NULL);
    611             if (gService == NULL) {
    612                 gService = newservice;
    613                 newservice = NULL;
    614             }
    615             umtx_unlock(NULL);
    616         }
    617         if (newservice) {
    618             delete newservice;
    619         } else {
    620             // we won the contention, this thread can register cleanup.
    621             ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
    622         }
    623     }
    624     return gService;
    625 }
    626 
    627 // -------------------------------------
    628 
    629 URegistryKey U_EXPORT2
    630 NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
    631 {
    632   ICULocaleService *service = getNumberFormatService();
    633   if (service) {
    634 	  NFFactory *tempnnf = new NFFactory(toAdopt);
    635 	  if (tempnnf != NULL) {
    636 		  return service->registerFactory(tempnnf, status);
    637 	  }
    638   }
    639   status = U_MEMORY_ALLOCATION_ERROR;
    640   return NULL;
    641 }
    642 
    643 // -------------------------------------
    644 
    645 UBool U_EXPORT2
    646 NumberFormat::unregister(URegistryKey key, UErrorCode& status)
    647 {
    648     if (U_SUCCESS(status)) {
    649         UBool haveService;
    650         UMTX_CHECK(NULL, gService != NULL, haveService);
    651         if (haveService) {
    652             return gService->unregister(key, status);
    653         }
    654         status = U_ILLEGAL_ARGUMENT_ERROR;
    655     }
    656     return FALSE;
    657 }
    658 
    659 // -------------------------------------
    660 StringEnumeration* U_EXPORT2
    661 NumberFormat::getAvailableLocales(void)
    662 {
    663   ICULocaleService *service = getNumberFormatService();
    664   if (service) {
    665     return service->getAvailableLocales();
    666   }
    667   return NULL; // no way to return error condition
    668 }
    669 #endif /* UCONFIG_NO_SERVICE */
    670 // -------------------------------------
    671 
    672 NumberFormat* U_EXPORT2
    673 NumberFormat::createInstance(const Locale& loc, EStyles kind, UErrorCode& status)
    674 {
    675 #if !UCONFIG_NO_SERVICE
    676     UBool haveService;
    677     UMTX_CHECK(NULL, gService != NULL, haveService);
    678     if (haveService) {
    679         return (NumberFormat*)gService->get(loc, kind, status);
    680     }
    681     else
    682 #endif
    683     {
    684         return makeInstance(loc, kind, status);
    685     }
    686 }
    687 
    688 
    689 // -------------------------------------
    690 // Checks if the thousand/10 thousand grouping is used in the
    691 // NumberFormat instance.
    692 
    693 UBool
    694 NumberFormat::isGroupingUsed() const
    695 {
    696     return fGroupingUsed;
    697 }
    698 
    699 // -------------------------------------
    700 // Sets to use the thousand/10 thousand grouping in the
    701 // NumberFormat instance.
    702 
    703 void
    704 NumberFormat::setGroupingUsed(UBool newValue)
    705 {
    706     fGroupingUsed = newValue;
    707 }
    708 
    709 // -------------------------------------
    710 // Gets the maximum number of digits for the integral part for
    711 // this NumberFormat instance.
    712 
    713 int32_t NumberFormat::getMaximumIntegerDigits() const
    714 {
    715     return fMaxIntegerDigits;
    716 }
    717 
    718 // -------------------------------------
    719 // Sets the maximum number of digits for the integral part for
    720 // this NumberFormat instance.
    721 
    722 void
    723 NumberFormat::setMaximumIntegerDigits(int32_t newValue)
    724 {
    725     fMaxIntegerDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
    726     if(fMinIntegerDigits > fMaxIntegerDigits)
    727         fMinIntegerDigits = fMaxIntegerDigits;
    728 }
    729 
    730 // -------------------------------------
    731 // Gets the minimum number of digits for the integral part for
    732 // this NumberFormat instance.
    733 
    734 int32_t
    735 NumberFormat::getMinimumIntegerDigits() const
    736 {
    737     return fMinIntegerDigits;
    738 }
    739 
    740 // -------------------------------------
    741 // Sets the minimum number of digits for the integral part for
    742 // this NumberFormat instance.
    743 
    744 void
    745 NumberFormat::setMinimumIntegerDigits(int32_t newValue)
    746 {
    747     fMinIntegerDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
    748     if(fMinIntegerDigits > fMaxIntegerDigits)
    749         fMaxIntegerDigits = fMinIntegerDigits;
    750 }
    751 
    752 // -------------------------------------
    753 // Gets the maximum number of digits for the fractional part for
    754 // this NumberFormat instance.
    755 
    756 int32_t
    757 NumberFormat::getMaximumFractionDigits() const
    758 {
    759     return fMaxFractionDigits;
    760 }
    761 
    762 // -------------------------------------
    763 // Sets the maximum number of digits for the fractional part for
    764 // this NumberFormat instance.
    765 
    766 void
    767 NumberFormat::setMaximumFractionDigits(int32_t newValue)
    768 {
    769     fMaxFractionDigits = uprv_max(0, uprv_min(newValue, gMaxIntegerDigits));
    770     if(fMaxFractionDigits < fMinFractionDigits)
    771         fMinFractionDigits = fMaxFractionDigits;
    772 }
    773 
    774 // -------------------------------------
    775 // Gets the minimum number of digits for the fractional part for
    776 // this NumberFormat instance.
    777 
    778 int32_t
    779 NumberFormat::getMinimumFractionDigits() const
    780 {
    781     return fMinFractionDigits;
    782 }
    783 
    784 // -------------------------------------
    785 // Sets the minimum number of digits for the fractional part for
    786 // this NumberFormat instance.
    787 
    788 void
    789 NumberFormat::setMinimumFractionDigits(int32_t newValue)
    790 {
    791     fMinFractionDigits = uprv_max(0, uprv_min(newValue, gMinIntegerDigits));
    792     if (fMaxFractionDigits < fMinFractionDigits)
    793         fMaxFractionDigits = fMinFractionDigits;
    794 }
    795 
    796 // -------------------------------------
    797 
    798 void NumberFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
    799     if (U_FAILURE(ec)) {
    800         return;
    801     }
    802     if (theCurrency) {
    803         u_strncpy(fCurrency, theCurrency, 3);
    804         fCurrency[3] = 0;
    805     } else {
    806         fCurrency[0] = 0;
    807     }
    808 }
    809 
    810 const UChar* NumberFormat::getCurrency() const {
    811     return fCurrency;
    812 }
    813 
    814 void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
    815     const UChar* c = getCurrency();
    816     if (*c != 0) {
    817         u_strncpy(result, c, 3);
    818         result[3] = 0;
    819     } else {
    820         const char* loc = getLocaleID(ULOC_VALID_LOCALE, ec);
    821         if (loc == NULL) {
    822             loc = uloc_getDefault();
    823         }
    824         ucurr_forLocale(loc, result, 4, &ec);
    825     }
    826 }
    827 
    828 // -------------------------------------
    829 // Creates the NumberFormat instance of the specified style (number, currency,
    830 // or percent) for the desired locale.
    831 
    832 NumberFormat*
    833 NumberFormat::makeInstance(const Locale& desiredLocale,
    834                            EStyles style,
    835                            UErrorCode& status)
    836 {
    837     if (U_FAILURE(status)) return NULL;
    838 
    839     if (style < 0 || style >= kStyleCount) {
    840         status = U_ILLEGAL_ARGUMENT_ERROR;
    841         return NULL;
    842     }
    843 
    844 #ifdef U_WINDOWS
    845     char buffer[8];
    846     int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);
    847 
    848     // if the locale has "@compat=host", create a host-specific NumberFormat
    849     if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
    850         Win32NumberFormat *f = NULL;
    851         UBool curr = TRUE;
    852 
    853         switch (style) {
    854         case kNumberStyle:
    855             curr = FALSE;
    856             // fall-through
    857 
    858         case kCurrencyStyle:
    859         case kIsoCurrencyStyle: // do not support plural formatting here
    860         case kPluralCurrencyStyle:
    861             f = new Win32NumberFormat(desiredLocale, curr, status);
    862 
    863             if (U_SUCCESS(status)) {
    864                 return f;
    865             }
    866 
    867             delete f;
    868             break;
    869 
    870         default:
    871             break;
    872         }
    873     }
    874 #endif
    875 
    876     NumberFormat* f = NULL;
    877     DecimalFormatSymbols* symbolsToAdopt = NULL;
    878     UnicodeString pattern;
    879     UResourceBundle *resource = ures_open((char *)0, desiredLocale.getName(), &status);
    880     UResourceBundle *numberPatterns = ures_getByKey(resource, DecimalFormat::fgNumberPatterns, NULL, &status);
    881     NumberingSystem *ns = NULL;
    882     UBool deleteSymbols = TRUE;
    883 
    884     if (U_FAILURE(status)) {
    885         // We don't appear to have resource data available -- use the last-resort data
    886         status = U_USING_FALLBACK_WARNING;
    887         // When the data is unavailable, and locale isn't passed in, last resort data is used.
    888         symbolsToAdopt = new DecimalFormatSymbols(status);
    889 
    890         // Creates a DecimalFormat instance with the last resort number patterns.
    891         pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1);
    892     }
    893     else {
    894         // If not all the styled patterns exists for the NumberFormat in this locale,
    895         // sets the status code to failure and returns nil.
    896         if (ures_getSize(numberPatterns) < (int32_t)(sizeof(gLastResortNumberPatterns)/sizeof(gLastResortNumberPatterns[0])) -2 ) { //minus 2: ISO and plural
    897             status = U_INVALID_FORMAT_ERROR;
    898             goto cleanup;
    899         }
    900 
    901         // Loads the decimal symbols of the desired locale.
    902         symbolsToAdopt = new DecimalFormatSymbols(desiredLocale, status);
    903 
    904         int32_t patLen = 0;
    905 
    906         /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
    907          * the pattern is the same as the pattern of CURRENCYSTYLE
    908          * but by replacing the single currency sign with
    909          * double currency sign or triple currency sign.
    910          */
    911         int styleInNumberPattern = ((style == kIsoCurrencyStyle ||
    912                                      style == kPluralCurrencyStyle) ?
    913                                     kCurrencyStyle : style);
    914 
    915         const UChar *patResStr = ures_getStringByIndex(numberPatterns, (int32_t)styleInNumberPattern, &patLen, &status);
    916 
    917         // Creates the specified decimal format style of the desired locale.
    918         pattern.setTo(TRUE, patResStr, patLen);
    919     }
    920     if (U_FAILURE(status) || symbolsToAdopt == NULL) {
    921         goto cleanup;
    922     }
    923     if(style==kCurrencyStyle || style == kIsoCurrencyStyle){
    924         const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
    925         if(currPattern!=NULL){
    926             pattern.setTo(currPattern, u_strlen(currPattern));
    927         }
    928     }
    929 
    930     ns = NumberingSystem::createInstance(desiredLocale,status);
    931 
    932     if (U_FAILURE(status)) {
    933         goto cleanup;
    934     }
    935 
    936     if (ns->isAlgorithmic()) {
    937         UnicodeString nsDesc;
    938         UnicodeString nsRuleSetGroup;
    939         UnicodeString nsRuleSetName;
    940         Locale nsLoc;
    941         URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;
    942 
    943         nsDesc.setTo(ns->getDescription());
    944         int32_t firstSlash = nsDesc.indexOf(gSlash);
    945         int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
    946         if ( lastSlash > firstSlash ) {
    947             char nsLocID[ULOC_FULLNAME_CAPACITY];
    948 
    949             nsDesc.extract(0,firstSlash,nsLocID,ULOC_FULLNAME_CAPACITY,US_INV);
    950             nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
    951             nsRuleSetName.setTo(nsDesc,lastSlash+1);
    952 
    953             nsLoc = Locale::createFromName(nsLocID);
    954 
    955             UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
    956             if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
    957                 desiredRulesType = URBNF_SPELLOUT;
    958             }
    959         } else {
    960             nsLoc = desiredLocale;
    961             nsRuleSetName.setTo(nsDesc);
    962         }
    963 
    964         RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
    965 
    966         if (U_FAILURE(status) || r == NULL) {
    967             goto cleanup;
    968         }
    969         r->setDefaultRuleSet(nsRuleSetName,status);
    970         f = (NumberFormat *) r;
    971 
    972     } else {
    973         // replace single currency sign in the pattern with double currency sign
    974         // if the style is kIsoCurrencyStyle
    975         if (style == kIsoCurrencyStyle) {
    976             pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign);
    977         }
    978 
    979         f = new DecimalFormat(pattern, symbolsToAdopt, style, status);
    980         if (U_FAILURE(status) || f == NULL) {
    981             goto cleanup;
    982         }
    983         deleteSymbols = FALSE;
    984     }
    985 
    986     f->setLocaleIDs(ures_getLocaleByType(numberPatterns, ULOC_VALID_LOCALE, &status),
    987                     ures_getLocaleByType(numberPatterns, ULOC_ACTUAL_LOCALE, &status));
    988 
    989 cleanup:
    990     ures_close(numberPatterns);
    991     ures_close(resource);
    992     if (ns) {
    993        delete ns;
    994     }
    995     if (U_FAILURE(status)) {
    996         /* If f exists, then it will delete the symbols */
    997         if (f==NULL) {
    998             delete symbolsToAdopt;
    999         }
   1000         else {
   1001             delete f;
   1002         }
   1003         return NULL;
   1004     }
   1005     if (f == NULL || symbolsToAdopt == NULL) {
   1006         status = U_MEMORY_ALLOCATION_ERROR;
   1007         f = NULL;
   1008     }
   1009     if (deleteSymbols && symbolsToAdopt != NULL) {
   1010         delete symbolsToAdopt;
   1011     }
   1012     return f;
   1013 }
   1014 
   1015 U_NAMESPACE_END
   1016 
   1017 #endif /* #if !UCONFIG_NO_FORMATTING */
   1018 
   1019 //eof
   1020