| 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 = ¤cyPluralPatternForOther;
|
| - // 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 */
|
|
|