Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: source/i18n/decimfmt.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « source/i18n/decimalformatpatternimpl.h ('k') | source/i18n/decimfmtimpl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: source/i18n/decimfmt.cpp
diff --git a/source/i18n/decimfmt.cpp b/source/i18n/decimfmt.cpp
index 825651be08abf5f8f54ba8c3f6065b818813f6a3..9518ef581c7cff907edf9a833a333f80c30adbdf 100644
--- a/source/i18n/decimfmt.cpp
+++ b/source/i18n/decimfmt.cpp
@@ -1,6 +1,6 @@
/*
*******************************************************************************
-* Copyright (C) 1997-2014, International Business Machines Corporation and *
+* Copyright (C) 1997-2015, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@@ -41,16 +41,7 @@
#if !UCONFIG_NO_FORMATTING
-#include "fphdlimp.h"
-#include "unicode/decimfmt.h"
-#include "unicode/choicfmt.h"
-#include "unicode/ucurr.h"
-#include "unicode/ustring.h"
-#include "unicode/dcfmtsym.h"
-#include "unicode/ures.h"
-#include "unicode/uchar.h"
#include "unicode/uniset.h"
-#include "unicode/curramt.h"
#include "unicode/currpinf.h"
#include "unicode/plurrule.h"
#include "unicode/utf16.h"
@@ -59,19 +50,16 @@
#include "uresimp.h"
#include "ucurrimp.h"
#include "charstr.h"
-#include "cmemory.h"
#include "patternprops.h"
-#include "digitlst.h"
#include "cstring.h"
-#include "umutex.h"
#include "uassert.h"
-#include "putilimp.h"
-#include <math.h>
#include "hash.h"
#include "decfmtst.h"
-#include "dcfmtimp.h"
#include "plurrule_impl.h"
#include "decimalformatpattern.h"
+#include "fmtableimp.h"
+#include "decimfmtimpl.h"
+#include "visibledigits.h"
/*
* On certain platforms, round is a macro defined in math.h
@@ -102,19 +90,6 @@ static const UnicodeString dbg_null("<NULL>","");
#endif
-
-/* == Fastpath calculation. ==
- */
-#if UCONFIG_FORMAT_FASTPATHS_49
-inline DecimalFormatInternal& internalData(uint8_t *reserved) {
- return *reinterpret_cast<DecimalFormatInternal*>(reserved);
-}
-inline const DecimalFormatInternal& internalData(const uint8_t *reserved) {
- return *reinterpret_cast<const DecimalFormatInternal*>(reserved);
-}
-#else
-#endif
-
/* For currency parsing purose,
* Need to remember all prefix patterns and suffix patterns of
* every currency format pattern,
@@ -195,28 +170,10 @@ U_CDECL_BEGIN
/**
* @internal ICU 4.2
*/
-static UBool U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2);
-
-/**
- * @internal ICU 4.2
- */
static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2);
static UBool
-U_CALLCONV decimfmtAffixValueComparator(UHashTok val1, UHashTok val2) {
- const AffixesForCurrency* affix_1 =
- (AffixesForCurrency*)val1.pointer;
- const AffixesForCurrency* affix_2 =
- (AffixesForCurrency*)val2.pointer;
- return affix_1->negPrefixForCurrency == affix_2->negPrefixForCurrency &&
- affix_1->negSuffixForCurrency == affix_2->negSuffixForCurrency &&
- affix_1->posPrefixForCurrency == affix_2->posPrefixForCurrency &&
- affix_1->posSuffixForCurrency == affix_2->posSuffixForCurrency;
-}
-
-
-static UBool
U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) {
const AffixPatternsForCurrency* affix_1 =
(AffixPatternsForCurrency*)val1.pointer;
@@ -284,32 +241,9 @@ static const char fgPatterns[]="patterns";
static const char fgDecimalFormat[]="decimalFormat";
static const char fgCurrencyFormat[]="currencyFormat";
-static const UChar fgTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
-
inline int32_t _min(int32_t a, int32_t b) { return (a<b) ? a : b; }
inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
-static void copyString(const UnicodeString& src, UBool isBogus, UnicodeString *& dest, UErrorCode &status) {
- if (U_FAILURE(status)) {
- return;
- }
- if (isBogus) {
- delete dest;
- dest = NULL;
- } else {
- if (dest != NULL) {
- *dest = src;
- } else {
- dest = new UnicodeString(src);
- if (dest == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
- }
- }
- }
-}
-
-
//------------------------------------------------------------------------------
// Constructs a DecimalFormat instance in the default locale.
@@ -391,46 +325,16 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
// or assignment operator can run successfully.
void
DecimalFormat::init() {
- fPosPrefixPattern = 0;
- fPosSuffixPattern = 0;
- fNegPrefixPattern = 0;
- fNegSuffixPattern = 0;
- fCurrencyChoice = 0;
- fMultiplier = NULL;
- fScale = 0;
- fGroupingSize = 0;
- fGroupingSize2 = 0;
- fDecimalSeparatorAlwaysShown = FALSE;
- fSymbols = NULL;
- fUseSignificantDigits = FALSE;
- fMinSignificantDigits = 1;
- fMaxSignificantDigits = 6;
- fUseExponentialNotation = FALSE;
- fMinExponentDigits = 0;
- fExponentSignAlwaysShown = FALSE;
fBoolFlags.clear();
- fRoundingIncrement = 0;
- fRoundingMode = kRoundHalfEven;
- fPad = 0;
- fFormatWidth = 0;
- fPadPosition = kPadBeforePrefix;
fStyle = UNUM_DECIMAL;
- fCurrencySignCount = fgCurrencySignCountZero;
fAffixPatternsForCurrency = NULL;
- fAffixesForCurrency = NULL;
- fPluralAffixesForCurrency = NULL;
fCurrencyPluralInfo = NULL;
- fCurrencyUsage = UCURR_USAGE_STANDARD;
#if UCONFIG_HAVE_PARSEALLINPUT
fParseAllInput = UNUM_MAYBE;
#endif
-#if UCONFIG_FORMAT_FASTPATHS_49
- DecimalFormatInternal &data = internalData(fReserved);
- data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
- data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
-#endif
fStaticSets = NULL;
+ fImpl = NULL;
}
//------------------------------------------------------------------------------
@@ -444,28 +348,18 @@ DecimalFormat::construct(UErrorCode& status,
const UnicodeString* pattern,
DecimalFormatSymbols* symbolsToAdopt)
{
- fSymbols = symbolsToAdopt; // Do this BEFORE aborting on status failure!!!
- fRoundingIncrement = NULL;
- fRoundingMode = kRoundHalfEven;
- fPad = kPatternPadEscape;
- fPadPosition = kPadBeforePrefix;
+ LocalPointer<DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
if (U_FAILURE(status))
return;
- fPosPrefixPattern = fPosSuffixPattern = NULL;
- fNegPrefixPattern = fNegSuffixPattern = NULL;
- setMultiplier(1);
- fGroupingSize = 3;
- fGroupingSize2 = 0;
- fDecimalSeparatorAlwaysShown = FALSE;
- fUseExponentialNotation = FALSE;
- fMinExponentDigits = 0;
-
- if (fSymbols == NULL)
+ if (adoptedSymbols.isNull())
{
- fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
- if (fSymbols == 0) {
+ adoptedSymbols.adoptInstead(
+ new DecimalFormatSymbols(Locale::getDefault(), status));
+ if (adoptedSymbols.isNull() && U_SUCCESS(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ if (U_FAILURE(status)) {
return;
}
}
@@ -473,18 +367,20 @@ DecimalFormat::construct(UErrorCode& status,
if (U_FAILURE(status)) {
return;
}
- UErrorCode nsStatus = U_ZERO_ERROR;
- NumberingSystem *ns = NumberingSystem::createInstance(nsStatus);
- if (U_FAILURE(nsStatus)) {
- status = nsStatus;
- return;
- }
UnicodeString str;
// Uses the default locale's number format pattern if there isn't
// one specified.
if (pattern == NULL)
{
+ UErrorCode nsStatus = U_ZERO_ERROR;
+ LocalPointer<NumberingSystem> ns(
+ NumberingSystem::createInstance(nsStatus));
+ if (U_FAILURE(nsStatus)) {
+ status = nsStatus;
+ return;
+ }
+
int32_t len = 0;
UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status);
@@ -505,26 +401,26 @@ DecimalFormat::construct(UErrorCode& status,
ures_close(top);
}
- delete ns;
+ fImpl = new DecimalFormatImpl(this, *pattern, adoptedSymbols.getAlias(), parseErr, status);
+ if (fImpl) {
+ adoptedSymbols.orphan();
+ } else if (U_SUCCESS(status)) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ if (U_FAILURE(status)) {
+ return;
+ }
if (U_FAILURE(status))
{
return;
}
- if (pattern->indexOf((UChar)kCurrencySign) >= 0) {
- // If it looks like we are going to use a currency pattern
- // then do the time consuming lookup.
- setCurrencyForSymbols();
- } else {
- setCurrencyInternally(NULL, status);
- }
-
const UnicodeString* patternUsed;
UnicodeString currencyPluralPatternForOther;
// apply pattern
if (fStyle == UNUM_CURRENCY_PLURAL) {
- fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
+ fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
if (U_FAILURE(status)) {
return;
}
@@ -537,9 +433,10 @@ DecimalFormat::construct(UErrorCode& status,
// plural count. If not, the right pattern need to be re-applied
// during format.
fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther);
+ // TODO(refactor): Revisit, we are setting the pattern twice.
+ fImpl->applyPatternFavorCurrencyPrecision(
+ currencyPluralPatternForOther, status);
patternUsed = &currencyPluralPatternForOther;
- // TODO: not needed?
- setCurrencyForSymbols();
} else {
patternUsed = pattern;
@@ -549,39 +446,44 @@ DecimalFormat::construct(UErrorCode& status,
// initialize for currency, not only for plural format,
// but also for mix parsing
if (fCurrencyPluralInfo == NULL) {
- fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
+ fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status);
if (U_FAILURE(status)) {
return;
}
}
// need it for mix parsing
setupCurrencyAffixPatterns(status);
- // expanded affixes for plural names
- if (patternUsed->indexOf(fgTripleCurrencySign, 3, 0) != -1) {
- setupCurrencyAffixes(*patternUsed, TRUE, TRUE, status);
- }
- }
-
- applyPatternWithoutExpandAffix(*patternUsed,FALSE, parseErr, status);
-
- // expand affixes
- if (fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
- expandAffixAdjustWidth(NULL);
- }
-
- // If it was a currency format, apply the appropriate rounding by
- // resetting the currency. NOTE: this copies fCurrency on top of itself.
- if (fCurrencySignCount != fgCurrencySignCountZero) {
- setCurrencyInternally(getCurrency(), status);
}
-#if UCONFIG_FORMAT_FASTPATHS_49
- DecimalFormatInternal &data = internalData(fReserved);
- data.fFastFormatStatus = kFastpathNO; // allow it to be calculated
- data.fFastParseStatus = kFastpathNO; // allow it to be calculated
- handleChanged();
-#endif
}
+static void
+applyPatternWithNoSideEffects(
+ const UnicodeString& pattern,
+ UParseError& parseError,
+ UnicodeString &negPrefix,
+ UnicodeString &negSuffix,
+ UnicodeString &posPrefix,
+ UnicodeString &posSuffix,
+ UErrorCode& status) {
+ if (U_FAILURE(status))
+ {
+ return;
+ }
+ DecimalFormatPatternParser patternParser;
+ DecimalFormatPattern out;
+ patternParser.applyPatternWithoutExpandAffix(
+ pattern,
+ out,
+ parseError,
+ status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ negPrefix = out.fNegPrefixPattern;
+ negSuffix = out.fNegSuffixPattern;
+ posPrefix = out.fPosPrefixPattern;
+ posSuffix = out.fPosSuffixPattern;
+}
void
DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
@@ -594,7 +496,7 @@ DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
return;
}
- NumberingSystem *ns = NumberingSystem::createInstance(fSymbols->getLocale(),status);
+ NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLocale(),status);
if (U_FAILURE(status)) {
return;
}
@@ -605,7 +507,7 @@ DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
UnicodeString currencyPattern;
UErrorCode error = U_ZERO_ERROR;
- UResourceBundle *resource = ures_open(NULL, fSymbols->getLocale().getName(), &error);
+ UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().getName(), &error);
UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error);
resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error);
resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error);
@@ -622,13 +524,18 @@ DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
delete ns;
if (U_SUCCESS(error)) {
- applyPatternWithoutExpandAffix(UnicodeString(patResStr, patLen), false,
- parseErr, status);
+ UnicodeString negPrefix;
+ UnicodeString negSuffix;
+ UnicodeString posPrefix;
+ UnicodeString posSuffix;
+ applyPatternWithNoSideEffects(UnicodeString(patResStr, patLen),
+ parseErr,
+ negPrefix, negSuffix, posPrefix, posSuffix, status);
AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
- *fNegPrefixPattern,
- *fNegSuffixPattern,
- *fPosPrefixPattern,
- *fPosSuffixPattern,
+ negPrefix,
+ negSuffix,
+ posPrefix,
+ posSuffix,
UCURR_SYMBOL_NAME);
fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status);
}
@@ -636,7 +543,7 @@ DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
// save the unique currency plural patterns of this locale.
Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern;
const UHashElement* element = NULL;
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
Hashtable pluralPatternSet;
while ((element = pluralPtn->nextElement(pos)) != NULL) {
const UHashTok valueTok = element->value;
@@ -644,13 +551,19 @@ DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
const UHashTok keyTok = element->key;
const UnicodeString* key = (UnicodeString*)keyTok.pointer;
if (pluralPatternSet.geti(*value) != 1) {
+ UnicodeString negPrefix;
+ UnicodeString negSuffix;
+ UnicodeString posPrefix;
+ UnicodeString posSuffix;
pluralPatternSet.puti(*value, 1, status);
- applyPatternWithoutExpandAffix(*value, false, parseErr, status);
+ applyPatternWithNoSideEffects(
+ *value, parseErr,
+ negPrefix, negSuffix, posPrefix, posSuffix, status);
AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency(
- *fNegPrefixPattern,
- *fNegSuffixPattern,
- *fPosPrefixPattern,
- *fPosSuffixPattern,
+ negPrefix,
+ negSuffix,
+ posPrefix,
+ posSuffix,
UCURR_LONG_NAME);
fAffixPatternsForCurrency->put(*key, affixPtn, status);
}
@@ -658,86 +571,13 @@ DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) {
}
-void
-DecimalFormat::setupCurrencyAffixes(const UnicodeString& pattern,
- UBool setupForCurrentPattern,
- UBool setupForPluralPattern,
- UErrorCode& status) {
- if (U_FAILURE(status)) {
- return;
- }
- UParseError parseErr;
- if (setupForCurrentPattern) {
- if (fAffixesForCurrency) {
- deleteHashForAffix(fAffixesForCurrency);
- }
- fAffixesForCurrency = initHashForAffix(status);
- if (U_SUCCESS(status)) {
- applyPatternWithoutExpandAffix(pattern, false, parseErr, status);
- const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules();
- StringEnumeration* keywords = pluralRules->getKeywords(status);
- if (U_SUCCESS(status)) {
- const UnicodeString* pluralCount;
- while ((pluralCount = keywords->snext(status)) != NULL) {
- if ( U_SUCCESS(status) ) {
- expandAffixAdjustWidth(pluralCount);
- AffixesForCurrency* affix = new AffixesForCurrency(
- fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix);
- fAffixesForCurrency->put(*pluralCount, affix, status);
- }
- }
- }
- delete keywords;
- }
- }
-
- if (U_FAILURE(status)) {
- return;
- }
-
- if (setupForPluralPattern) {
- if (fPluralAffixesForCurrency) {
- deleteHashForAffix(fPluralAffixesForCurrency);
- }
- fPluralAffixesForCurrency = initHashForAffix(status);
- if (U_SUCCESS(status)) {
- const PluralRules* pluralRules = fCurrencyPluralInfo->getPluralRules();
- StringEnumeration* keywords = pluralRules->getKeywords(status);
- if (U_SUCCESS(status)) {
- const UnicodeString* pluralCount;
- while ((pluralCount = keywords->snext(status)) != NULL) {
- if ( U_SUCCESS(status) ) {
- UnicodeString ptn;
- fCurrencyPluralInfo->getCurrencyPluralPattern(*pluralCount, ptn);
- applyPatternInternally(*pluralCount, ptn, false, parseErr, status);
- AffixesForCurrency* affix = new AffixesForCurrency(
- fNegativePrefix, fNegativeSuffix, fPositivePrefix, fPositiveSuffix);
- fPluralAffixesForCurrency->put(*pluralCount, affix, status);
- }
- }
- }
- delete keywords;
- }
- }
-}
-
-
//------------------------------------------------------------------------------
DecimalFormat::~DecimalFormat()
{
- delete fPosPrefixPattern;
- delete fPosSuffixPattern;
- delete fNegPrefixPattern;
- delete fNegSuffixPattern;
- delete fCurrencyChoice;
- delete fMultiplier;
- delete fSymbols;
- delete fRoundingIncrement;
deleteHashForAffixPattern();
- deleteHashForAffix(fAffixesForCurrency);
- deleteHashForAffix(fPluralAffixesForCurrency);
delete fCurrencyPluralInfo;
+ delete fImpl;
}
//------------------------------------------------------------------------------
@@ -753,18 +593,6 @@ DecimalFormat::DecimalFormat(const DecimalFormat &source) :
// assignment operator
template <class T>
-static void _copy_ptr(T** pdest, const T* source) {
- if (source == NULL) {
- delete *pdest;
- *pdest = NULL;
- } else if (*pdest == NULL) {
- *pdest = new T(*source);
- } else {
- **pdest = *source;
- }
-}
-
-template <class T>
static void _clone_ptr(T** pdest, const T* source) {
delete *pdest;
if (source == NULL) {
@@ -780,41 +608,12 @@ DecimalFormat::operator=(const DecimalFormat& rhs)
if(this != &rhs) {
UErrorCode status = U_ZERO_ERROR;
NumberFormat::operator=(rhs);
+ if (fImpl == NULL) {
+ fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status);
+ } else {
+ fImpl->assign(*rhs.fImpl, status);
+ }
fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
- fPositivePrefix = rhs.fPositivePrefix;
- fPositiveSuffix = rhs.fPositiveSuffix;
- fNegativePrefix = rhs.fNegativePrefix;
- fNegativeSuffix = rhs.fNegativeSuffix;
- _copy_ptr(&fPosPrefixPattern, rhs.fPosPrefixPattern);
- _copy_ptr(&fPosSuffixPattern, rhs.fPosSuffixPattern);
- _copy_ptr(&fNegPrefixPattern, rhs.fNegPrefixPattern);
- _copy_ptr(&fNegSuffixPattern, rhs.fNegSuffixPattern);
- _clone_ptr(&fCurrencyChoice, rhs.fCurrencyChoice);
- setRoundingIncrement(rhs.getRoundingIncrement());
- fRoundingMode = rhs.fRoundingMode;
- setMultiplier(rhs.getMultiplier());
- fGroupingSize = rhs.fGroupingSize;
- fGroupingSize2 = rhs.fGroupingSize2;
- fDecimalSeparatorAlwaysShown = rhs.fDecimalSeparatorAlwaysShown;
- _copy_ptr(&fSymbols, rhs.fSymbols);
- fUseExponentialNotation = rhs.fUseExponentialNotation;
- fExponentSignAlwaysShown = rhs.fExponentSignAlwaysShown;
- fBoolFlags = rhs.fBoolFlags;
- /*Bertrand A. D. Update 98.03.17*/
- fCurrencySignCount = rhs.fCurrencySignCount;
- /*end of Update*/
- fMinExponentDigits = rhs.fMinExponentDigits;
-
- /* sfb 990629 */
- fFormatWidth = rhs.fFormatWidth;
- fPad = rhs.fPad;
- fPadPosition = rhs.fPadPosition;
- /* end sfb */
- fMinSignificantDigits = rhs.fMinSignificantDigits;
- fMaxSignificantDigits = rhs.fMaxSignificantDigits;
- fUseSignificantDigits = rhs.fUseSignificantDigits;
- fFormatPattern = rhs.fFormatPattern;
- fCurrencyUsage = rhs.fCurrencyUsage;
fStyle = rhs.fStyle;
_clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo);
deleteHashForAffixPattern();
@@ -824,24 +623,8 @@ DecimalFormat::operator=(const DecimalFormat& rhs)
copyHashForAffixPattern(rhs.fAffixPatternsForCurrency,
fAffixPatternsForCurrency, status);
}
- deleteHashForAffix(fAffixesForCurrency);
- if (rhs.fAffixesForCurrency) {
- UErrorCode status = U_ZERO_ERROR;
- fAffixesForCurrency = initHashForAffixPattern(status);
- copyHashForAffix(rhs.fAffixesForCurrency, fAffixesForCurrency, status);
- }
- deleteHashForAffix(fPluralAffixesForCurrency);
- if (rhs.fPluralAffixesForCurrency) {
- UErrorCode status = U_ZERO_ERROR;
- fPluralAffixesForCurrency = initHashForAffixPattern(status);
- copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCurrency, status);
- }
-#if UCONFIG_FORMAT_FASTPATHS_49
- DecimalFormatInternal &data = internalData(fReserved);
- const DecimalFormatInternal &rhsData = internalData(rhs.fReserved);
- data = rhsData;
-#endif
}
+
return *this;
}
@@ -856,247 +639,11 @@ DecimalFormat::operator==(const Format& that) const
// NumberFormat::operator== guarantees this cast is safe
const DecimalFormat* other = (DecimalFormat*)&that;
-#ifdef FMT_DEBUG
- // This code makes it easy to determine why two format objects that should
- // be equal aren't.
- UBool first = TRUE;
- if (!NumberFormat::operator==(that)) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("NumberFormat::!=");
- } else {
- if (!((fPosPrefixPattern == other->fPosPrefixPattern && // both null
- fPositivePrefix == other->fPositivePrefix)
- || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
- *fPosPrefixPattern == *other->fPosPrefixPattern))) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("Pos Prefix !=");
- }
- if (!((fPosSuffixPattern == other->fPosSuffixPattern && // both null
- fPositiveSuffix == other->fPositiveSuffix)
- || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
- *fPosSuffixPattern == *other->fPosSuffixPattern))) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("Pos Suffix !=");
- }
- if (!((fNegPrefixPattern == other->fNegPrefixPattern && // both null
- fNegativePrefix == other->fNegativePrefix)
- || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
- *fNegPrefixPattern == *other->fNegPrefixPattern))) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("Neg Prefix ");
- if (fNegPrefixPattern == NULL) {
- debug("NULL(");
- debugout(fNegativePrefix);
- debug(")");
- } else {
- debugout(*fNegPrefixPattern);
- }
- debug(" != ");
- if (other->fNegPrefixPattern == NULL) {
- debug("NULL(");
- debugout(other->fNegativePrefix);
- debug(")");
- } else {
- debugout(*other->fNegPrefixPattern);
- }
- }
- if (!((fNegSuffixPattern == other->fNegSuffixPattern && // both null
- fNegativeSuffix == other->fNegativeSuffix)
- || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
- *fNegSuffixPattern == *other->fNegSuffixPattern))) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("Neg Suffix ");
- if (fNegSuffixPattern == NULL) {
- debug("NULL(");
- debugout(fNegativeSuffix);
- debug(")");
- } else {
- debugout(*fNegSuffixPattern);
- }
- debug(" != ");
- if (other->fNegSuffixPattern == NULL) {
- debug("NULL(");
- debugout(other->fNegativeSuffix);
- debug(")");
- } else {
- debugout(*other->fNegSuffixPattern);
- }
- }
- if (!((fRoundingIncrement == other->fRoundingIncrement) // both null
- || (fRoundingIncrement != NULL &&
- other->fRoundingIncrement != NULL &&
- *fRoundingIncrement == *other->fRoundingIncrement))) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("Rounding Increment !=");
- }
- if (fRoundingMode != other->fRoundingMode) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- printf("Rounding Mode %d != %d", (int)fRoundingMode, (int)other->fRoundingMode);
- }
- if (getMultiplier() != other->getMultiplier()) {
- if (first) { printf("[ "); first = FALSE; }
- printf("Multiplier %ld != %ld", getMultiplier(), other->getMultiplier());
- }
- if (fGroupingSize != other->fGroupingSize) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- printf("Grouping Size %ld != %ld", fGroupingSize, other->fGroupingSize);
- }
- if (fGroupingSize2 != other->fGroupingSize2) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- printf("Secondary Grouping Size %ld != %ld", fGroupingSize2, other->fGroupingSize2);
- }
- if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- printf("fDecimalSeparatorAlwaysShown %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown);
- }
- if (fUseExponentialNotation != other->fUseExponentialNotation) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fUseExponentialNotation !=");
- }
- if (fUseExponentialNotation &&
- fMinExponentDigits != other->fMinExponentDigits) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fMinExponentDigits !=");
- }
- if (fUseExponentialNotation &&
- fExponentSignAlwaysShown != other->fExponentSignAlwaysShown) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fExponentSignAlwaysShown !=");
- }
- if (fBoolFlags.getAll() != other->fBoolFlags.getAll()) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fBoolFlags !=");
- }
- if (*fSymbols != *(other->fSymbols)) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("Symbols !=");
- }
- // TODO Add debug stuff for significant digits here
- if (fUseSignificantDigits != other->fUseSignificantDigits) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fUseSignificantDigits !=");
- }
- if (fUseSignificantDigits &&
- fMinSignificantDigits != other->fMinSignificantDigits) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fMinSignificantDigits !=");
- }
- if (fUseSignificantDigits &&
- fMaxSignificantDigits != other->fMaxSignificantDigits) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fMaxSignificantDigits !=");
- }
- if (fFormatWidth != other->fFormatWidth) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fFormatWidth !=");
- }
- if (fPad != other->fPad) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fPad !=");
- }
- if (fPadPosition != other->fPadPosition) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fPadPosition !=");
- }
- if (fStyle == UNUM_CURRENCY_PLURAL &&
- fStyle != other->fStyle)
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fStyle !=");
- }
- if (fStyle == UNUM_CURRENCY_PLURAL &&
- fFormatPattern != other->fFormatPattern) {
- if (first) { printf("[ "); first = FALSE; } else { printf(", "); }
- debug("fFormatPattern !=");
- }
-
- if (!first) { printf(" ]"); }
- if (fCurrencySignCount != other->fCurrencySignCount) {
- debug("fCurrencySignCount !=");
- }
- if (fCurrencyPluralInfo == other->fCurrencyPluralInfo) {
- debug("fCurrencyPluralInfo == ");
- if (fCurrencyPluralInfo == NULL) {
- debug("fCurrencyPluralInfo == NULL");
- }
- }
- if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL &&
- *fCurrencyPluralInfo != *(other->fCurrencyPluralInfo)) {
- debug("fCurrencyPluralInfo !=");
- }
- if (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo == NULL ||
- fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo != NULL) {
- debug("fCurrencyPluralInfo one NULL, the other not");
- }
- if (fCurrencyPluralInfo == NULL && other->fCurrencyPluralInfo == NULL) {
- debug("fCurrencyPluralInfo == ");
- }
- }
-#endif
-
return (
NumberFormat::operator==(that) &&
-
- ((fCurrencySignCount == fgCurrencySignCountInPluralFormat) ?
- (fAffixPatternsForCurrency->equals(*other->fAffixPatternsForCurrency)) :
- (((fPosPrefixPattern == other->fPosPrefixPattern && // both null
- fPositivePrefix == other->fPositivePrefix)
- || (fPosPrefixPattern != 0 && other->fPosPrefixPattern != 0 &&
- *fPosPrefixPattern == *other->fPosPrefixPattern)) &&
- ((fPosSuffixPattern == other->fPosSuffixPattern && // both null
- fPositiveSuffix == other->fPositiveSuffix)
- || (fPosSuffixPattern != 0 && other->fPosSuffixPattern != 0 &&
- *fPosSuffixPattern == *other->fPosSuffixPattern)) &&
- ((fNegPrefixPattern == other->fNegPrefixPattern && // both null
- fNegativePrefix == other->fNegativePrefix)
- || (fNegPrefixPattern != 0 && other->fNegPrefixPattern != 0 &&
- *fNegPrefixPattern == *other->fNegPrefixPattern)) &&
- ((fNegSuffixPattern == other->fNegSuffixPattern && // both null
- fNegativeSuffix == other->fNegativeSuffix)
- || (fNegSuffixPattern != 0 && other->fNegSuffixPattern != 0 &&
- *fNegSuffixPattern == *other->fNegSuffixPattern)))) &&
-
- ((fRoundingIncrement == other->fRoundingIncrement) // both null
- || (fRoundingIncrement != NULL &&
- other->fRoundingIncrement != NULL &&
- *fRoundingIncrement == *other->fRoundingIncrement)) &&
-
- fRoundingMode == other->fRoundingMode &&
- getMultiplier() == other->getMultiplier() &&
- fGroupingSize == other->fGroupingSize &&
- fGroupingSize2 == other->fGroupingSize2 &&
- fDecimalSeparatorAlwaysShown == other->fDecimalSeparatorAlwaysShown &&
- fUseExponentialNotation == other->fUseExponentialNotation &&
-
- (!fUseExponentialNotation ||
- (fMinExponentDigits == other->fMinExponentDigits && fExponentSignAlwaysShown == other->fExponentSignAlwaysShown)) &&
-
fBoolFlags.getAll() == other->fBoolFlags.getAll() &&
- *fSymbols == *(other->fSymbols) &&
- fUseSignificantDigits == other->fUseSignificantDigits &&
-
- (!fUseSignificantDigits ||
- (fMinSignificantDigits == other->fMinSignificantDigits && fMaxSignificantDigits == other->fMaxSignificantDigits)) &&
-
- fFormatWidth == other->fFormatWidth &&
- fPad == other->fPad &&
- fPadPosition == other->fPadPosition &&
-
- (fStyle != UNUM_CURRENCY_PLURAL ||
- (fStyle == other->fStyle && fFormatPattern == other->fFormatPattern)) &&
-
- fCurrencySignCount == other->fCurrencySignCount &&
+ *fImpl == *other->fImpl);
- ((fCurrencyPluralInfo == other->fCurrencyPluralInfo &&
- fCurrencyPluralInfo == NULL) ||
- (fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL &&
- *fCurrencyPluralInfo == *(other->fCurrencyPluralInfo))) &&
-
- fCurrencyUsage == other->fCurrencyUsage
-
- // depending on other settings we may also need to compare
- // fCurrencyChoice (mostly deprecated?),
- // fAffixesForCurrency & fPluralAffixesForCurrency (only relevant in some cases)
- );
}
//------------------------------------------------------------------------------
@@ -1110,86 +657,60 @@ DecimalFormat::clone() const
FixedDecimal
DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const {
- FixedDecimal result;
-
+ VisibleDigitsWithExponent digits;
+ initVisibleDigitsWithExponent(number, digits, status);
if (U_FAILURE(status)) {
- return result;
- }
-
- if (uprv_isNaN(number) || uprv_isPositiveInfinity(fabs(number))) {
- // For NaN and Infinity the state of the formatter is ignored.
- result.init(number);
- return result;
+ return FixedDecimal();
}
+ return FixedDecimal(digits.getMantissa());
+}
- if (fMultiplier == NULL && fScale == 0 && fRoundingIncrement == 0 && areSignificantDigitsUsed() == FALSE &&
- result.quickInit(number) && result.visibleDecimalDigitCount <= getMaximumFractionDigits()) {
- // Fast Path. Construction of an exact FixedDecimal directly from the double, without passing
- // through a DigitList, was successful, and the formatter is doing nothing tricky with rounding.
- // printf("getFixedDecimal(%g): taking fast path.\n", number);
- result.adjustForMinFractionDigits(getMinimumFractionDigits());
- } else {
- // Slow path. Create a DigitList, and have this formatter round it according to the
- // requirements of the format, and fill the fixedDecimal from that.
- DigitList digits;
- digits.set(number);
- result = getFixedDecimal(digits, status);
- }
- return result;
+VisibleDigitsWithExponent &
+DecimalFormat::initVisibleDigitsWithExponent(
+ double number,
+ VisibleDigitsWithExponent &digits,
+ UErrorCode &status) const {
+ return fImpl->initVisibleDigitsWithExponent(number, digits, status);
}
-// MSVC optimizer bug?
-// turn off optimization as it causes different behavior in the int64->double->int64 conversion
-#if defined (_MSC_VER)
-#pragma optimize ( "", off )
-#endif
FixedDecimal
DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const {
+ VisibleDigitsWithExponent digits;
+ initVisibleDigitsWithExponent(number, digits, status);
if (U_FAILURE(status)) {
return FixedDecimal();
}
+ return FixedDecimal(digits.getMantissa());
+}
+
+VisibleDigitsWithExponent &
+DecimalFormat::initVisibleDigitsWithExponent(
+ const Formattable &number,
+ VisibleDigitsWithExponent &digits,
+ UErrorCode &status) const {
+ if (U_FAILURE(status)) {
+ return digits;
+ }
if (!number.isNumeric()) {
status = U_ILLEGAL_ARGUMENT_ERROR;
- return FixedDecimal();
+ return digits;
}
DigitList *dl = number.getDigitList();
if (dl != NULL) {
- DigitList clonedDL(*dl);
- return getFixedDecimal(clonedDL, status);
+ DigitList dlCopy(*dl);
+ return fImpl->initVisibleDigitsWithExponent(
+ dlCopy, digits, status);
}
Formattable::Type type = number.getType();
if (type == Formattable::kDouble || type == Formattable::kLong) {
- return getFixedDecimal(number.getDouble(status), status);
- }
-
- if (type == Formattable::kInt64) {
- // "volatile" here is a workaround to avoid optimization issues.
- volatile double fdv = number.getDouble(status);
- // Note: conversion of int64_t -> double rounds with some compilers to
- // values beyond what can be represented as a 64 bit int. Subsequent
- // testing or conversion with int64_t produces bad results.
- // So filter the problematic values, route them to DigitList.
- if (fdv != (double)U_INT64_MAX && fdv != (double)U_INT64_MIN &&
- number.getInt64() == (int64_t)fdv) {
- return getFixedDecimal(number.getDouble(status), status);
- }
+ return fImpl->initVisibleDigitsWithExponent(
+ number.getDouble(status), digits, status);
}
-
- // The only case left is type==int64_t, with a value with more digits than a double can represent.
- // Any formattable originating as a big decimal will have had a pre-existing digit list.
- // Any originating as a double or int32 will have been handled as a double.
-
- U_ASSERT(type == Formattable::kInt64);
- DigitList digits;
- digits.set(number.getInt64());
- return getFixedDecimal(digits, status);
+ return fImpl->initVisibleDigitsWithExponent(
+ number.getInt64(), digits, status);
}
-// end workaround MSVC optimizer bug
-#if defined (_MSC_VER)
-#pragma optimize ( "", on )
-#endif
// Create a fixed decimal from a DigitList.
@@ -1197,70 +718,21 @@ DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) co
// Internal function only.
FixedDecimal
DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const {
- // Round the number according to the requirements of this Format.
- FixedDecimal result;
- _round(number, number, result.isNegative, status);
-
- // The int64_t fields in FixedDecimal can easily overflow.
- // In deciding what to discard in this event, consider that fixedDecimal
- // is being used only with PluralRules, and those rules mostly look at least significant
- // few digits of the integer part, and whether the fraction part is zero or not.
- //
- // So, in case of overflow when filling in the fields of the FixedDecimal object,
- // for the integer part, discard the most significant digits.
- // for the fraction part, discard the least significant digits,
- // don't truncate the fraction value to zero.
- // For simplicity, the int64_t fields are limited to 18 decimal digits, even
- // though they could hold most (but not all) 19 digit values.
-
- // Integer Digits.
- int32_t di = number.getDecimalAt()-18; // Take at most 18 digits.
- if (di < 0) {
- di = 0;
- }
- result.intValue = 0;
- for (; di<number.getDecimalAt(); di++) {
- result.intValue = result.intValue * 10 + (number.getDigit(di) & 0x0f);
- }
- if (result.intValue == 0 && number.getDecimalAt()-18 > 0) {
- // The number is something like 100000000000000000000000.
- // More than 18 digits integer digits, but the least significant 18 are all zero.
- // We don't want to return zero as the int part, but want to keep zeros
- // for several of the least significant digits.
- result.intValue = 100000000000000000LL;
- }
-
- // Fraction digits.
- result.decimalDigits = result.decimalDigitsWithoutTrailingZeros = result.visibleDecimalDigitCount = 0;
- for (di = number.getDecimalAt(); di < number.getCount(); di++) {
- result.visibleDecimalDigitCount++;
- if (result.decimalDigits < 100000000000000000LL) {
- // 9223372036854775807 Largest 64 bit signed integer
- int32_t digitVal = number.getDigit(di) & 0x0f; // getDigit() returns a char, '0'-'9'.
- result.decimalDigits = result.decimalDigits * 10 + digitVal;
- if (digitVal > 0) {
- result.decimalDigitsWithoutTrailingZeros = result.decimalDigits;
- }
- }
- }
-
- result.hasIntegerValue = (result.decimalDigits == 0);
-
- // Trailing fraction zeros. The format specification may require more trailing
- // zeros than the numeric value. Add any such on now.
-
- int32_t minFractionDigits;
- if (areSignificantDigitsUsed()) {
- minFractionDigits = getMinimumSignificantDigits() - number.getDecimalAt();
- if (minFractionDigits < 0) {
- minFractionDigits = 0;
- }
- } else {
- minFractionDigits = getMinimumFractionDigits();
+ VisibleDigitsWithExponent digits;
+ initVisibleDigitsWithExponent(number, digits, status);
+ if (U_FAILURE(status)) {
+ return FixedDecimal();
}
- result.adjustForMinFractionDigits(minFractionDigits);
+ return FixedDecimal(digits.getMantissa());
+}
- return result;
+VisibleDigitsWithExponent &
+DecimalFormat::initVisibleDigitsWithExponent(
+ DigitList &number,
+ VisibleDigitsWithExponent &digits,
+ UErrorCode &status) const {
+ return fImpl->initVisibleDigitsWithExponent(
+ number, digits, status);
}
@@ -1271,7 +743,8 @@ DecimalFormat::format(int32_t number,
UnicodeString& appendTo,
FieldPosition& fieldPosition) const
{
- return format((int64_t)number, appendTo, fieldPosition);
+ UErrorCode status = U_ZERO_ERROR;
+ return fImpl->format(number, appendTo, fieldPosition, status);
}
UnicodeString&
@@ -1280,7 +753,7 @@ DecimalFormat::format(int32_t number,
FieldPosition& fieldPosition,
UErrorCode& status) const
{
- return format((int64_t)number, appendTo, fieldPosition, status);
+ return fImpl->format(number, appendTo, fieldPosition, status);
}
UnicodeString&
@@ -1289,80 +762,10 @@ DecimalFormat::format(int32_t number,
FieldPositionIterator* posIter,
UErrorCode& status) const
{
- return format((int64_t)number, appendTo, posIter, status);
+ return fImpl->format(number, appendTo, posIter, status);
}
-#if UCONFIG_FORMAT_FASTPATHS_49
-void DecimalFormat::handleChanged() {
- DecimalFormatInternal &data = internalData(fReserved);
-
- if(data.fFastFormatStatus == kFastpathUNKNOWN || data.fFastParseStatus == kFastpathUNKNOWN) {
- return; // still constructing. Wait.
- }
-
- data.fFastParseStatus = data.fFastFormatStatus = kFastpathNO;
-
-#if UCONFIG_HAVE_PARSEALLINPUT
- if(fParseAllInput == UNUM_NO) {
- debug("No Parse fastpath: fParseAllInput==UNUM_NO");
- } else
-#endif
- if (fFormatWidth!=0) {
- debug("No Parse fastpath: fFormatWidth");
- } else if(fPositivePrefix.length()>0) {
- debug("No Parse fastpath: positive prefix");
- } else if(fPositiveSuffix.length()>0) {
- debug("No Parse fastpath: positive suffix");
- } else if(fNegativePrefix.length()>1
- || ((fNegativePrefix.length()==1) && (fNegativePrefix.charAt(0)!=0x002D))) {
- debug("No Parse fastpath: negative prefix that isn't '-'");
- } else if(fNegativeSuffix.length()>0) {
- debug("No Parse fastpath: negative suffix");
- } else {
- data.fFastParseStatus = kFastpathYES;
- debug("parse fastpath: YES");
- }
-
- if(fUseExponentialNotation) {
- debug("No format fastpath: fUseExponentialNotation");
- } else if(fFormatWidth!=0) {
- debug("No format fastpath: fFormatWidth!=0");
- } else if(fMinSignificantDigits!=1) {
- debug("No format fastpath: fMinSignificantDigits!=1");
- } else if(fMultiplier!=NULL) {
- debug("No format fastpath: fMultiplier!=NULL");
- } else if(fScale!=0) {
- debug("No format fastpath: fScale!=0");
- } else if(0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)) {
- debug("No format fastpath: 0x0030 != getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0)");
- } else if(fDecimalSeparatorAlwaysShown) {
- debug("No format fastpath: fDecimalSeparatorAlwaysShown");
- } else if(getMinimumFractionDigits()>0) {
- debug("No format fastpath: fMinFractionDigits>0");
- } else if(fCurrencySignCount != fgCurrencySignCountZero) {
- debug("No format fastpath: fCurrencySignCount != fgCurrencySignCountZero");
- } else if(fRoundingIncrement!=0) {
- debug("No format fastpath: fRoundingIncrement!=0");
- } else if (fGroupingSize!=0 && isGroupingUsed()) {
- debug("Maybe format fastpath: fGroupingSize!=0 and grouping is used");
-#ifdef FMT_DEBUG
- printf("groupingsize=%d\n", fGroupingSize);
-#endif
-
- if (getMinimumIntegerDigits() <= fGroupingSize) {
- data.fFastFormatStatus = kFastpathMAYBE;
- }
- } else if(fGroupingSize2!=0 && isGroupingUsed()) {
- debug("No format fastpath: fGroupingSize2!=0");
- } else {
- data.fFastFormatStatus = kFastpathYES;
- debug("format:kFastpathYES!");
- }
-
-
-}
-#endif
//------------------------------------------------------------------------------
UnicodeString&
@@ -1371,8 +774,7 @@ DecimalFormat::format(int64_t number,
FieldPosition& fieldPosition) const
{
UErrorCode status = U_ZERO_ERROR; /* ignored */
- FieldPositionOnlyHandler handler(fieldPosition);
- return _format(number, appendTo, handler, status);
+ return fImpl->format(number, appendTo, fieldPosition, status);
}
UnicodeString&
@@ -1381,8 +783,7 @@ DecimalFormat::format(int64_t number,
FieldPosition& fieldPosition,
UErrorCode& status) const
{
- FieldPositionOnlyHandler handler(fieldPosition);
- return _format(number, appendTo, handler, status);
+ return fImpl->format(number, appendTo, fieldPosition, status);
}
UnicodeString&
@@ -1391,108 +792,7 @@ DecimalFormat::format(int64_t number,
FieldPositionIterator* posIter,
UErrorCode& status) const
{
- FieldPositionIteratorHandler handler(posIter, status);
- return _format(number, appendTo, handler, status);
-}
-
-UnicodeString&
-DecimalFormat::_format(int64_t number,
- UnicodeString& appendTo,
- FieldPositionHandler& handler,
- UErrorCode &status) const
-{
- // Bottleneck function for formatting int64_t
- if (U_FAILURE(status)) {
- return appendTo;
- }
-
-#if UCONFIG_FORMAT_FASTPATHS_49
- // const UnicodeString *posPrefix = fPosPrefixPattern;
- // const UnicodeString *posSuffix = fPosSuffixPattern;
- // const UnicodeString *negSuffix = fNegSuffixPattern;
-
- const DecimalFormatInternal &data = internalData(fReserved);
-
-#ifdef FMT_DEBUG
- data.dump();
- printf("fastpath? [%d]\n", number);
-#endif
-
- if( data.fFastFormatStatus==kFastpathYES ||
- data.fFastFormatStatus==kFastpathMAYBE) {
- int32_t noGroupingThreshold = 0;
-
-#define kZero 0x0030
- const int32_t MAX_IDX = MAX_DIGITS+2;
- UChar outputStr[MAX_IDX];
- int32_t destIdx = MAX_IDX;
- outputStr[--destIdx] = 0; // term
-
- if (data.fFastFormatStatus==kFastpathMAYBE) {
- noGroupingThreshold = destIdx - fGroupingSize;
- }
- int64_t n = number;
- if (number < 1) {
- // Negative numbers are slightly larger than positive
- // output the first digit (or the leading zero)
- outputStr[--destIdx] = (-(n % 10) + kZero);
- n /= -10;
- }
- // get any remaining digits
- while (n > 0) {
- if (destIdx == noGroupingThreshold) {
- goto slowPath;
- }
- outputStr[--destIdx] = (n % 10) + kZero;
- n /= 10;
- }
-
- // Slide the number to the start of the output str
- U_ASSERT(destIdx >= 0);
- int32_t length = MAX_IDX - destIdx -1;
- /*int32_t prefixLen = */ appendAffix(appendTo, static_cast<double>(number), handler, number<0, TRUE);
- int32_t maxIntDig = getMaximumIntegerDigits();
- int32_t destlength = length<=maxIntDig?length:maxIntDig; // dest length pinned to max int digits
-
- if(length>maxIntDig && fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- }
-
- int32_t prependZero = getMinimumIntegerDigits() - destlength;
-
-#ifdef FMT_DEBUG
- printf("prependZero=%d, length=%d, minintdig=%d maxintdig=%d destlength=%d skip=%d\n", prependZero, length, getMinimumIntegerDigits(), maxIntDig, destlength, length-destlength);
-#endif
- int32_t intBegin = appendTo.length();
-
- while((prependZero--)>0) {
- appendTo.append((UChar)0x0030); // '0'
- }
-
- appendTo.append(outputStr+destIdx+
- (length-destlength), // skip any leading digits
- destlength);
- handler.addAttribute(kIntegerField, intBegin, appendTo.length());
-
- /*int32_t suffixLen =*/ appendAffix(appendTo, static_cast<double>(number), handler, number<0, FALSE);
-
- //outputStr[length]=0;
-
-#ifdef FMT_DEBUG
- printf("Writing [%s] length [%d] max %d for [%d]\n", outputStr+destIdx, length, MAX_IDX, number);
-#endif
-
-#undef kZero
-
- return appendTo;
- } // end fastpath
-#endif
- slowPath:
-
- // Else the slow way - via DigitList
- DigitList digits;
- digits.set(number);
- return _format(digits, appendTo, handler, status);
+ return fImpl->format(number, appendTo, posIter, status);
}
//------------------------------------------------------------------------------
@@ -1503,8 +803,7 @@ DecimalFormat::format( double number,
FieldPosition& fieldPosition) const
{
UErrorCode status = U_ZERO_ERROR; /* ignored */
- FieldPositionOnlyHandler handler(fieldPosition);
- return _format(number, appendTo, handler, status);
+ return fImpl->format(number, appendTo, fieldPosition, status);
}
UnicodeString&
@@ -1513,8 +812,7 @@ DecimalFormat::format( double number,
FieldPosition& fieldPosition,
UErrorCode& status) const
{
- FieldPositionOnlyHandler handler(fieldPosition);
- return _format(number, appendTo, handler, status);
+ return fImpl->format(number, appendTo, fieldPosition, status);
}
UnicodeString&
@@ -1523,38 +821,7 @@ DecimalFormat::format( double number,
FieldPositionIterator* posIter,
UErrorCode& status) const
{
- FieldPositionIteratorHandler handler(posIter, status);
- return _format(number, appendTo, handler, status);
-}
-
-UnicodeString&
-DecimalFormat::_format( double number,
- UnicodeString& appendTo,
- FieldPositionHandler& handler,
- UErrorCode &status) const
-{
- if (U_FAILURE(status)) {
- return appendTo;
- }
- // Special case for NaN, sets the begin and end index to be the
- // the string length of localized name of NaN.
- // TODO: let NaNs go through DigitList.
- if (uprv_isNaN(number))
- {
- int begin = appendTo.length();
- appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
-
- handler.addAttribute(kIntegerField, begin, appendTo.length());
-
- addPadding(appendTo, handler, 0, 0);
- return appendTo;
- }
-
- DigitList digits;
- digits.set(number);
- _format(digits, appendTo, handler, status);
- // No way to return status from here.
- return appendTo;
+ return fImpl->format(number, appendTo, posIter, status);
}
//------------------------------------------------------------------------------
@@ -1566,56 +833,8 @@ DecimalFormat::format(const StringPiece &number,
FieldPositionIterator *posIter,
UErrorCode &status) const
{
-#if UCONFIG_FORMAT_FASTPATHS_49
- // don't bother if the int64 path is not optimized
- int32_t len = number.length();
-
- if(len>0&&len<10) { /* 10 or more digits may not be an int64 */
- const char *data = number.data();
- int64_t num = 0;
- UBool neg = FALSE;
- UBool ok = TRUE;
-
- int32_t start = 0;
-
- if(data[start]=='+') {
- start++;
- } else if(data[start]=='-') {
- neg=TRUE;
- start++;
- }
-
- int32_t place = 1; /* 1, 10, ... */
- for(int32_t i=len-1;i>=start;i--) {
- if(data[i]>='0'&&data[i]<='9') {
- num+=place*(int64_t)(data[i]-'0');
- } else {
- ok=FALSE;
- break;
- }
- place *= 10;
- }
-
- if(ok) {
- if(neg) {
- num = -num;// add minus bit
- }
- // format as int64_t
- return format(num, toAppendTo, posIter, status);
- }
- // else fall through
- }
-#endif
-
- DigitList dnum;
- dnum.set(number, status);
- if (U_FAILURE(status)) {
- return toAppendTo;
- }
- FieldPositionIteratorHandler handler(posIter, status);
- _format(dnum, toAppendTo, handler, status);
- return toAppendTo;
-}
+ return fImpl->format(number, toAppendTo, posIter, status);
+}
UnicodeString&
@@ -1623,577 +842,43 @@ DecimalFormat::format(const DigitList &number,
UnicodeString &appendTo,
FieldPositionIterator *posIter,
UErrorCode &status) const {
- FieldPositionIteratorHandler handler(posIter, status);
- _format(number, appendTo, handler, status);
- return appendTo;
+ return fImpl->format(number, appendTo, posIter, status);
}
-
UnicodeString&
DecimalFormat::format(const DigitList &number,
UnicodeString& appendTo,
FieldPosition& pos,
UErrorCode &status) const {
- FieldPositionOnlyHandler handler(pos);
- _format(number, appendTo, handler, status);
- return appendTo;
-}
-
-DigitList&
-DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& isNegative, UErrorCode &status) const {
- if (U_FAILURE(status)) {
- return adjustedNum;
- }
-
- // note: number and adjustedNum may refer to the same DigitList, in cases where a copy
- // is not needed by the caller.
-
- adjustedNum = number;
- isNegative = false;
- if (number.isNaN()) {
- return adjustedNum;
- }
-
- // Do this BEFORE checking to see if value is infinite or negative! Sets the
- // begin and end index to be length of the string composed of
- // localized name of Infinite and the positive/negative localized
- // signs.
-
- adjustedNum.setRoundingMode(fRoundingMode);
- if (fMultiplier != NULL) {
- adjustedNum.mult(*fMultiplier, status);
- if (U_FAILURE(status)) {
- return adjustedNum;
- }
- }
-
- if (fScale != 0) {
- DigitList ten;
- ten.set((int32_t)10);
- if (fScale > 0) {
- for (int32_t i = fScale ; i > 0 ; i--) {
- adjustedNum.mult(ten, status);
- if (U_FAILURE(status)) {
- return adjustedNum;
- }
- }
- } else {
- for (int32_t i = fScale ; i < 0 ; i++) {
- adjustedNum.div(ten, status);
- if (U_FAILURE(status)) {
- return adjustedNum;
- }
- }
- }
- }
-
- /*
- * Note: sign is important for zero as well as non-zero numbers.
- * Proper detection of -0.0 is needed to deal with the
- * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
- */
- isNegative = !adjustedNum.isPositive();
-
- // Apply rounding after multiplier
-
- adjustedNum.fContext.status &= ~DEC_Inexact;
- if (fRoundingIncrement != NULL) {
- adjustedNum.div(*fRoundingIncrement, status);
- adjustedNum.toIntegralValue();
- adjustedNum.mult(*fRoundingIncrement, status);
- adjustedNum.trim();
- if (U_FAILURE(status)) {
- return adjustedNum;
- }
- }
- if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) {
- status = U_FORMAT_INEXACT_ERROR;
- return adjustedNum;
- }
-
- if (adjustedNum.isInfinite()) {
- return adjustedNum;
- }
-
- if (fUseExponentialNotation || areSignificantDigitsUsed()) {
- int32_t sigDigits = precision();
- if (sigDigits > 0) {
- adjustedNum.round(sigDigits);
- // Travis Keep (21/2/2014): Calling round on a digitList does not necessarily
- // preserve the sign of that digit list. Preserving the sign is especially
- // important when formatting -0.0 for instance. Not preserving the sign seems
- // like a bug because I cannot think of any case where the sign would actually
- // have to change when rounding. For now, we preserve the sign by setting the
- // positive attribute directly.
- adjustedNum.setPositive(!isNegative);
- }
- } else {
- // Fixed point format. Round to a set number of fraction digits.
- int32_t numFractionDigits = precision();
- adjustedNum.roundFixedPoint(numFractionDigits);
- }
- if (fRoundingMode == kRoundUnnecessary && (adjustedNum.fContext.status & DEC_Inexact)) {
- status = U_FORMAT_INEXACT_ERROR;
- return adjustedNum;
- }
- return adjustedNum;
+ return fImpl->format(number, appendTo, pos, status);
}
UnicodeString&
-DecimalFormat::_format(const DigitList &number,
- UnicodeString& appendTo,
- FieldPositionHandler& handler,
- UErrorCode &status) const
-{
- if (U_FAILURE(status)) {
- return appendTo;
- }
-
- // Special case for NaN, sets the begin and end index to be the
- // the string length of localized name of NaN.
- if (number.isNaN())
- {
- int begin = appendTo.length();
- appendTo += getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
-
- handler.addAttribute(kIntegerField, begin, appendTo.length());
-
- addPadding(appendTo, handler, 0, 0);
- return appendTo;
- }
-
- DigitList adjustedNum;
- UBool isNegative;
- _round(number, adjustedNum, isNegative, status);
- if (U_FAILURE(status)) {
- return appendTo;
- }
-
- // Special case for INFINITE,
- if (adjustedNum.isInfinite()) {
- int32_t prefixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, TRUE);
-
- int begin = appendTo.length();
- appendTo += getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
-
- handler.addAttribute(kIntegerField, begin, appendTo.length());
-
- int32_t suffixLen = appendAffix(appendTo, adjustedNum.getDouble(), handler, isNegative, FALSE);
-
- addPadding(appendTo, handler, prefixLen, suffixLen);
- return appendTo;
- }
- return subformat(appendTo, handler, adjustedNum, FALSE, status);
-}
-
-/**
- * Return true if a grouping separator belongs at the given
- * position, based on whether grouping is in use and the values of
- * the primary and secondary grouping interval.
- * @param pos the number of integer digits to the right of
- * the current position. Zero indicates the position after the
- * rightmost integer digit.
- * @return true if a grouping character belongs at the current
- * position.
- */
-UBool DecimalFormat::isGroupingPosition(int32_t pos) const {
- UBool result = FALSE;
- if (isGroupingUsed() && (pos > 0) && (fGroupingSize > 0)) {
- if ((fGroupingSize2 > 0) && (pos > fGroupingSize)) {
- result = ((pos - fGroupingSize) % fGroupingSize2) == 0;
- } else {
- result = pos % fGroupingSize == 0;
- }
- }
- return result;
+DecimalFormat::format(const VisibleDigitsWithExponent &number,
+ UnicodeString &appendTo,
+ FieldPositionIterator *posIter,
+ UErrorCode &status) const {
+ return fImpl->format(number, appendTo, posIter, status);
}
-//------------------------------------------------------------------------------
-/**
- * Complete the formatting of a finite number. On entry, the DigitList must
- * be filled in with the correct digits.
- */
UnicodeString&
-DecimalFormat::subformat(UnicodeString& appendTo,
- FieldPositionHandler& handler,
- DigitList& digits,
- UBool isInteger,
- UErrorCode& status) const
-{
- // char zero = '0';
- // DigitList returns digits as '0' thru '9', so we will need to
- // always need to subtract the character 0 to get the numeric value to use for indexing.
-
- UChar32 localizedDigits[10];
- localizedDigits[0] = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
- localizedDigits[1] = getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0);
- localizedDigits[2] = getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0);
- localizedDigits[3] = getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0);
- localizedDigits[4] = getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0);
- localizedDigits[5] = getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0);
- localizedDigits[6] = getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0);
- localizedDigits[7] = getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0);
- localizedDigits[8] = getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0);
- localizedDigits[9] = getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0);
-
- const UnicodeString *grouping ;
- if(fCurrencySignCount == fgCurrencySignCountZero) {
- grouping = &getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
- }else{
- grouping = &getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
- }
- const UnicodeString *decimal;
- if(fCurrencySignCount == fgCurrencySignCountZero) {
- decimal = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
- } else {
- decimal = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
- }
- UBool useSigDig = areSignificantDigitsUsed();
- int32_t maxIntDig = getMaximumIntegerDigits();
- int32_t minIntDig = getMinimumIntegerDigits();
-
- // Appends the prefix.
- double doubleValue = digits.getDouble();
- int32_t prefixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), TRUE);
-
- if (fUseExponentialNotation)
- {
- int currentLength = appendTo.length();
- int intBegin = currentLength;
- int intEnd = -1;
- int fracBegin = -1;
-
- int32_t minFracDig = 0;
- if (useSigDig) {
- maxIntDig = minIntDig = 1;
- minFracDig = getMinimumSignificantDigits() - 1;
- } else {
- minFracDig = getMinimumFractionDigits();
- if (maxIntDig > kMaxScientificIntegerDigits) {
- maxIntDig = 1;
- if (maxIntDig < minIntDig) {
- maxIntDig = minIntDig;
- }
- }
- if (maxIntDig > minIntDig) {
- minIntDig = 1;
- }
- }
-
- // Minimum integer digits are handled in exponential format by
- // adjusting the exponent. For example, 0.01234 with 3 minimum
- // integer digits is "123.4E-4".
-
- // Maximum integer digits are interpreted as indicating the
- // repeating range. This is useful for engineering notation, in
- // which the exponent is restricted to a multiple of 3. For
- // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
- // If maximum integer digits are defined and are larger than
- // minimum integer digits, then minimum integer digits are
- // ignored.
- digits.reduce(); // Removes trailing zero digits.
- int32_t exponent = digits.getDecimalAt();
- if (maxIntDig > 1 && maxIntDig != minIntDig) {
- // A exponent increment is defined; adjust to it.
- exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
- : (exponent / maxIntDig) - 1;
- exponent *= maxIntDig;
- } else {
- // No exponent increment is defined; use minimum integer digits.
- // If none is specified, as in "#E0", generate 1 integer digit.
- exponent -= (minIntDig > 0 || minFracDig > 0)
- ? minIntDig : 1;
- }
-
- // We now output a minimum number of digits, and more if there
- // are more digits, up to the maximum number of digits. We
- // place the decimal point after the "integer" digits, which
- // are the first (decimalAt - exponent) digits.
- int32_t minimumDigits = minIntDig + minFracDig;
- // The number of integer digits is handled specially if the number
- // is zero, since then there may be no digits.
- int32_t integerDigits = digits.isZero() ? minIntDig :
- digits.getDecimalAt() - exponent;
- int32_t totalDigits = digits.getCount();
- if (minimumDigits > totalDigits)
- totalDigits = minimumDigits;
- if (integerDigits > totalDigits)
- totalDigits = integerDigits;
-
- // totalDigits records total number of digits needs to be processed
- int32_t i;
- for (i=0; i<totalDigits; ++i)
- {
- if (i == integerDigits)
- {
- intEnd = appendTo.length();
- handler.addAttribute(kIntegerField, intBegin, intEnd);
-
- appendTo += *decimal;
-
- fracBegin = appendTo.length();
- handler.addAttribute(kDecimalSeparatorField, fracBegin - 1, fracBegin);
- }
- // Restores the digit character or pads the buffer with zeros.
- UChar32 c = (UChar32)((i < digits.getCount()) ?
- localizedDigits[digits.getDigitValue(i)] :
- localizedDigits[0]);
- appendTo += c;
- }
-
- currentLength = appendTo.length();
-
- if (intEnd < 0) {
- handler.addAttribute(kIntegerField, intBegin, currentLength);
- }
- if (fracBegin > 0) {
- handler.addAttribute(kFractionField, fracBegin, currentLength);
- }
-
- // The exponent is output using the pattern-specified minimum
- // exponent digits. There is no maximum limit to the exponent
- // digits, since truncating the exponent would appendTo in an
- // unacceptable inaccuracy.
- appendTo += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
-
- handler.addAttribute(kExponentSymbolField, currentLength, appendTo.length());
- currentLength = appendTo.length();
-
- // For zero values, we force the exponent to zero. We
- // must do this here, and not earlier, because the value
- // is used to determine integer digit count above.
- if (digits.isZero())
- exponent = 0;
-
- if (exponent < 0) {
- appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- handler.addAttribute(kExponentSignField, currentLength, appendTo.length());
- } else if (fExponentSignAlwaysShown) {
- appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- handler.addAttribute(kExponentSignField, currentLength, appendTo.length());
- }
-
- currentLength = appendTo.length();
-
- DigitList expDigits;
- expDigits.set(exponent);
- {
- int expDig = fMinExponentDigits;
- if (fUseExponentialNotation && expDig < 1) {
- expDig = 1;
- }
- for (i=expDigits.getDecimalAt(); i<expDig; ++i)
- appendTo += (localizedDigits[0]);
- }
- for (i=0; i<expDigits.getDecimalAt(); ++i)
- {
- UChar32 c = (UChar32)((i < expDigits.getCount()) ?
- localizedDigits[expDigits.getDigitValue(i)] :
- localizedDigits[0]);
- appendTo += c;
- }
-
- handler.addAttribute(kExponentField, currentLength, appendTo.length());
- }
- else // Not using exponential notation
- {
- int currentLength = appendTo.length();
- int intBegin = currentLength;
-
- int32_t sigCount = 0;
- int32_t minSigDig = getMinimumSignificantDigits();
- int32_t maxSigDig = getMaximumSignificantDigits();
- if (!useSigDig) {
- minSigDig = 0;
- maxSigDig = INT32_MAX;
- }
-
- // Output the integer portion. Here 'count' is the total
- // number of integer digits we will display, including both
- // leading zeros required to satisfy getMinimumIntegerDigits,
- // and actual digits present in the number.
- int32_t count = useSigDig ?
- _max(1, digits.getDecimalAt()) : minIntDig;
- if (digits.getDecimalAt() > 0 && count < digits.getDecimalAt()) {
- count = digits.getDecimalAt();
- }
-
- // Handle the case where getMaximumIntegerDigits() is smaller
- // than the real number of integer digits. If this is so, we
- // output the least significant max integer digits. For example,
- // the value 1997 printed with 2 max integer digits is just "97".
-
- int32_t digitIndex = 0; // Index into digitList.fDigits[]
- if (count > maxIntDig && maxIntDig >= 0) {
- count = maxIntDig;
- digitIndex = digits.getDecimalAt() - count;
- if(fBoolFlags.contains(UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- }
- }
-
- int32_t sizeBeforeIntegerPart = appendTo.length();
-
- int32_t i;
- for (i=count-1; i>=0; --i)
- {
- if (i < digits.getDecimalAt() && digitIndex < digits.getCount() &&
- sigCount < maxSigDig) {
- // Output a real digit
- appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)];
- ++sigCount;
- }
- else
- {
- // Output a zero (leading or trailing)
- appendTo += localizedDigits[0];
- if (sigCount > 0) {
- ++sigCount;
- }
- }
-
- // Output grouping separator if necessary.
- if (isGroupingPosition(i)) {
- currentLength = appendTo.length();
- appendTo.append(*grouping);
- handler.addAttribute(kGroupingSeparatorField, currentLength, appendTo.length());
- }
- }
-
- // This handles the special case of formatting 0. For zero only, we count the
- // zero to the left of the decimal point as one signficant digit. Ordinarily we
- // do not count any leading 0's as significant. If the number we are formatting
- // is not zero, then either sigCount or digits.getCount() will be non-zero.
- if (sigCount == 0 && digits.getCount() == 0) {
- sigCount = 1;
- }
-
- // TODO(dlf): this looks like it was a bug, we marked the int field as ending
- // before the zero was generated.
- // Record field information for caller.
- // if (fieldPosition.getField() == NumberFormat::kIntegerField)
- // fieldPosition.setEndIndex(appendTo.length());
-
- // Determine whether or not there are any printable fractional
- // digits. If we've used up the digits we know there aren't.
- UBool fractionPresent = (!isInteger && digitIndex < digits.getCount()) ||
- (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
-
- // If there is no fraction present, and we haven't printed any
- // integer digits, then print a zero. Otherwise we won't print
- // _any_ digits, and we won't be able to parse this string.
- if (!fractionPresent && appendTo.length() == sizeBeforeIntegerPart)
- appendTo += localizedDigits[0];
-
- currentLength = appendTo.length();
- handler.addAttribute(kIntegerField, intBegin, currentLength);
-
- // Output the decimal separator if we always do so.
- if (fDecimalSeparatorAlwaysShown || fractionPresent) {
- appendTo += *decimal;
- handler.addAttribute(kDecimalSeparatorField, currentLength, appendTo.length());
- currentLength = appendTo.length();
- }
-
- int fracBegin = currentLength;
-
- count = useSigDig ? INT32_MAX : getMaximumFractionDigits();
- if (useSigDig && (sigCount == maxSigDig ||
- (sigCount >= minSigDig && digitIndex == digits.getCount()))) {
- count = 0;
- }
-
- for (i=0; i < count; ++i) {
- // Here is where we escape from the loop. We escape
- // if we've output the maximum fraction digits
- // (specified in the for expression above). We also
- // stop when we've output the minimum digits and
- // either: we have an integer, so there is no
- // fractional stuff to display, or we're out of
- // significant digits.
- if (!useSigDig && i >= getMinimumFractionDigits() &&
- (isInteger || digitIndex >= digits.getCount())) {
- break;
- }
-
- // Output leading fractional zeros. These are zeros
- // that come after the decimal but before any
- // significant digits. These are only output if
- // abs(number being formatted) < 1.0.
- if (-1-i > (digits.getDecimalAt()-1)) {
- appendTo += localizedDigits[0];
- continue;
- }
-
- // Output a digit, if we have any precision left, or a
- // zero if we don't. We don't want to output noise digits.
- if (!isInteger && digitIndex < digits.getCount()) {
- appendTo += (UChar32)localizedDigits[digits.getDigitValue(digitIndex++)];
- } else {
- appendTo += localizedDigits[0];
- }
-
- // If we reach the maximum number of significant
- // digits, or if we output all the real digits and
- // reach the minimum, then we are done.
- ++sigCount;
- if (useSigDig &&
- (sigCount == maxSigDig ||
- (digitIndex == digits.getCount() && sigCount >= minSigDig))) {
- break;
- }
- }
-
- handler.addAttribute(kFractionField, fracBegin, appendTo.length());
- }
-
- int32_t suffixLen = appendAffix(appendTo, doubleValue, handler, !digits.isPositive(), FALSE);
-
- addPadding(appendTo, handler, prefixLen, suffixLen);
- return appendTo;
+DecimalFormat::format(const VisibleDigitsWithExponent &number,
+ UnicodeString& appendTo,
+ FieldPosition& pos,
+ UErrorCode &status) const {
+ return fImpl->format(number, appendTo, pos, status);
}
-/**
- * Inserts the character fPad as needed to expand result to fFormatWidth.
- * @param result the string to be padded
- */
-void DecimalFormat::addPadding(UnicodeString& appendTo,
- FieldPositionHandler& handler,
- int32_t prefixLen,
- int32_t suffixLen) const
-{
- if (fFormatWidth > 0) {
- int32_t len = fFormatWidth - appendTo.length();
- if (len > 0) {
- UnicodeString padding;
- for (int32_t i=0; i<len; ++i) {
- padding += fPad;
- }
- switch (fPadPosition) {
- case kPadAfterPrefix:
- appendTo.insert(prefixLen, padding);
- break;
- case kPadBeforePrefix:
- appendTo.insert(0, padding);
- break;
- case kPadBeforeSuffix:
- appendTo.insert(appendTo.length() - suffixLen, padding);
- break;
- case kPadAfterSuffix:
- appendTo += padding;
- break;
- }
- if (fPadPosition == kPadBeforePrefix || fPadPosition == kPadAfterPrefix) {
- handler.shiftLast(len);
- }
- }
- }
+DigitList&
+DecimalFormat::_round(const DigitList& number, DigitList& adjustedNum, UBool& isNegative, UErrorCode& status) const {
+ adjustedNum = number;
+ fImpl->round(adjustedNum, status);
+ isNegative = !adjustedNum.isPositive();
+ return adjustedNum;
}
-//------------------------------------------------------------------------------
-
void
DecimalFormat::parse(const UnicodeString& text,
Formattable& result,
@@ -2209,7 +894,7 @@ CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text,
parse(text, parseResult, pos, curbuf);
if (pos.getIndex() != start) {
UErrorCode ec = U_ZERO_ERROR;
- LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec));
+ LocalPointer<CurrencyAmount> currAmt(new CurrencyAmount(parseResult, curbuf, ec), ec);
if (U_FAILURE(ec)) {
pos.setIndex(start); // indicate failure
} else {
@@ -2250,10 +935,12 @@ void DecimalFormat::parse(const UnicodeString& text,
}
// Handle NaN as a special case:
+ int32_t formatWidth = fImpl->getOldFormatWidth();
// Skip padding characters, if around prefix
- if (fFormatWidth > 0 && (fPadPosition == kPadBeforePrefix ||
- fPadPosition == kPadAfterPrefix)) {
+ if (formatWidth > 0 && (
+ fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix ||
+ fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix)) {
i = skipPadding(text, i);
}
@@ -2263,13 +950,12 @@ void DecimalFormat::parse(const UnicodeString& text,
}
// If the text is composed of the representation of NaN, returns NaN.length
- const UnicodeString *nan = &getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
+ const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
int32_t nanLen = (text.compare(i, nan->length(), *nan)
? 0 : nan->length());
if (nanLen) {
i += nanLen;
- if (fFormatWidth > 0 && (fPadPosition == kPadBeforeSuffix ||
- fPadPosition == kPadAfterSuffix)) {
+ if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix)) {
i = skipPadding(text, i);
}
parsePosition.setIndex(i);
@@ -2289,15 +975,17 @@ void DecimalFormat::parse(const UnicodeString& text,
return; // no way to report error from here.
}
- if (fCurrencySignCount != fgCurrencySignCountZero) {
+ if (fImpl->fMonetary) {
if (!parseForCurrency(text, parsePosition, *digits,
status, currency)) {
return;
}
} else {
if (!subparse(text,
- fNegPrefixPattern, fNegSuffixPattern,
- fPosPrefixPattern, fPosSuffixPattern,
+ &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
+ &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
+ &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
+ &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
FALSE, UCURR_SYMBOL_NAME,
parsePosition, *digits, status, currency)) {
debug("!subparse(...) - rewind");
@@ -2315,21 +1003,21 @@ void DecimalFormat::parse(const UnicodeString& text,
else {
- if (fMultiplier != NULL) {
+ if (!fImpl->fMultiplier.isZero()) {
UErrorCode ec = U_ZERO_ERROR;
- digits->div(*fMultiplier, ec);
+ digits->div(fImpl->fMultiplier, ec);
}
- if (fScale != 0) {
+ if (fImpl->fScale != 0) {
DigitList ten;
ten.set((int32_t)10);
- if (fScale > 0) {
- for (int32_t i = fScale; i > 0; i--) {
+ if (fImpl->fScale > 0) {
+ for (int32_t i = fImpl->fScale; i > 0; i--) {
UErrorCode ec = U_ZERO_ERROR;
digits->div(ten,ec);
}
} else {
- for (int32_t i = fScale; i < 0; i++) {
+ for (int32_t i = fImpl->fScale; i < 0; i++) {
UErrorCode ec = U_ZERO_ERROR;
digits->mult(ten,ec);
}
@@ -2354,6 +1042,15 @@ DecimalFormat::parseForCurrency(const UnicodeString& text,
DigitList& digits,
UBool* status,
UChar* currency) const {
+ UnicodeString positivePrefix;
+ UnicodeString positiveSuffix;
+ UnicodeString negativePrefix;
+ UnicodeString negativeSuffix;
+ fImpl->fPositivePrefixPattern.toString(positivePrefix);
+ fImpl->fPositiveSuffixPattern.toString(positiveSuffix);
+ fImpl->fNegativePrefixPattern.toString(negativePrefix);
+ fImpl->fNegativeSuffixPattern.toString(negativeSuffix);
+
int origPos = parsePosition.getIndex();
int maxPosIndex = origPos;
int maxErrorPos = -1;
@@ -2367,14 +1064,14 @@ DecimalFormat::parseForCurrency(const UnicodeString& text,
UBool found;
if (fStyle == UNUM_CURRENCY_PLURAL) {
found = subparse(text,
- fNegPrefixPattern, fNegSuffixPattern,
- fPosPrefixPattern, fPosSuffixPattern,
+ &negativePrefix, &negativeSuffix,
+ &positivePrefix, &positiveSuffix,
TRUE, UCURR_LONG_NAME,
tmpPos, tmpDigitList, tmpStatus, currency);
} else {
found = subparse(text,
- fNegPrefixPattern, fNegSuffixPattern,
- fPosPrefixPattern, fPosSuffixPattern,
+ &negativePrefix, &negativeSuffix,
+ &positivePrefix, &positiveSuffix,
TRUE, UCURR_SYMBOL_NAME,
tmpPos, tmpDigitList, tmpStatus, currency);
}
@@ -2391,7 +1088,7 @@ DecimalFormat::parseForCurrency(const UnicodeString& text,
}
// Then, parse against affix patterns.
// Those are currency patterns and currency plural patterns.
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
const UHashElement* element = NULL;
while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
const UHashTok valueTok = element->value;
@@ -2446,8 +1143,10 @@ DecimalFormat::parseForCurrency(const UnicodeString& text,
// Disable complex currency parsing and try it again.
UBool result = subparse(text,
- &fNegativePrefix, &fNegativeSuffix,
- &fPositivePrefix, &fPositiveSuffix,
+ &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(),
+ &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(),
+ &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(),
+ &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(),
FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME,
tmpPos_2, tmpDigitList_2, tmpStatus_2,
currency);
@@ -2518,9 +1217,10 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
int32_t oldStart = position;
int32_t textLength = text.length(); // One less pointer to follow
UBool strictParse = !isLenient();
- UChar32 zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
- const UnicodeString *groupingString = &getConstSymbol(fCurrencySignCount == fgCurrencySignCountZero ?
- DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
+ UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
+ const UnicodeString *groupingString = &fImpl->getConstSymbol(
+ !fImpl->fMonetary ?
+ DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol);
UChar32 groupingChar = groupingString->char32At(0);
int32_t groupingStringLength = groupingString->length();
int32_t groupingCharLength = U16_LENGTH(groupingChar);
@@ -2535,15 +1235,11 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
DBGAPPD(posPrefix);
DBGAPPD(posSuffix);
debugout(s);
- printf("currencyParsing=%d, fFormatWidth=%d, isParseIntegerOnly=%c text.length=%d negPrefLen=%d\n", currencyParsing, fFormatWidth, (isParseIntegerOnly())?'Y':'N', text.length(), negPrefix!=NULL?negPrefix->length():-1);
#endif
UBool fastParseOk = false; /* TRUE iff fast parse is OK */
// UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */
- const DecimalFormatInternal &data = internalData(fReserved);
- if((data.fFastParseStatus==kFastpathYES) &&
- fCurrencySignCount == fgCurrencySignCountZero &&
- // (negPrefix!=NULL&&negPrefix->isEmpty()) ||
+ if((fImpl->isParseFastpath()) && !fImpl->fMonetary &&
text.length()>0 &&
text.length()<32 &&
(posPrefix==NULL||posPrefix->isEmpty()) &&
@@ -2555,7 +1251,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
int l=text.length();
int digitCount=0;
UChar32 ch = text.char32At(j);
- const UnicodeString *decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
+ const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
UChar32 decimalChar = 0;
UBool intOnly = FALSE;
UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0;
@@ -2617,9 +1313,6 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
if(
((j==l)||intOnly) // end OR only parsing integer
&& (digitCount>0)) { // and have at least one digit
-#ifdef FMT_DEBUG
- printf("PP -> %d, good = [%s] digitcount=%d, fGroupingSize=%d fGroupingSize2=%d!\n", j, parsedNum.data(), digitCount, fGroupingSize, fGroupingSize2);
-#endif
fastParseOk=true; // Fast parse OK!
#ifdef SKIP_OPT
@@ -2641,7 +1334,6 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
} else {
#ifdef FMT_DEBUG
printf("Could not fastpath parse. ");
- printf("fFormatWidth=%d ", fFormatWidth);
printf("text.length()=%d ", text.length());
printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix);
@@ -2649,14 +1341,18 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
#endif
}
+ UnicodeString formatPattern;
+ toPattern(formatPattern);
+
if(!fastParseOk
#if UCONFIG_HAVE_PARSEALLINPUT
&& fParseAllInput!=UNUM_YES
#endif
)
{
+ int32_t formatWidth = fImpl->getOldFormatWidth();
// Match padding before prefix
- if (fFormatWidth > 0 && fPadPosition == kPadBeforePrefix) {
+ if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
position = skipPadding(text, position);
}
@@ -2685,7 +1381,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
}
// Match padding before prefix
- if (fFormatWidth > 0 && fPadPosition == kPadAfterPrefix) {
+ if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
position = skipPadding(text, position);
}
@@ -2694,7 +1390,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
}
// process digits or Inf, find decimal position
- const UnicodeString *inf = &getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
+ const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol);
int32_t infLen = (text.compare(position, inf->length(), *inf)
? 0 : inf->length());
position += infLen; // infLen is non-zero when it does equal to infinity
@@ -2714,13 +1410,13 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
UBool strictFail = FALSE; // did we exit with a strict parse failure?
int32_t lastGroup = -1; // where did we last see a grouping separator?
int32_t digitStart = position;
- int32_t gs2 = fGroupingSize2 == 0 ? fGroupingSize : fGroupingSize2;
+ int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping.fGrouping : fImpl->fEffGrouping.fGrouping2;
const UnicodeString *decimalString;
- if (fCurrencySignCount != fgCurrencySignCountZero) {
- decimalString = &getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
+ if (fImpl->fMonetary) {
+ decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol);
} else {
- decimalString = &getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
+ decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
}
UChar32 decimalChar = decimalString->char32At(0);
int32_t decimalStringLength = decimalString->length();
@@ -2784,11 +1480,11 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
// is not a "standard" Unicode digit.
if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) {
digit = 0;
- if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) {
+ if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) {
break;
}
for (digit = 1 ; digit < 10 ; digit++ ) {
- if ( getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
+ if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) {
break;
}
}
@@ -2860,7 +1556,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
{
if (strictParse) {
if (backup != -1 ||
- (lastGroup != -1 && position - lastGroup != fGroupingSize + 1)) {
+ (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1)) {
strictFail = TRUE;
break;
}
@@ -2884,7 +1580,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless..
isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways
const UnicodeString *tmp;
- tmp = &getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
+ tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
// TODO: CASE
if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit
{
@@ -2894,13 +1590,13 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
if (pos < textLength)
{
- tmp = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
+ tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
if (!text.compare(pos, tmp->length(), *tmp))
{
pos += tmp->length();
}
else {
- tmp = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
+ tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
if (!text.compare(pos, tmp->length(), *tmp))
{
exponentSign = '-';
@@ -2947,7 +1643,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
// if we didn't see a decimal and it is required, check to see if the pattern had one
if(!sawDecimal && isDecimalPatternMatchRequired())
{
- if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
+ if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
{
parsePosition.setIndex(oldStart);
parsePosition.setErrorIndex(position);
@@ -2962,7 +1658,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
}
if (strictParse && !sawDecimal) {
- if (lastGroup != -1 && position - lastGroup != fGroupingSize + 1) {
+ if (lastGroup != -1 && position - lastGroup != fImpl->fEffGrouping.fGrouping + 1) {
strictFail = TRUE;
}
}
@@ -2994,7 +1690,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
}
// Match padding before suffix
- if (fFormatWidth > 0 && fPadPosition == kPadBeforeSuffix) {
+ if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
position = skipPadding(text, position);
}
@@ -3025,7 +1721,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0));
// Match padding before suffix
- if (fFormatWidth > 0 && fPadPosition == kPadAfterSuffix) {
+ if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
position = skipPadding(text, position);
}
@@ -3073,7 +1769,7 @@ printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d
// check if we missed a required decimal point
if(fastParseOk && isDecimalPatternMatchRequired())
{
- if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
+ if(formatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0)
{
parsePosition.setIndex(oldStart);
parsePosition.setErrorIndex(position);
@@ -3092,9 +1788,9 @@ printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d
* character. Result is >= position.
*/
int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const {
- int32_t padLen = U16_LENGTH(fPad);
+ int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar);
while (position < text.length() &&
- text.char32At(position) == fPad) {
+ text.char32At(position) == fImpl->fAffixes.fPadChar) {
position += padLen;
}
return position;
@@ -3128,8 +1824,8 @@ int32_t DecimalFormat::compareAffix(const UnicodeString& text,
UChar* currency) const
{
const UnicodeString *patternToCompare;
- if (fCurrencyChoice != NULL || currency != NULL ||
- (fCurrencySignCount != fgCurrencySignCountZero && complexCurrencyParsing)) {
+ if (currency != NULL ||
+ (fImpl->fMonetary && complexCurrencyParsing)) {
if (affixPat != NULL) {
return compareComplexAffix(*affixPat, text, pos, type, currency);
@@ -3138,18 +1834,18 @@ int32_t DecimalFormat::compareAffix(const UnicodeString& text,
if (isNegative) {
if (isPrefix) {
- patternToCompare = &fNegativePrefix;
+ patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString();
}
else {
- patternToCompare = &fNegativeSuffix;
+ patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString();
}
}
else {
if (isPrefix) {
- patternToCompare = &fPositivePrefix;
+ patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString();
}
else {
- patternToCompare = &fPositiveSuffix;
+ patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString();
}
}
return compareSimpleAffix(*patternToCompare, text, pos, isLenient());
@@ -3420,9 +2116,7 @@ int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
UChar* currency) const
{
int32_t start = pos;
- U_ASSERT(currency != NULL ||
- (fCurrencyChoice != NULL && *getCurrency() != 0) ||
- fCurrencySignCount != fgCurrencySignCountZero);
+ U_ASSERT(currency != NULL || fImpl->fMonetary);
for (int32_t i=0;
i<affixPat.length() && pos >= 0; ) {
@@ -3487,16 +2181,16 @@ int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat,
continue;
}
case kPatternPercent:
- affix = &getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
+ affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
break;
case kPatternPerMill:
- affix = &getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
+ affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
break;
case kPatternPlus:
- affix = &getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
+ affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
break;
case kPatternMinus:
- affix = &getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
+ affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
break;
default:
// fall through to affix!=0 test, which will fail
@@ -3603,7 +2297,7 @@ UBool DecimalFormat::matchGrouping(UChar32 groupingChar,
const DecimalFormatSymbols*
DecimalFormat::getDecimalFormatSymbols() const
{
- return fSymbols;
+ return &fImpl->getDecimalFormatSymbols();
}
//------------------------------------------------------------------------------
@@ -3615,25 +2309,7 @@ DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
if (symbolsToAdopt == NULL) {
return; // do not allow caller to set fSymbols to NULL
}
-
- UBool sameSymbols = FALSE;
- if (fSymbols != NULL) {
- sameSymbols = (UBool)(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) ==
- symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) &&
- getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) ==
- symbolsToAdopt->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
- delete fSymbols;
- }
-
- fSymbols = symbolsToAdopt;
- if (!sameSymbols) {
- // If the currency symbols are the same, there is no need to recalculate.
- setCurrencyForSymbols();
- }
- expandAffixes(NULL);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->adoptDecimalFormatSymbols(symbolsToAdopt);
}
//------------------------------------------------------------------------------
// Setting the symbols is equlivalent to adopting a newly created localized
@@ -3643,9 +2319,6 @@ void
DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
{
adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
}
@@ -3663,73 +2336,20 @@ DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt)
delete fCurrencyPluralInfo;
fCurrencyPluralInfo = toAdopt;
// re-set currency affix patterns and currency affixes.
- if (fCurrencySignCount != fgCurrencySignCountZero) {
+ if (fImpl->fMonetary) {
UErrorCode status = U_ZERO_ERROR;
if (fAffixPatternsForCurrency) {
deleteHashForAffixPattern();
}
setupCurrencyAffixPatterns(status);
- if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
- // only setup the affixes of the plural pattern.
- setupCurrencyAffixes(fFormatPattern, FALSE, TRUE, status);
- }
}
}
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
}
void
DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info)
{
adoptCurrencyPluralInfo(info.clone());
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-
-/**
- * Update the currency object to match the symbols. This method
- * is used only when the caller has passed in a symbols object
- * that may not be the default object for its locale.
- */
-void
-DecimalFormat::setCurrencyForSymbols() {
- /*Bug 4212072
- Update the affix strings accroding to symbols in order to keep
- the affix strings up to date.
- [Richard/GCL]
- */
-
- // With the introduction of the Currency object, the currency
- // symbols in the DFS object are ignored. For backward
- // compatibility, we check any explicitly set DFS object. If it
- // is a default symbols object for its locale, we change the
- // currency object to one for that locale. If it is custom,
- // we set the currency to null.
- UErrorCode ec = U_ZERO_ERROR;
- const UChar* c = NULL;
- const char* loc = fSymbols->getLocale().getName();
- UChar intlCurrencySymbol[4];
- ucurr_forLocale(loc, intlCurrencySymbol, 4, &ec);
- UnicodeString currencySymbol;
-
- uprv_getStaticCurrencyName(intlCurrencySymbol, loc, currencySymbol, ec);
- if (U_SUCCESS(ec)
- && getConstSymbol(DecimalFormatSymbols::kCurrencySymbol) == currencySymbol
- && getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol) == UnicodeString(intlCurrencySymbol))
- {
- // Trap an error in mapping locale to currency. If we can't
- // map, then don't fail and set the currency to "".
- c = intlCurrencySymbol;
- }
- ec = U_ZERO_ERROR; // reset local error code!
- setCurrencyInternally(c, ec);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
}
@@ -3739,8 +2359,7 @@ DecimalFormat::setCurrencyForSymbols() {
UnicodeString&
DecimalFormat::getPositivePrefix(UnicodeString& result) const
{
- result = fPositivePrefix;
- return result;
+ return fImpl->getPositivePrefix(result);
}
//------------------------------------------------------------------------------
@@ -3749,12 +2368,7 @@ DecimalFormat::getPositivePrefix(UnicodeString& result) const
void
DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
{
- fPositivePrefix = newValue;
- delete fPosPrefixPattern;
- fPosPrefixPattern = 0;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setPositivePrefix(newValue);
}
//------------------------------------------------------------------------------
@@ -3763,8 +2377,7 @@ DecimalFormat::setPositivePrefix(const UnicodeString& newValue)
UnicodeString&
DecimalFormat::getNegativePrefix(UnicodeString& result) const
{
- result = fNegativePrefix;
- return result;
+ return fImpl->getNegativePrefix(result);
}
//------------------------------------------------------------------------------
@@ -3773,12 +2386,7 @@ DecimalFormat::getNegativePrefix(UnicodeString& result) const
void
DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
{
- fNegativePrefix = newValue;
- delete fNegPrefixPattern;
- fNegPrefixPattern = 0;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setNegativePrefix(newValue);
}
//------------------------------------------------------------------------------
@@ -3787,8 +2395,7 @@ DecimalFormat::setNegativePrefix(const UnicodeString& newValue)
UnicodeString&
DecimalFormat::getPositiveSuffix(UnicodeString& result) const
{
- result = fPositiveSuffix;
- return result;
+ return fImpl->getPositiveSuffix(result);
}
//------------------------------------------------------------------------------
@@ -3797,12 +2404,7 @@ DecimalFormat::getPositiveSuffix(UnicodeString& result) const
void
DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
{
- fPositiveSuffix = newValue;
- delete fPosSuffixPattern;
- fPosSuffixPattern = 0;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setPositiveSuffix(newValue);
}
//------------------------------------------------------------------------------
@@ -3811,8 +2413,7 @@ DecimalFormat::setPositiveSuffix(const UnicodeString& newValue)
UnicodeString&
DecimalFormat::getNegativeSuffix(UnicodeString& result) const
{
- result = fNegativeSuffix;
- return result;
+ return fImpl->getNegativeSuffix(result);
}
//------------------------------------------------------------------------------
@@ -3821,12 +2422,7 @@ DecimalFormat::getNegativeSuffix(UnicodeString& result) const
void
DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
{
- fNegativeSuffix = newValue;
- delete fNegSuffixPattern;
- fNegSuffixPattern = 0;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setNegativeSuffix(newValue);
}
//------------------------------------------------------------------------------
@@ -3838,11 +2434,7 @@ DecimalFormat::setNegativeSuffix(const UnicodeString& newValue)
int32_t
DecimalFormat::getMultiplier() const
{
- if (fMultiplier == NULL) {
- return 1;
- } else {
- return fMultiplier->getLong();
- }
+ return fImpl->getMultiplier();
}
//------------------------------------------------------------------------------
@@ -3850,26 +2442,7 @@ DecimalFormat::getMultiplier() const
void
DecimalFormat::setMultiplier(int32_t newValue)
{
-// if (newValue == 0) {
-// throw new IllegalArgumentException("Bad multiplier: " + newValue);
-// }
- if (newValue == 0) {
- newValue = 1; // one being the benign default value for a multiplier.
- }
- if (newValue == 1) {
- delete fMultiplier;
- fMultiplier = NULL;
- } else {
- if (fMultiplier == NULL) {
- fMultiplier = new DigitList;
- }
- if (fMultiplier != NULL) {
- fMultiplier->set(newValue);
- }
- }
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setMultiplier(newValue);
}
/**
@@ -3881,11 +2454,7 @@ DecimalFormat::setMultiplier(int32_t newValue)
* @see #setRoundingMode
*/
double DecimalFormat::getRoundingIncrement() const {
- if (fRoundingIncrement == NULL) {
- return 0.0;
- } else {
- return fRoundingIncrement->getDouble();
- }
+ return fImpl->getRoundingIncrement();
}
/**
@@ -3898,22 +2467,7 @@ double DecimalFormat::getRoundingIncrement() const {
* @see #setRoundingMode
*/
void DecimalFormat::setRoundingIncrement(double newValue) {
- if (newValue > 0.0) {
- if (fRoundingIncrement == NULL) {
- fRoundingIncrement = new DigitList();
- }
- if (fRoundingIncrement != NULL) {
- fRoundingIncrement->set(newValue);
- return;
- }
- }
- // These statements are executed if newValue is less than 0.0
- // or fRoundingIncrement could not be created.
- delete fRoundingIncrement;
- fRoundingIncrement = NULL;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setRoundingIncrement(newValue);
}
/**
@@ -3924,7 +2478,7 @@ void DecimalFormat::setRoundingIncrement(double newValue) {
* @see #setRoundingMode
*/
DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
- return fRoundingMode;
+ return fImpl->getRoundingMode();
}
/**
@@ -3936,10 +2490,7 @@ DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const {
* @see #getRoundingMode
*/
void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
- fRoundingMode = roundingMode;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setRoundingMode(roundingMode);
}
/**
@@ -3952,7 +2503,7 @@ void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
* @see #setPadPosition
*/
int32_t DecimalFormat::getFormatWidth() const {
- return fFormatWidth;
+ return fImpl->getFormatWidth();
}
/**
@@ -3968,26 +2519,40 @@ int32_t DecimalFormat::getFormatWidth() const {
* @see #setPadPosition
*/
void DecimalFormat::setFormatWidth(int32_t width) {
- fFormatWidth = (width > 0) ? width : 0;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ int32_t formatWidth = (width > 0) ? width : 0;
+ fImpl->setFormatWidth(formatWidth);
}
UnicodeString DecimalFormat::getPadCharacterString() const {
- return UnicodeString(fPad);
+ return UnicodeString(fImpl->getPadCharacter());
}
void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
+ UChar pad;
if (padChar.length() > 0) {
- fPad = padChar.char32At(0);
+ pad = padChar.char32At(0);
}
else {
- fPad = kDefaultPad;
+ pad = kDefaultPad;
}
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setPadCharacter(pad);
+}
+
+static DecimalFormat::EPadPosition fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos) {
+ switch (padPos) {
+ case DigitAffixesAndPadding::kPadBeforePrefix:
+ return DecimalFormat::kPadBeforePrefix;
+ case DigitAffixesAndPadding::kPadAfterPrefix:
+ return DecimalFormat::kPadAfterPrefix;
+ case DigitAffixesAndPadding::kPadBeforeSuffix:
+ return DecimalFormat::kPadBeforeSuffix;
+ case DigitAffixesAndPadding::kPadAfterSuffix:
+ return DecimalFormat::kPadAfterSuffix;
+ default:
+ U_ASSERT(FALSE);
+ break;
+ }
+ return DecimalFormat::kPadBeforePrefix;
}
/**
@@ -4008,7 +2573,24 @@ void DecimalFormat::setPadCharacter(const UnicodeString &padChar) {
* @see #kPadAfterSuffix
*/
DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
- return fPadPosition;
+ return fromPadPosition(fImpl->getPadPosition());
+}
+
+static DigitAffixesAndPadding::EPadPosition toPadPosition(DecimalFormat::EPadPosition padPos) {
+ switch (padPos) {
+ case DecimalFormat::kPadBeforePrefix:
+ return DigitAffixesAndPadding::kPadBeforePrefix;
+ case DecimalFormat::kPadAfterPrefix:
+ return DigitAffixesAndPadding::kPadAfterPrefix;
+ case DecimalFormat::kPadBeforeSuffix:
+ return DigitAffixesAndPadding::kPadBeforeSuffix;
+ case DecimalFormat::kPadAfterSuffix:
+ return DigitAffixesAndPadding::kPadAfterSuffix;
+ default:
+ U_ASSERT(FALSE);
+ break;
+ }
+ return DigitAffixesAndPadding::kPadBeforePrefix;
}
/**
@@ -4031,10 +2613,7 @@ DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const {
* @see #kPadAfterSuffix
*/
void DecimalFormat::setPadPosition(EPadPosition padPos) {
- fPadPosition = padPos;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setPadPosition(toPadPosition(padPos));
}
/**
@@ -4047,7 +2626,7 @@ void DecimalFormat::setPadPosition(EPadPosition padPos) {
* @see #setExponentSignAlwaysShown
*/
UBool DecimalFormat::isScientificNotation() const {
- return fUseExponentialNotation;
+ return fImpl->isScientificNotation();
}
/**
@@ -4061,10 +2640,7 @@ UBool DecimalFormat::isScientificNotation() const {
* @see #setExponentSignAlwaysShown
*/
void DecimalFormat::setScientificNotation(UBool useScientific) {
- fUseExponentialNotation = useScientific;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setScientificNotation(useScientific);
}
/**
@@ -4077,7 +2653,7 @@ void DecimalFormat::setScientificNotation(UBool useScientific) {
* @see #setExponentSignAlwaysShown
*/
int8_t DecimalFormat::getMinimumExponentDigits() const {
- return fMinExponentDigits;
+ return fImpl->getMinimumExponentDigits();
}
/**
@@ -4092,10 +2668,8 @@ int8_t DecimalFormat::getMinimumExponentDigits() const {
* @see #setExponentSignAlwaysShown
*/
void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
- fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
+ fImpl->setMinimumExponentDigits(minExponentDigits);
}
/**
@@ -4110,7 +2684,7 @@ void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
* @see #setExponentSignAlwaysShown
*/
UBool DecimalFormat::isExponentSignAlwaysShown() const {
- return fExponentSignAlwaysShown;
+ return fImpl->isExponentSignAlwaysShown();
}
/**
@@ -4126,10 +2700,7 @@ UBool DecimalFormat::isExponentSignAlwaysShown() const {
* @see #isExponentSignAlwaysShown
*/
void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
- fExponentSignAlwaysShown = expSignAlways;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setExponentSignAlwaysShown(expSignAlways);
}
//------------------------------------------------------------------------------
@@ -4139,7 +2710,7 @@ void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
int32_t
DecimalFormat::getGroupingSize() const
{
- return isGroupingUsed() ? fGroupingSize : 0;
+ return fImpl->getGroupingSize();
}
//------------------------------------------------------------------------------
@@ -4148,10 +2719,7 @@ DecimalFormat::getGroupingSize() const
void
DecimalFormat::setGroupingSize(int32_t newValue)
{
- fGroupingSize = newValue;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setGroupingSize(newValue);
}
//------------------------------------------------------------------------------
@@ -4159,7 +2727,7 @@ DecimalFormat::setGroupingSize(int32_t newValue)
int32_t
DecimalFormat::getSecondaryGroupingSize() const
{
- return fGroupingSize2;
+ return fImpl->getSecondaryGroupingSize();
}
//------------------------------------------------------------------------------
@@ -4167,10 +2735,23 @@ DecimalFormat::getSecondaryGroupingSize() const
void
DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
{
- fGroupingSize2 = newValue;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setSecondaryGroupingSize(newValue);
+}
+
+//------------------------------------------------------------------------------
+
+int32_t
+DecimalFormat::getMinimumGroupingDigits() const
+{
+ return fImpl->getMinimumGroupingDigits();
+}
+
+//------------------------------------------------------------------------------
+
+void
+DecimalFormat::setMinimumGroupingDigits(int32_t newValue)
+{
+ fImpl->setMinimumGroupingDigits(newValue);
}
//------------------------------------------------------------------------------
@@ -4179,7 +2760,7 @@ DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
UBool
DecimalFormat::isDecimalSeparatorAlwaysShown() const
{
- return fDecimalSeparatorAlwaysShown;
+ return fImpl->isDecimalSeparatorAlwaysShown();
}
//------------------------------------------------------------------------------
@@ -4188,10 +2769,7 @@ DecimalFormat::isDecimalSeparatorAlwaysShown() const
void
DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
{
- fDecimalSeparatorAlwaysShown = newValue;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setDecimalSeparatorAlwaysShown(newValue);
}
//------------------------------------------------------------------------------
@@ -4218,7 +2796,7 @@ DecimalFormat::setDecimalPatternMatchRequired(UBool newValue)
UnicodeString&
DecimalFormat::toPattern(UnicodeString& result) const
{
- return toPattern(result, FALSE);
+ return fImpl->toPattern(result);
}
//------------------------------------------------------------------------------
@@ -4227,690 +2805,9 @@ DecimalFormat::toPattern(UnicodeString& result) const
UnicodeString&
DecimalFormat::toLocalizedPattern(UnicodeString& result) const
{
- return toPattern(result, TRUE);
-}
-
-//------------------------------------------------------------------------------
-/**
- * Expand the affix pattern strings into the expanded affix strings. If any
- * affix pattern string is null, do not expand it. This method should be
- * called any time the symbols or the affix patterns change in order to keep
- * the expanded affix strings up to date.
- * This method also will be called before formatting if format currency
- * plural names, since the plural name is not a static one, it is
- * based on the currency plural count, the affix will be known only
- * after the currency plural count is know.
- * In which case, the parameter
- * 'pluralCount' will be a non-null currency plural count.
- * In all other cases, the 'pluralCount' is null, which means it is not needed.
- */
-void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
- FieldPositionHandler none;
- if (fPosPrefixPattern != 0) {
- expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCount);
- }
- if (fPosSuffixPattern != 0) {
- expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCount);
- }
- if (fNegPrefixPattern != 0) {
- expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCount);
- }
- if (fNegSuffixPattern != 0) {
- expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCount);
- }
-#ifdef FMT_DEBUG
- UnicodeString s;
- s.append(UnicodeString("["))
- .append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fPosSuffixPattern))
- .append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fNegSuffixPattern))
- .append((UnicodeString)"]->[")
- .append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuffix)
- .append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeString)"|").append(fNegativeSuffix)
- .append((UnicodeString)"]\n");
- debugout(s);
-#endif
-}
-
-/**
- * Expand an affix pattern into an affix string. All characters in the
- * pattern are literal unless prefixed by kQuote. The following characters
- * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
- * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
- * kCurrencySign + kCurrencySign), it is interpreted as an international
- * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
- * currency plural long names, such as "US Dollars".
- * Any other character after a kQuote represents itself.
- * kQuote must be followed by another character; kQuote may not occur by
- * itself at the end of the pattern.
- *
- * This method is used in two distinct ways. First, it is used to expand
- * the stored affix patterns into actual affixes. For this usage, doFormat
- * must be false. Second, it is used to expand the stored affix patterns
- * given a specific number (doFormat == true), for those rare cases in
- * which a currency format references a ChoiceFormat (e.g., en_IN display
- * name for INR). The number itself is taken from digitList.
- *
- * When used in the first way, this method has a side effect: It sets
- * currencyChoice to a ChoiceFormat object, if the currency's display name
- * in this locale is a ChoiceFormat pattern (very rare). It only does this
- * if currencyChoice is null to start with.
- *
- * @param pattern the non-null, fPossibly empty pattern
- * @param affix string to receive the expanded equivalent of pattern.
- * Previous contents are deleted.
- * @param doFormat if false, then the pattern will be expanded, and if a
- * currency symbol is encountered that expands to a ChoiceFormat, the
- * currencyChoice member variable will be initialized if it is null. If
- * doFormat is true, then it is assumed that the currencyChoice has been
- * created, and it will be used to format the value in digitList.
- * @param pluralCount the plural count. It is only used for currency
- * plural format. In which case, it is the plural
- * count of the currency amount. For example,
- * in en_US, it is the singular "one", or the plural
- * "other". For all other cases, it is null, and
- * is not being used.
- */
-void DecimalFormat::expandAffix(const UnicodeString& pattern,
- UnicodeString& affix,
- double number,
- FieldPositionHandler& handler,
- UBool doFormat,
- const UnicodeString* pluralCount) const {
- affix.remove();
- for (int i=0; i<pattern.length(); ) {
- UChar32 c = pattern.char32At(i);
- i += U16_LENGTH(c);
- if (c == kQuote) {
- c = pattern.char32At(i);
- i += U16_LENGTH(c);
- int beginIdx = affix.length();
- switch (c) {
- case kCurrencySign: {
- // As of ICU 2.2 we use the currency object, and
- // ignore the currency symbols in the DFS, unless
- // we have a null currency object. This occurs if
- // resurrecting a pre-2.2 object or if the user
- // sets a custom DFS.
- UBool intl = i<pattern.length() &&
- pattern.char32At(i) == kCurrencySign;
- UBool plural = FALSE;
- if (intl) {
- ++i;
- plural = i<pattern.length() &&
- pattern.char32At(i) == kCurrencySign;
- if (plural) {
- intl = FALSE;
- ++i;
- }
- }
- const UChar* currencyUChars = getCurrency();
- if (currencyUChars[0] != 0) {
- UErrorCode ec = U_ZERO_ERROR;
- if (plural && pluralCount != NULL) {
- // plural name is only needed when pluralCount != null,
- // which means when formatting currency plural names.
- // For other cases, pluralCount == null,
- // and plural names are not needed.
- int32_t len;
- CharString pluralCountChar;
- pluralCountChar.appendInvariantChars(*pluralCount, ec);
- UBool isChoiceFormat;
- const UChar* s = ucurr_getPluralName(currencyUChars,
- fSymbols != NULL ? fSymbols->getLocale().getName() :
- Locale::getDefault().getName(), &isChoiceFormat,
- pluralCountChar.data(), &len, &ec);
- affix += UnicodeString(s, len);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- } else if(intl) {
- affix.append(currencyUChars, -1);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- } else {
- int32_t len;
- UBool isChoiceFormat;
- // If fSymbols is NULL, use default locale
- const UChar* s = ucurr_getName(currencyUChars,
- fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(),
- UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
- if (isChoiceFormat) {
- // Two modes here: If doFormat is false, we set up
- // currencyChoice. If doFormat is true, we use the
- // previously created currencyChoice to format the
- // value in digitList.
- if (!doFormat) {
- // If the currency is handled by a ChoiceFormat,
- // then we're not going to use the expanded
- // patterns. Instantiate the ChoiceFormat and
- // return.
- if (fCurrencyChoice == NULL) {
- // TODO Replace double-check with proper thread-safe code
- ChoiceFormat* fmt = new ChoiceFormat(UnicodeString(s), ec);
- if (U_SUCCESS(ec)) {
- umtx_lock(NULL);
- if (fCurrencyChoice == NULL) {
- // Cast away const
- ((DecimalFormat*)this)->fCurrencyChoice = fmt;
- fmt = NULL;
- }
- umtx_unlock(NULL);
- delete fmt;
- }
- }
- // We could almost return null or "" here, since the
- // expanded affixes are almost not used at all
- // in this situation. However, one method --
- // toPattern() -- still does use the expanded
- // affixes, in order to set up a padding
- // pattern. We use the CURRENCY_SIGN as a
- // placeholder.
- affix.append(kCurrencySign);
- } else {
- if (fCurrencyChoice != NULL) {
- FieldPosition pos(0); // ignored
- if (number < 0) {
- number = -number;
- }
- fCurrencyChoice->format(number, affix, pos);
- } else {
- // We only arrive here if the currency choice
- // format in the locale data is INVALID.
- affix.append(currencyUChars, -1);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- }
- }
- continue;
- }
- affix += UnicodeString(s, len);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- }
- } else {
- if(intl) {
- affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
- } else {
- affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
- }
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- }
- break;
- }
- case kPatternPercent:
- affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
- handler.addAttribute(kPercentField, beginIdx, affix.length());
- break;
- case kPatternPerMill:
- affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
- handler.addAttribute(kPermillField, beginIdx, affix.length());
- break;
- case kPatternPlus:
- affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- handler.addAttribute(kSignField, beginIdx, affix.length());
- break;
- case kPatternMinus:
- affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- handler.addAttribute(kSignField, beginIdx, affix.length());
- break;
- default:
- affix.append(c);
- break;
- }
- }
- else {
- affix.append(c);
- }
- }
-}
-
-/**
- * Append an affix to the given StringBuffer.
- * @param buf buffer to append to
- * @param isNegative
- * @param isPrefix
- */
-int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
- FieldPositionHandler& handler,
- UBool isNegative, UBool isPrefix) const {
- // plural format precedes choice format
- if (fCurrencyChoice != 0 &&
- fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
- const UnicodeString* affixPat;
- if (isPrefix) {
- affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern;
- } else {
- affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern;
- }
- if (affixPat) {
- UnicodeString affixBuf;
- expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL);
- buf.append(affixBuf);
- return affixBuf.length();
- }
- // else someone called a function that reset the pattern.
- }
-
- const UnicodeString* affix;
- if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
- // TODO: get an accurate count of visible fraction digits.
- UnicodeString pluralCount;
- int32_t minFractionDigits = this->getMinimumFractionDigits();
- if (minFractionDigits > 0) {
- FixedDecimal ni(number, this->getMinimumFractionDigits());
- pluralCount = fCurrencyPluralInfo->getPluralRules()->select(ni);
- } else {
- pluralCount = fCurrencyPluralInfo->getPluralRules()->select(number);
- }
- AffixesForCurrency* oneSet;
- if (fStyle == UNUM_CURRENCY_PLURAL) {
- oneSet = (AffixesForCurrency*)fPluralAffixesForCurrency->get(pluralCount);
- } else {
- oneSet = (AffixesForCurrency*)fAffixesForCurrency->get(pluralCount);
- }
- if (isPrefix) {
- affix = isNegative ? &oneSet->negPrefixForCurrency :
- &oneSet->posPrefixForCurrency;
- } else {
- affix = isNegative ? &oneSet->negSuffixForCurrency :
- &oneSet->posSuffixForCurrency;
- }
- } else {
- if (isPrefix) {
- affix = isNegative ? &fNegativePrefix : &fPositivePrefix;
- } else {
- affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
- }
- }
-
- int32_t begin = (int) buf.length();
-
- buf.append(*affix);
-
- if (handler.isRecording()) {
- int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
- handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
- handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- handler.addAttribute(kSignField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
- handler.addAttribute(kPercentField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
- handler.addAttribute(kPermillField, begin + offset, begin + offset + aff.length());
- }
- }
- return affix->length();
-}
-
-/**
- * Appends an affix pattern to the given StringBuffer, quoting special
- * characters as needed. Uses the internal affix pattern, if that exists,
- * or the literal affix, if the internal affix pattern is null. The
- * appended string will generate the same affix pattern (or literal affix)
- * when passed to toPattern().
- *
- * @param appendTo the affix string is appended to this
- * @param affixPattern a pattern such as fPosPrefixPattern; may be null
- * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
- * Ignored unless affixPattern is null. If affixPattern is null, then
- * expAffix is appended as a literal affix.
- * @param localized true if the appended pattern should contain localized
- * pattern characters; otherwise, non-localized pattern chars are appended
- */
-void DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
- const UnicodeString* affixPattern,
- const UnicodeString& expAffix,
- UBool localized) const {
- if (affixPattern == 0) {
- appendAffixPattern(appendTo, expAffix, localized);
- } else {
- int i;
- for (int pos=0; pos<affixPattern->length(); pos=i) {
- i = affixPattern->indexOf(kQuote, pos);
- if (i < 0) {
- UnicodeString s;
- affixPattern->extractBetween(pos, affixPattern->length(), s);
- appendAffixPattern(appendTo, s, localized);
- break;
- }
- if (i > pos) {
- UnicodeString s;
- affixPattern->extractBetween(pos, i, s);
- appendAffixPattern(appendTo, s, localized);
- }
- UChar32 c = affixPattern->char32At(++i);
- ++i;
- if (c == kQuote) {
- appendTo.append(c).append(c);
- // Fall through and append another kQuote below
- } else if (c == kCurrencySign &&
- i<affixPattern->length() &&
- affixPattern->char32At(i) == kCurrencySign) {
- ++i;
- appendTo.append(c).append(c);
- } else if (localized) {
- switch (c) {
- case kPatternPercent:
- appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
- break;
- case kPatternPerMill:
- appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
- break;
- case kPatternPlus:
- appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- break;
- case kPatternMinus:
- appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- break;
- default:
- appendTo.append(c);
- }
- } else {
- appendTo.append(c);
- }
- }
- }
-}
-
-/**
- * Append an affix to the given StringBuffer, using quotes if
- * there are special characters. Single quotes themselves must be
- * escaped in either case.
- */
-void
-DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
- const UnicodeString& affix,
- UBool localized) const {
- UBool needQuote;
- if(localized) {
- needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0
- || affix.indexOf(kCurrencySign) >= 0;
- }
- else {
- needQuote = affix.indexOf(kPatternZeroDigit) >= 0
- || affix.indexOf(kPatternGroupingSeparator) >= 0
- || affix.indexOf(kPatternDecimalSeparator) >= 0
- || affix.indexOf(kPatternPercent) >= 0
- || affix.indexOf(kPatternPerMill) >= 0
- || affix.indexOf(kPatternDigit) >= 0
- || affix.indexOf(kPatternSeparator) >= 0
- || affix.indexOf(kPatternExponent) >= 0
- || affix.indexOf(kPatternPlus) >= 0
- || affix.indexOf(kPatternMinus) >= 0
- || affix.indexOf(kCurrencySign) >= 0;
- }
- if (needQuote)
- appendTo += (UChar)0x0027 /*'\''*/;
- if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0)
- appendTo += affix;
- else {
- for (int32_t j = 0; j < affix.length(); ) {
- UChar32 c = affix.char32At(j);
- j += U16_LENGTH(c);
- appendTo += c;
- if (c == 0x0027 /*'\''*/)
- appendTo += c;
- }
- }
- if (needQuote)
- appendTo += (UChar)0x0027 /*'\''*/;
-}
-
-//------------------------------------------------------------------------------
-
-UnicodeString&
-DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
-{
- if (fStyle == UNUM_CURRENCY_PLURAL) {
- // the prefix or suffix pattern might not be defined yet,
- // so they can not be synthesized,
- // instead, get them directly.
- // but it might not be the actual pattern used in formatting.
- // the actual pattern used in formatting depends on the
- // formatted number's plural count.
- result = fFormatPattern;
- return result;
- }
- result.remove();
- UChar32 zero, sigDigit = kPatternSignificantDigit;
- UnicodeString digit, group;
- int32_t i;
- int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits
- UnicodeString roundingDigits;
- int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1;
- UnicodeString padSpec;
- UBool useSigDig = areSignificantDigitsUsed();
-
- if (localized) {
- digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
- group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
- zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
- if (useSigDig) {
- sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
- }
- }
- else {
- digit.append((UChar)kPatternDigit);
- group.append((UChar)kPatternGroupingSeparator);
- zero = (UChar32)kPatternZeroDigit;
- }
- if (fFormatWidth > 0) {
- if (localized) {
- padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
- }
- else {
- padSpec.append((UChar)kPatternPadEscape);
- }
- padSpec.append(fPad);
- }
- if (fRoundingIncrement != NULL) {
- for(i=0; i<fRoundingIncrement->getCount(); ++i) {
- roundingDigits.append(zero+(fRoundingIncrement->getDigitValue(i))); // Convert to Unicode digit
- }
- roundingDecimalPos = fRoundingIncrement->getDecimalAt();
- }
- for (int32_t part=0; part<2; ++part) {
- if (padPos == kPadBeforePrefix) {
- result.append(padSpec);
- }
- appendAffixPattern(result,
- (part==0 ? fPosPrefixPattern : fNegPrefixPattern),
- (part==0 ? fPositivePrefix : fNegativePrefix),
- localized);
- if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- int32_t sub0Start = result.length();
- int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0;
- if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
- g += fGroupingSize2;
- }
- int32_t maxDig = 0, minDig = 0, maxSigDig = 0;
- if (useSigDig) {
- minDig = getMinimumSignificantDigits();
- maxDig = maxSigDig = getMaximumSignificantDigits();
- } else {
- minDig = getMinimumIntegerDigits();
- maxDig = getMaximumIntegerDigits();
- }
- if (fUseExponentialNotation) {
- if (maxDig > kMaxScientificIntegerDigits) {
- maxDig = 1;
- }
- } else if (useSigDig) {
- maxDig = _max(maxDig, g+1);
- } else {
- maxDig = _max(_max(g, getMinimumIntegerDigits()),
- roundingDecimalPos) + 1;
- }
- for (i = maxDig; i > 0; --i) {
- if (!fUseExponentialNotation && i<maxDig &&
- isGroupingPosition(i)) {
- result.append(group);
- }
- if (useSigDig) {
- // #@,@### (maxSigDig == 5, minSigDig == 2)
- // 65 4321 (1-based pos, count from the right)
- // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
- // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
- if (maxSigDig >= i && i > (maxSigDig - minDig)) {
- result.append(sigDigit);
- } else {
- result.append(digit);
- }
- } else {
- if (! roundingDigits.isEmpty()) {
- int32_t pos = roundingDecimalPos - i;
- if (pos >= 0 && pos < roundingDigits.length()) {
- result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
- continue;
- }
- }
- if (i<=minDig) {
- result.append(zero);
- } else {
- result.append(digit);
- }
- }
- }
- if (!useSigDig) {
- if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
- }
- else {
- result.append((UChar)kPatternDecimalSeparator);
- }
- }
- int32_t pos = roundingDecimalPos;
- for (i = 0; i < getMaximumFractionDigits(); ++i) {
- if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) {
- if (pos < 0) {
- result.append(zero);
- }
- else {
- result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
- }
- ++pos;
- continue;
- }
- if (i<getMinimumFractionDigits()) {
- result.append(zero);
- }
- else {
- result.append(digit);
- }
- }
- }
- if (fUseExponentialNotation) {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
- }
- else {
- result.append((UChar)kPatternExponent);
- }
- if (fExponentSignAlwaysShown) {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- }
- else {
- result.append((UChar)kPatternPlus);
- }
- }
- for (i=0; i<fMinExponentDigits; ++i) {
- result.append(zero);
- }
- }
- if (! padSpec.isEmpty() && !fUseExponentialNotation) {
- int32_t add = fFormatWidth - result.length() + sub0Start
- - ((part == 0)
- ? fPositivePrefix.length() + fPositiveSuffix.length()
- : fNegativePrefix.length() + fNegativeSuffix.length());
- while (add > 0) {
- result.insert(sub0Start, digit);
- ++maxDig;
- --add;
- // Only add a grouping separator if we have at least
- // 2 additional characters to be added, so we don't
- // end up with ",###".
- if (add>1 && isGroupingPosition(maxDig)) {
- result.insert(sub0Start, group);
- --add;
- }
- }
- }
- if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- if (part == 0) {
- appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized);
- if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- UBool isDefault = FALSE;
- if ((fNegSuffixPattern == fPosSuffixPattern && // both null
- fNegativeSuffix == fPositiveSuffix)
- || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 &&
- *fNegSuffixPattern == *fPosSuffixPattern))
- {
- if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL)
- {
- int32_t length = fPosPrefixPattern->length();
- isDefault = fNegPrefixPattern->length() == (length+2) &&
- (*fNegPrefixPattern)[(int32_t)0] == kQuote &&
- (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus &&
- fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0;
- }
- if (!isDefault &&
- fNegPrefixPattern == NULL && fPosPrefixPattern == NULL)
- {
- int32_t length = fPositivePrefix.length();
- isDefault = fNegativePrefix.length() == (length+1) &&
- fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 &&
- fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0;
- }
- }
- if (isDefault) {
- break; // Don't output default negative subpattern
- } else {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
- }
- else {
- result.append((UChar)kPatternSeparator);
- }
- }
- } else {
- appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized);
- if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- }
- }
-
- return result;
+ // toLocalizedPattern is deprecated, so we just make it the same as
+ // toPattern.
+ return fImpl->toPattern(result);
}
//------------------------------------------------------------------------------
@@ -4918,8 +2815,7 @@ DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
void
DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status)
{
- UParseError parseError;
- applyPattern(pattern, FALSE, parseError, status);
+ fImpl->applyPattern(pattern, status);
}
//------------------------------------------------------------------------------
@@ -4929,15 +2825,14 @@ DecimalFormat::applyPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
- applyPattern(pattern, FALSE, parseError, status);
+ fImpl->applyPattern(pattern, parseError, status);
}
//------------------------------------------------------------------------------
void
DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status)
{
- UParseError parseError;
- applyPattern(pattern, TRUE,parseError,status);
+ fImpl->applyLocalizedPattern(pattern, status);
}
//------------------------------------------------------------------------------
@@ -4947,160 +2842,20 @@ DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern,
UParseError& parseError,
UErrorCode& status)
{
- applyPattern(pattern, TRUE,parseError,status);
+ fImpl->applyLocalizedPattern(pattern, parseError, status);
}
//------------------------------------------------------------------------------
-void
-DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern,
- UBool localized,
- UParseError& parseError,
- UErrorCode& status)
-{
- if (U_FAILURE(status))
- {
- return;
- }
- DecimalFormatPatternParser patternParser;
- if (localized) {
- patternParser.useSymbols(*fSymbols);
- }
- fFormatPattern = pattern;
- DecimalFormatPattern out;
- patternParser.applyPatternWithoutExpandAffix(
- pattern,
- out,
- parseError,
- status);
- if (U_FAILURE(status)) {
- return;
- }
-
- setMinimumIntegerDigits(out.fMinimumIntegerDigits);
- setMaximumIntegerDigits(out.fMaximumIntegerDigits);
- setMinimumFractionDigits(out.fMinimumFractionDigits);
- setMaximumFractionDigits(out.fMaximumFractionDigits);
- setSignificantDigitsUsed(out.fUseSignificantDigits);
- if (out.fUseSignificantDigits) {
- setMinimumSignificantDigits(out.fMinimumSignificantDigits);
- setMaximumSignificantDigits(out.fMaximumSignificantDigits);
- }
- fUseExponentialNotation = out.fUseExponentialNotation;
- if (out.fUseExponentialNotation) {
- fMinExponentDigits = out.fMinExponentDigits;
- }
- fExponentSignAlwaysShown = out.fExponentSignAlwaysShown;
- fCurrencySignCount = out.fCurrencySignCount;
- setGroupingUsed(out.fGroupingUsed);
- if (out.fGroupingUsed) {
- fGroupingSize = out.fGroupingSize;
- fGroupingSize2 = out.fGroupingSize2;
- }
- setMultiplier(out.fMultiplier);
- fDecimalSeparatorAlwaysShown = out.fDecimalSeparatorAlwaysShown;
- fFormatWidth = out.fFormatWidth;
- if (out.fRoundingIncrementUsed) {
- if (fRoundingIncrement != NULL) {
- *fRoundingIncrement = out.fRoundingIncrement;
- } else {
- fRoundingIncrement = new DigitList(out.fRoundingIncrement);
- /* test for NULL */
- if (fRoundingIncrement == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
- }
- }
- } else {
- setRoundingIncrement(0.0);
- }
- fPad = out.fPad;
- switch (out.fPadPosition) {
- case DecimalFormatPattern::kPadBeforePrefix:
- fPadPosition = kPadBeforePrefix;
- break;
- case DecimalFormatPattern::kPadAfterPrefix:
- fPadPosition = kPadAfterPrefix;
- break;
- case DecimalFormatPattern::kPadBeforeSuffix:
- fPadPosition = kPadBeforeSuffix;
- break;
- case DecimalFormatPattern::kPadAfterSuffix:
- fPadPosition = kPadAfterSuffix;
- break;
- }
- copyString(out.fNegPrefixPattern, out.fNegPatternsBogus, fNegPrefixPattern, status);
- copyString(out.fNegSuffixPattern, out.fNegPatternsBogus, fNegSuffixPattern, status);
- copyString(out.fPosPrefixPattern, out.fPosPatternsBogus, fPosPrefixPattern, status);
- copyString(out.fPosSuffixPattern, out.fPosPatternsBogus, fPosSuffixPattern, status);
-}
-
-
-void
-DecimalFormat::expandAffixAdjustWidth(const UnicodeString* pluralCount) {
- expandAffixes(pluralCount);
- if (fFormatWidth > 0) {
- // Finish computing format width (see above)
- // TODO: how to handle fFormatWidth,
- // need to save in f(Plural)AffixesForCurrecy?
- fFormatWidth += fPositivePrefix.length() + fPositiveSuffix.length();
- }
-}
-
-
-void
-DecimalFormat::applyPattern(const UnicodeString& pattern,
- UBool localized,
- UParseError& parseError,
- UErrorCode& status)
-{
- // do the following re-set first. since they change private data by
- // apply pattern again.
- if (pattern.indexOf(kCurrencySign) != -1) {
- if (fCurrencyPluralInfo == NULL) {
- // initialize currencyPluralInfo if needed
- fCurrencyPluralInfo = new CurrencyPluralInfo(fSymbols->getLocale(), status);
- }
- if (fAffixPatternsForCurrency == NULL) {
- setupCurrencyAffixPatterns(status);
- }
- if (pattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) {
- // only setup the affixes of the current pattern.
- setupCurrencyAffixes(pattern, TRUE, FALSE, status);
- }
- }
- applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
- expandAffixAdjustWidth(NULL);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-
-void
-DecimalFormat::applyPatternInternally(const UnicodeString& pluralCount,
- const UnicodeString& pattern,
- UBool localized,
- UParseError& parseError,
- UErrorCode& status) {
- applyPatternWithoutExpandAffix(pattern, localized, parseError, status);
- expandAffixAdjustWidth(&pluralCount);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-
/**
* Sets the maximum number of digits allowed in the integer portion of a
* number.
* @see NumberFormat#setMaximumIntegerDigits
*/
void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
- NumberFormat::setMaximumIntegerDigits(_min(newValue, gDefaultMaxIntegerDigits));
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ newValue = _min(newValue, gDefaultMaxIntegerDigits);
+ NumberFormat::setMaximumIntegerDigits(newValue);
+ fImpl->updatePrecision();
}
/**
@@ -5109,10 +2864,9 @@ void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
* @see NumberFormat#setMinimumIntegerDigits
*/
void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
- NumberFormat::setMinimumIntegerDigits(_min(newValue, kDoubleIntegerDigits));
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ newValue = _min(newValue, kDoubleIntegerDigits);
+ NumberFormat::setMinimumIntegerDigits(newValue);
+ fImpl->updatePrecision();
}
/**
@@ -5121,10 +2875,9 @@ void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
* @see NumberFormat#setMaximumFractionDigits
*/
void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
- NumberFormat::setMaximumFractionDigits(_min(newValue, kDoubleFractionDigits));
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ newValue = _min(newValue, kDoubleFractionDigits);
+ NumberFormat::setMaximumFractionDigits(newValue);
+ fImpl->updatePrecision();
}
/**
@@ -5133,18 +2886,17 @@ void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
* @see NumberFormat#setMinimumFractionDigits
*/
void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
- NumberFormat::setMinimumFractionDigits(_min(newValue, kDoubleFractionDigits));
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ newValue = _min(newValue, kDoubleFractionDigits);
+ NumberFormat::setMinimumFractionDigits(newValue);
+ fImpl->updatePrecision();
}
int32_t DecimalFormat::getMinimumSignificantDigits() const {
- return fMinSignificantDigits;
+ return fImpl->getMinimumSignificantDigits();
}
int32_t DecimalFormat::getMaximumSignificantDigits() const {
- return fMaxSignificantDigits;
+ return fImpl->getMaximumSignificantDigits();
}
void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
@@ -5152,13 +2904,8 @@ void DecimalFormat::setMinimumSignificantDigits(int32_t min) {
min = 1;
}
// pin max sig dig to >= min
- int32_t max = _max(fMaxSignificantDigits, min);
- fMinSignificantDigits = min;
- fMaxSignificantDigits = max;
- fUseSignificantDigits = TRUE;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ int32_t max = _max(fImpl->fMaxSigDigits, min);
+ fImpl->setMinMaxSignificantDigits(min, max);
}
void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
@@ -5166,113 +2913,41 @@ void DecimalFormat::setMaximumSignificantDigits(int32_t max) {
max = 1;
}
// pin min sig dig to 1..max
- U_ASSERT(fMinSignificantDigits >= 1);
- int32_t min = _min(fMinSignificantDigits, max);
- fMinSignificantDigits = min;
- fMaxSignificantDigits = max;
- fUseSignificantDigits = TRUE;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ U_ASSERT(fImpl->fMinSigDigits >= 1);
+ int32_t min = _min(fImpl->fMinSigDigits, max);
+ fImpl->setMinMaxSignificantDigits(min, max);
}
UBool DecimalFormat::areSignificantDigitsUsed() const {
- return fUseSignificantDigits;
+ return fImpl->areSignificantDigitsUsed();
}
void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
- fUseSignificantDigits = useSignificantDigits;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-void DecimalFormat::setCurrencyInternally(const UChar* theCurrency,
- UErrorCode& ec) {
- // If we are a currency format, then modify our affixes to
- // encode the currency symbol for the given currency in our
- // locale, and adjust the decimal digits and rounding for the
- // given currency.
-
- // Note: The code is ordered so that this object is *not changed*
- // until we are sure we are going to succeed.
-
- // NULL or empty currency is *legal* and indicates no currency.
- UBool isCurr = (theCurrency && *theCurrency);
-
- double rounding = 0.0;
- int32_t frac = 0;
- if (fCurrencySignCount != fgCurrencySignCountZero && isCurr) {
- rounding = ucurr_getRoundingIncrementForUsage(theCurrency, fCurrencyUsage, &ec);
- frac = ucurr_getDefaultFractionDigitsForUsage(theCurrency, fCurrencyUsage, &ec);
- }
-
- NumberFormat::setCurrency(theCurrency, ec);
- if (U_FAILURE(ec)) return;
-
- if (fCurrencySignCount != fgCurrencySignCountZero) {
- // NULL or empty currency is *legal* and indicates no currency.
- if (isCurr) {
- setRoundingIncrement(rounding);
- setMinimumFractionDigits(frac);
- setMaximumFractionDigits(frac);
- }
- expandAffixes(NULL);
- }
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->setSignificantDigitsUsed(useSignificantDigits);
}
void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) {
// set the currency before compute affixes to get the right currency names
NumberFormat::setCurrency(theCurrency, ec);
- if (fFormatPattern.indexOf(fgTripleCurrencySign, 3, 0) != -1) {
- UnicodeString savedPtn = fFormatPattern;
- setupCurrencyAffixes(fFormatPattern, TRUE, TRUE, ec);
- UParseError parseErr;
- applyPattern(savedPtn, FALSE, parseErr, ec);
- }
- // set the currency after apply pattern to get the correct rounding/fraction
- setCurrencyInternally(theCurrency, ec);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
+ fImpl->updateCurrency(ec);
}
void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){
- fCurrencyUsage = newContext;
-
- const UChar* theCurrency = getCurrency();
-
- // We set rounding/digit based on currency context
- if(theCurrency){
- double rounding = ucurr_getRoundingIncrementForUsage(theCurrency, fCurrencyUsage, ec);
- int32_t frac = ucurr_getDefaultFractionDigitsForUsage(theCurrency, fCurrencyUsage, ec);
-
- if (U_SUCCESS(*ec)) {
- setRoundingIncrement(rounding);
- setMinimumFractionDigits(frac);
- setMaximumFractionDigits(frac);
- }
- }
+ fImpl->setCurrencyUsage(newContext, *ec);
}
UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
- return fCurrencyUsage;
+ return fImpl->getCurrencyUsage();
}
// Deprecated variant with no UErrorCode parameter
void DecimalFormat::setCurrency(const UChar* theCurrency) {
UErrorCode ec = U_ZERO_ERROR;
setCurrency(theCurrency, ec);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
}
void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
- if (fSymbols == NULL) {
+ if (fImpl->fSymbols == NULL) {
ec = U_MEMORY_ALLOCATION_ERROR;
return;
}
@@ -5280,49 +2955,13 @@ void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
const UChar* c = getCurrency();
if (*c == 0) {
const UnicodeString &intl =
- fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
+ fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
c = intl.getBuffer(); // ok for intl to go out of scope
}
u_strncpy(result, c, 3);
result[3] = 0;
}
-/**
- * Return the number of fraction digits to display, or the total
- * number of digits for significant digit formats and exponential
- * formats.
- */
-int32_t
-DecimalFormat::precision() const {
- if (areSignificantDigitsUsed()) {
- return getMaximumSignificantDigits();
- } else if (fUseExponentialNotation) {
- return getMinimumIntegerDigits() + getMaximumFractionDigits();
- } else {
- return getMaximumFractionDigits();
- }
-}
-
-
-// TODO: template algorithm
-Hashtable*
-DecimalFormat::initHashForAffix(UErrorCode& status) {
- if ( U_FAILURE(status) ) {
- return NULL;
- }
- Hashtable* hTable;
- if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
- if ( U_FAILURE(status) ) {
- delete hTable;
- return NULL;
- }
- hTable->setValueComparator(decimfmtAffixValueComparator);
- return hTable;
-}
-
Hashtable*
DecimalFormat::initHashForAffixPattern(UErrorCode& status) {
if ( U_FAILURE(status) ) {
@@ -5342,31 +2981,12 @@ DecimalFormat::initHashForAffixPattern(UErrorCode& status) {
}
void
-DecimalFormat::deleteHashForAffix(Hashtable*& table)
-{
- if ( table == NULL ) {
- return;
- }
- int32_t pos = -1;
- const UHashElement* element = NULL;
- while ( (element = table->nextElement(pos)) != NULL ) {
- const UHashTok valueTok = element->value;
- const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer;
- delete value;
- }
- delete table;
- table = NULL;
-}
-
-
-
-void
DecimalFormat::deleteHashForAffixPattern()
{
if ( fAffixPatternsForCurrency == NULL ) {
return;
}
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
const UHashElement* element = NULL;
while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) {
const UHashTok valueTok = element->value;
@@ -5385,7 +3005,7 @@ DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
if ( U_FAILURE(status) ) {
return;
}
- int32_t pos = -1;
+ int32_t pos = UHASH_FIRST;
const UHashElement* element = NULL;
if ( source ) {
while ( (element = source->nextElement(pos)) != NULL ) {
@@ -5407,29 +3027,22 @@ DecimalFormat::copyHashForAffixPattern(const Hashtable* source,
}
}
-// this is only overridden to call handleChanged() for fastpath purposes.
void
DecimalFormat::setGroupingUsed(UBool newValue) {
NumberFormat::setGroupingUsed(newValue);
- handleChanged();
+ fImpl->updateGrouping();
}
-// this is only overridden to call handleChanged() for fastpath purposes.
void
DecimalFormat::setParseIntegerOnly(UBool newValue) {
NumberFormat::setParseIntegerOnly(newValue);
- handleChanged();
}
-// this is only overridden to call handleChanged() for fastpath purposes.
-// setContext doesn't affect the fastPath right now, but this is called for completeness
void
DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) {
NumberFormat::setContext(value, status);
- handleChanged();
}
-
DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
int32_t newValue,
UErrorCode &status) {
@@ -5528,16 +3141,24 @@ DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr,
if(!fBoolFlags.isValidValue(newValue)) {
status = U_ILLEGAL_ARGUMENT_ERROR;
} else {
+ if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) {
+ fImpl->setFailIfMoreThanMaxDigits((UBool) newValue);
+ }
fBoolFlags.set(attr, newValue);
}
break;
case UNUM_SCALE:
- fScale = newValue;
+ fImpl->setScale(newValue);
break;
case UNUM_CURRENCY_USAGE:
setCurrencyUsage((UCurrencyUsage)newValue, &status);
+ break;
+
+ case UNUM_MINIMUM_GROUPING_DIGITS:
+ setMinimumGroupingDigits(newValue);
+ break;
default:
status = U_UNSUPPORTED_ERROR;
@@ -5616,10 +3237,13 @@ int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
return fBoolFlags.get(attr);
case UNUM_SCALE:
- return fScale;
+ return fImpl->fScale;
case UNUM_CURRENCY_USAGE:
- return fCurrencyUsage;
+ return fImpl->getCurrencyUsage();
+
+ case UNUM_MINIMUM_GROUPING_DIGITS:
+ return getMinimumGroupingDigits();
default:
status = U_UNSUPPORTED_ERROR;
@@ -5632,41 +3256,9 @@ int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr,
#if UCONFIG_HAVE_PARSEALLINPUT
void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
fParseAllInput = value;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
}
#endif
-void
-DecimalFormat::copyHashForAffix(const Hashtable* source,
- Hashtable* target,
- UErrorCode& status) {
- if ( U_FAILURE(status) ) {
- return;
- }
- int32_t pos = -1;
- const UHashElement* element = NULL;
- if ( source ) {
- while ( (element = source->nextElement(pos)) != NULL ) {
- const UHashTok keyTok = element->key;
- const UnicodeString* key = (UnicodeString*)keyTok.pointer;
-
- const UHashTok valueTok = element->value;
- const AffixesForCurrency* value = (AffixesForCurrency*)valueTok.pointer;
- AffixesForCurrency* copy = new AffixesForCurrency(
- value->negPrefixForCurrency,
- value->negSuffixForCurrency,
- value->posPrefixForCurrency,
- value->posSuffixForCurrency);
- target->put(UnicodeString(*key), copy, status);
- if ( U_FAILURE(status) ) {
- return;
- }
- }
- }
-}
-
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
« no previous file with comments | « source/i18n/decimalformatpatternimpl.h ('k') | source/i18n/decimfmtimpl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698