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