Index: source/i18n/numfmt.cpp |
diff --git a/source/i18n/numfmt.cpp b/source/i18n/numfmt.cpp |
index da09207e87dea258e4c54038790cd80989c2e220..ed4239650cca738437dceda48389fb47ca6e41fa 100644 |
--- a/source/i18n/numfmt.cpp |
+++ b/source/i18n/numfmt.cpp |
@@ -1,6 +1,6 @@ |
/* |
******************************************************************************* |
-* Copyright (C) 1997-2013, International Business Machines Corporation and |
+* Copyright (C) 1997-2014, International Business Machines Corporation and |
* others. All Rights Reserved. |
******************************************************************************* |
* |
@@ -36,6 +36,7 @@ |
#include "unicode/numsys.h" |
#include "unicode/rbnf.h" |
#include "unicode/localpointer.h" |
+#include "unicode/udisplaycontext.h" |
#include "charstr.h" |
#include "winnmfmt.h" |
#include "uresimp.h" |
@@ -50,6 +51,8 @@ |
#include "mutex.h" |
#include "digitlst.h" |
#include <float.h> |
+#include "sharednumberformat.h" |
+#include "unifiedcache.h" |
//#define FMT_DEBUG |
@@ -67,24 +70,27 @@ static inline void debugout(UnicodeString s) { |
#endif |
// If no number pattern can be located for a locale, this is the last |
-// resort. |
+// resort. The patterns are same as the ones in root locale. |
static const UChar gLastResortDecimalPat[] = { |
- 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x3B, 0x2D, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#0.###;-#0.###" */ |
+ 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0 /* "#,##0.###" */ |
}; |
static const UChar gLastResortCurrencyPat[] = { |
- 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x3B, 0x28, 0x24, 0x23, 0x30, 0x2E, 0x30, 0x30, 0x29, 0 /* "$#0.00;($#0.00)" */ |
+ 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */ |
}; |
static const UChar gLastResortPercentPat[] = { |
- 0x23, 0x30, 0x25, 0 /* "#0%" */ |
+ 0x23, 0x2C, 0x23, 0x23, 0x30, 0x25, 0 /* "#,##0%" */ |
}; |
static const UChar gLastResortScientificPat[] = { |
0x23, 0x45, 0x30, 0 /* "#E0" */ |
}; |
static const UChar gLastResortIsoCurrencyPat[] = { |
- 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)" */ |
+ 0xA4, 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A4\u00A0#,##0.00" */ |
}; |
static const UChar gLastResortPluralCurrencyPat[] = { |
- 0x23, 0x30, 0x2E, 0x30, 0x30, 0xA0, 0xA4, 0xA4, 0xA4, 0 /* "#0.00\u00A0\u00A4\u00A4\u00A4*/ |
+ 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x23, 0x23, 0x23, 0x20, 0xA4, 0xA4, 0xA4, 0 /* "#,##0.### \u00A4\u00A4\u00A4*/ |
+}; |
+static const UChar gLastResortAccountingCurrencyPat[] = { |
+ 0xA4, 0xA0, 0x23, 0x2C, 0x23, 0x23, 0x30, 0x2E, 0x30, 0x30, 0 /* "\u00A4\u00A0#,##0.00" */ |
}; |
static const UChar gSingleCurrencySign[] = {0xA4, 0}; |
@@ -111,7 +117,9 @@ static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = |
NULL, // UNUM_NUMBERING_SYSTEM |
NULL, // UNUM_PATTERN_RULEBASED |
gLastResortIsoCurrencyPat, // UNUM_CURRENCY_ISO |
- gLastResortPluralCurrencyPat // UNUM_CURRENCY_PLURAL |
+ gLastResortPluralCurrencyPat, // UNUM_CURRENCY_PLURAL |
+ gLastResortAccountingCurrencyPat, // UNUM_CURRENCY_ACCOUNTING |
+ gLastResortCurrencyPat, // UNUM_CASH_CURRENCY |
}; |
// Keys used for accessing resource bundles |
@@ -135,7 +143,9 @@ static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = { |
// except for replacing the single currency sign with |
// double currency sign or triple currency sign. |
"currencyFormat", // UNUM_CURRENCY_ISO |
- "currencyFormat" // UNUM_CURRENCY_PLURAL |
+ "currencyFormat", // UNUM_CURRENCY_PLURAL |
+ "accountingFormat", // UNUM_CURRENCY_ACCOUNTING |
+ "currencyFormat" // UNUM_CASH_CURRENCY |
}; |
// Static hashtable cache of NumberingSystem objects used by NumberFormat |
@@ -171,7 +181,6 @@ static UBool U_CALLCONV numfmt_cleanup(void) { |
uhash_close(NumberingSystem_cache); |
NumberingSystem_cache = NULL; |
} |
- |
return TRUE; |
} |
U_CDECL_END |
@@ -221,7 +230,8 @@ NumberFormat::NumberFormat() |
fMaxFractionDigits(3), // invariant, >= minFractionDigits |
fMinFractionDigits(0), |
fParseIntegerOnly(FALSE), |
- fLenient(FALSE) |
+ fLenient(FALSE), |
+ fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE) |
{ |
fCurrency[0] = 0; |
} |
@@ -232,6 +242,10 @@ NumberFormat::~NumberFormat() |
{ |
} |
+SharedNumberFormat::~SharedNumberFormat() { |
+ delete ptr; |
+} |
+ |
// ------------------------------------- |
// copy constructor |
@@ -258,6 +272,7 @@ NumberFormat::operator=(const NumberFormat& rhs) |
fParseIntegerOnly = rhs.fParseIntegerOnly; |
u_strncpy(fCurrency, rhs.fCurrency, 4); |
fLenient = rhs.fLenient; |
+ fCapitalizationContext = rhs.fCapitalizationContext; |
} |
return *this; |
} |
@@ -304,6 +319,10 @@ NumberFormat::operator==(const Format& that) const |
if (first) { printf("[ "); first = FALSE; } else { printf(", "); } |
debug("fLenient != "); |
} |
+ if (!(fCapitalizationContext == other->fCapitalizationContext)) { |
+ if (first) { printf("[ "); first = FALSE; } else { printf(", "); } |
+ debug("fCapitalizationContext != "); |
+ } |
if (!first) { printf(" ]"); } |
#endif |
@@ -316,7 +335,8 @@ NumberFormat::operator==(const Format& that) const |
fGroupingUsed == other->fGroupingUsed && |
fParseIntegerOnly == other->fParseIntegerOnly && |
u_strcmp(fCurrency, other->fCurrency) == 0 && |
- fLenient == other->fLenient))); |
+ fLenient == other->fLenient && |
+ fCapitalizationContext == other->fCapitalizationContext))); |
} |
// ------------------------------------- |
@@ -1000,8 +1020,8 @@ NumberFormat::getAvailableLocales(void) |
#endif /* UCONFIG_NO_SERVICE */ |
// ------------------------------------- |
-NumberFormat* U_EXPORT2 |
-NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { |
+NumberFormat* |
+NumberFormat::internalCreateInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { |
#if !UCONFIG_NO_SERVICE |
if (haveService()) { |
return (NumberFormat*)gService->get(loc, kind, status); |
@@ -1010,6 +1030,23 @@ NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorC |
return makeInstance(loc, kind, status); |
} |
+NumberFormat* U_EXPORT2 |
+NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { |
+ if (kind != UNUM_DECIMAL) { |
+ return internalCreateInstance(loc, kind, status); |
+ } |
+ const SharedNumberFormat *shared = createSharedInstance(loc, kind, status); |
+ if (U_FAILURE(status)) { |
+ return NULL; |
+ } |
+ NumberFormat *result = static_cast<NumberFormat *>((*shared)->clone()); |
+ shared->removeRef(); |
+ if (result == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ } |
+ return result; |
+} |
+ |
// ------------------------------------- |
// Checks if the thousand/10 thousand grouping is used in the |
@@ -1150,6 +1187,33 @@ void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { |
} |
} |
+//---------------------------------------------------------------------- |
+ |
+ |
+void NumberFormat::setContext(UDisplayContext value, UErrorCode& status) |
+{ |
+ if (U_FAILURE(status)) |
+ return; |
+ if ( (UDisplayContextType)((uint32_t)value >> 8) == UDISPCTX_TYPE_CAPITALIZATION ) { |
+ fCapitalizationContext = value; |
+ } else { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+} |
+ |
+ |
+UDisplayContext NumberFormat::getContext(UDisplayContextType type, UErrorCode& status) const |
+{ |
+ if (U_FAILURE(status)) |
+ return (UDisplayContext)0; |
+ if (type != UDISPCTX_TYPE_CAPITALIZATION) { |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ return (UDisplayContext)0; |
+ } |
+ return fCapitalizationContext; |
+} |
+ |
+ |
// ------------------------------------- |
// Creates the NumberFormat instance of the specified style (number, currency, |
// or percent) for the desired locale. |
@@ -1170,6 +1234,39 @@ static void U_CALLCONV nscacheInit() { |
uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem); |
} |
+template<> U_I18N_API |
+const SharedNumberFormat *LocaleCacheKey<SharedNumberFormat>::createObject( |
+ const void * /*unused*/, UErrorCode &status) const { |
+ const char *localeId = fLoc.getName(); |
+ NumberFormat *nf = NumberFormat::internalCreateInstance( |
+ localeId, UNUM_DECIMAL, status); |
+ if (U_FAILURE(status)) { |
+ return NULL; |
+ } |
+ SharedNumberFormat *result = new SharedNumberFormat(nf); |
+ if (result == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ delete nf; |
+ return NULL; |
+ } |
+ result->addRef(); |
+ return result; |
+} |
+ |
+const SharedNumberFormat* U_EXPORT2 |
+NumberFormat::createSharedInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) { |
+ if (U_FAILURE(status)) { |
+ return NULL; |
+ } |
+ if (kind != UNUM_DECIMAL) { |
+ status = U_UNSUPPORTED_ERROR; |
+ return NULL; |
+ } |
+ const SharedNumberFormat *result = NULL; |
+ UnifiedCache::getByLocale(loc, result, status); |
+ return result; |
+} |
+ |
UBool |
NumberFormat::isStyleSupported(UNumberFormatStyle style) { |
return gLastResortNumberPatterns[style] != NULL; |
@@ -1223,6 +1320,8 @@ NumberFormat::makeInstance(const Locale& desiredLocale, |
case UNUM_CURRENCY: |
case UNUM_CURRENCY_ISO: // do not support plural formatting here |
case UNUM_CURRENCY_PLURAL: |
+ case UNUM_CURRENCY_ACCOUNTING: |
+ case UNUM_CASH_CURRENCY: |
f = new Win32NumberFormat(desiredLocale, curr, status); |
if (U_SUCCESS(status)) { |
@@ -1272,17 +1371,7 @@ NumberFormat::makeInstance(const Locale& desiredLocale, |
UnicodeString pattern; |
LocalUResourceBundlePointer ownedResource(ures_open(NULL, desiredLocale.getName(), &status)); |
if (U_FAILURE(status)) { |
- // We don't appear to have resource data available -- use the last-resort data |
- status = U_USING_FALLBACK_WARNING; |
- // When the data is unavailable, and locale isn't passed in, last resort data is used. |
- symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(status)); |
- if (symbolsToAdopt.isNull()) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return NULL; |
- } |
- |
- // Creates a DecimalFormat instance with the last resort number patterns. |
- pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1); |
+ return NULL; |
} |
else { |
// Loads the decimal symbols of the desired locale. |
@@ -1317,7 +1406,8 @@ NumberFormat::makeInstance(const Locale& desiredLocale, |
if (U_FAILURE(status)) { |
return NULL; |
} |
- if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO){ |
+ if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO || style == UNUM_CURRENCY_ACCOUNTING |
+ || style == UNUM_CASH_CURRENCY){ |
const UChar* currPattern = symbolsToAdopt->getCurrencyPattern(); |
if(currPattern!=NULL){ |
pattern.setTo(currPattern, u_strlen(currPattern)); |
@@ -1371,7 +1461,19 @@ NumberFormat::makeInstance(const Locale& desiredLocale, |
// "new DecimalFormat()" does not adopt the symbols if its memory allocation fails. |
DecimalFormatSymbols *syms = symbolsToAdopt.orphan(); |
- f = new DecimalFormat(pattern, syms, style, status); |
+ DecimalFormat* df = new DecimalFormat(pattern, syms, style, status); |
+ |
+ // if it is cash currency style, setCurrencyUsage with usage |
+ if (style == UNUM_CASH_CURRENCY){ |
+ df->setCurrencyUsage(UCURR_USAGE_CASH, &status); |
+ } |
+ |
+ if (U_FAILURE(status)) { |
+ delete df; |
+ return NULL; |
+ } |
+ |
+ f = df; |
if (f == NULL) { |
delete syms; |
status = U_MEMORY_ALLOCATION_ERROR; |