Index: source/i18n/decimfmt.cpp |
diff --git a/source/i18n/decimfmt.cpp b/source/i18n/decimfmt.cpp |
index c9d8b0c43a685c4d5c774415402acda55270d33b..da1f8d29f37e316716815f6c65910fbdd1d5b4b6 100644 |
--- a/source/i18n/decimfmt.cpp |
+++ b/source/i18n/decimfmt.cpp |
@@ -1,6 +1,6 @@ |
/* |
******************************************************************************* |
-* Copyright (C) 1997-2013, International Business Machines Corporation and * |
+* Copyright (C) 1997-2014, International Business Machines Corporation and * |
* others. All Rights Reserved. * |
******************************************************************************* |
* |
@@ -71,6 +71,7 @@ |
#include "decfmtst.h" |
#include "dcfmtimp.h" |
#include "plurrule_impl.h" |
+#include "decimalformatpattern.h" |
/* |
* On certain platforms, round is a macro defined in math.h |
@@ -288,6 +289,27 @@ 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. |
@@ -398,6 +420,7 @@ DecimalFormat::init() { |
fAffixesForCurrency = NULL; |
fPluralAffixesForCurrency = NULL; |
fCurrencyPluralInfo = NULL; |
+ fCurrencyUsage = UCURR_USAGE_STANDARD; |
#if UCONFIG_HAVE_PARSEALLINPUT |
fParseAllInput = UNUM_MAYBE; |
#endif |
@@ -791,8 +814,8 @@ DecimalFormat::operator=(const DecimalFormat& rhs) |
fMaxSignificantDigits = rhs.fMaxSignificantDigits; |
fUseSignificantDigits = rhs.fUseSignificantDigits; |
fFormatPattern = rhs.fFormatPattern; |
+ fCurrencyUsage = rhs.fCurrencyUsage; |
fStyle = rhs.fStyle; |
- fCurrencySignCount = rhs.fCurrencySignCount; |
_clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo); |
deleteHashForAffixPattern(); |
if (rhs.fAffixPatternsForCurrency) { |
@@ -813,10 +836,12 @@ DecimalFormat::operator=(const DecimalFormat& rhs) |
fPluralAffixesForCurrency = initHashForAffixPattern(status); |
copyHashForAffix(rhs.fPluralAffixesForCurrency, fPluralAffixesForCurrency, status); |
} |
- } |
#if UCONFIG_FORMAT_FASTPATHS_49 |
- handleChanged(); |
+ DecimalFormatInternal &data = internalData(fReserved); |
+ const DecimalFormatInternal &rhsData = internalData(rhs.fReserved); |
+ data = rhsData; |
#endif |
+ } |
return *this; |
} |
@@ -904,6 +929,10 @@ DecimalFormat::operator==(const Format& that) const |
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()); |
@@ -918,16 +947,25 @@ DecimalFormat::operator==(const Format& that) const |
} |
if (fDecimalSeparatorAlwaysShown != other->fDecimalSeparatorAlwaysShown) { |
if (first) { printf("[ "); first = FALSE; } else { printf(", "); } |
- printf("Dec Sep Always %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown); |
+ printf("fDecimalSeparatorAlwaysShown %d != %d", fDecimalSeparatorAlwaysShown, other->fDecimalSeparatorAlwaysShown); |
} |
if (fUseExponentialNotation != other->fUseExponentialNotation) { |
if (first) { printf("[ "); first = FALSE; } else { printf(", "); } |
- debug("Use Exp !="); |
+ 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 (!(!fUseExponentialNotation || |
- fMinExponentDigits != other->fMinExponentDigits)) { |
+ if (fBoolFlags.getAll() != other->fBoolFlags.getAll()) { |
if (first) { printf("[ "); first = FALSE; } else { printf(", "); } |
- debug("Exp Digits !="); |
+ debug("fBoolFlags !="); |
} |
if (*fSymbols != *(other->fSymbols)) { |
if (first) { printf("[ "); first = FALSE; } else { printf(", "); } |
@@ -935,16 +973,41 @@ DecimalFormat::operator==(const Format& that) const |
} |
// 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) { |
@@ -970,46 +1033,70 @@ DecimalFormat::operator==(const Format& that) const |
} |
#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)) && |
+ 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) && |
+ (fMinExponentDigits == other->fMinExponentDigits && fExponentSignAlwaysShown == other->fExponentSignAlwaysShown)) && |
+ |
+ fBoolFlags.getAll() == other->fBoolFlags.getAll() && |
*fSymbols == *(other->fSymbols) && |
fUseSignificantDigits == other->fUseSignificantDigits && |
+ |
(!fUseSignificantDigits || |
- (fMinSignificantDigits == other->fMinSignificantDigits && |
- fMaxSignificantDigits == other->fMaxSignificantDigits)) && |
+ (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 && |
+ |
((fCurrencyPluralInfo == other->fCurrencyPluralInfo && |
fCurrencyPluralInfo == NULL) || |
(fCurrencyPluralInfo != NULL && other->fCurrencyPluralInfo != NULL && |
- *fCurrencyPluralInfo == *(other->fCurrencyPluralInfo)))); |
+ *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) |
+ ); |
} |
//------------------------------------------------------------------------------ |
@@ -1237,14 +1324,7 @@ void DecimalFormat::handleChanged() { |
debug("parse fastpath: YES"); |
} |
- if (fGroupingSize!=0 && isGroupingUsed()) { |
- debug("No format fastpath: fGroupingSize!=0 and grouping is used"); |
-#ifdef FMT_DEBUG |
- printf("groupingsize=%d\n", fGroupingSize); |
-#endif |
- } else if(fGroupingSize2!=0 && isGroupingUsed()) { |
- debug("No format fastpath: fGroupingSize2!=0"); |
- } else if(fUseExponentialNotation) { |
+ if(fUseExponentialNotation) { |
debug("No format fastpath: fUseExponentialNotation"); |
} else if(fFormatWidth!=0) { |
debug("No format fastpath: fFormatWidth!=0"); |
@@ -1264,6 +1344,17 @@ void DecimalFormat::handleChanged() { |
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!"); |
@@ -1327,7 +1418,9 @@ DecimalFormat::_format(int64_t number, |
printf("fastpath? [%d]\n", number); |
#endif |
- if( data.fFastFormatStatus==kFastpathYES) { |
+ if( data.fFastFormatStatus==kFastpathYES || |
+ data.fFastFormatStatus==kFastpathMAYBE) { |
+ int32_t noGroupingThreshold = 0; |
#define kZero 0x0030 |
const int32_t MAX_IDX = MAX_DIGITS+2; |
@@ -1335,6 +1428,9 @@ DecimalFormat::_format(int64_t number, |
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 |
@@ -1344,10 +1440,12 @@ DecimalFormat::_format(int64_t number, |
} |
// 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); |
@@ -1389,6 +1487,7 @@ DecimalFormat::_format(int64_t number, |
return appendTo; |
} // end fastpath |
#endif |
+ slowPath: |
// Else the slow way - via DigitList |
DigitList digits; |
@@ -1621,6 +1720,13 @@ DecimalFormat::_round(const DigitList &number, DigitList &adjustedNum, UBool& is |
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. |
@@ -2838,6 +2944,18 @@ 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) |
+ { |
+ parsePosition.setIndex(oldStart); |
+ parsePosition.setErrorIndex(position); |
+ debug("decimal point match required fail!"); |
+ return FALSE; |
+ } |
+ } |
+ |
if (backup != -1) |
{ |
position = backup; |
@@ -2951,6 +3069,20 @@ printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.d |
parsePosition.setErrorIndex(position); |
return FALSE; |
} |
+ |
+ // check if we missed a required decimal point |
+ if(fastParseOk && isDecimalPatternMatchRequired()) |
+ { |
+ if(fFormatPattern.indexOf(DecimalFormatSymbols::kDecimalSeparatorSymbol) != 0) |
+ { |
+ parsePosition.setIndex(oldStart); |
+ parsePosition.setErrorIndex(position); |
+ debug("decimal point match required fail!"); |
+ return FALSE; |
+ } |
+ } |
+ |
+ |
return TRUE; |
} |
@@ -3046,12 +3178,12 @@ UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, Uni |
for (affixPos = 0; affixPos < affixLen; affixPos++) { |
UChar c = affix.charAt(affixPos); |
if (!IS_BIDI_MARK(c)) { |
- if (trimLen < TRIM_BUFLEN) { |
- trimBuf[trimLen++] = c; |
- } else { |
- trimLen = 0; |
- break; |
- } |
+ if (trimLen < TRIM_BUFLEN) { |
+ trimBuf[trimLen++] = c; |
+ } else { |
+ trimLen = 0; |
+ break; |
+ } |
} |
} |
return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix); |
@@ -3344,8 +3476,8 @@ int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat, |
UChar effectiveCurr[4]; |
getEffectiveCurrency(effectiveCurr, ec); |
if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) { |
- pos = -1; |
- continue; |
+ pos = -1; |
+ continue; |
} |
} |
pos = ppos.getIndex(); |
@@ -4007,7 +4139,7 @@ void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { |
int32_t |
DecimalFormat::getGroupingSize() const |
{ |
- return fGroupingSize; |
+ return isGroupingUsed() ? fGroupingSize : 0; |
} |
//------------------------------------------------------------------------------ |
@@ -4063,6 +4195,24 @@ DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) |
} |
//------------------------------------------------------------------------------ |
+// Checks if decimal point pattern match is required |
+UBool |
+DecimalFormat::isDecimalPatternMatchRequired(void) const |
+{ |
+ return fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED); |
+} |
+ |
+//------------------------------------------------------------------------------ |
+// Checks if decimal point pattern match is required |
+ |
+void |
+DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) |
+{ |
+ fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue); |
+} |
+ |
+ |
+//------------------------------------------------------------------------------ |
// Emits the pattern of this DecimalFormat instance. |
UnicodeString& |
@@ -4812,596 +4962,77 @@ DecimalFormat::applyPatternWithoutExpandAffix(const UnicodeString& pattern, |
{ |
return; |
} |
- // Clear error struct |
- parseError.offset = -1; |
- parseError.preContext[0] = parseError.postContext[0] = (UChar)0; |
- |
- // Set the significant pattern symbols |
- UChar32 zeroDigit = kPatternZeroDigit; // '0' |
- UChar32 sigDigit = kPatternSignificantDigit; // '@' |
- UnicodeString groupingSeparator ((UChar)kPatternGroupingSeparator); |
- UnicodeString decimalSeparator ((UChar)kPatternDecimalSeparator); |
- UnicodeString percent ((UChar)kPatternPercent); |
- UnicodeString perMill ((UChar)kPatternPerMill); |
- UnicodeString digit ((UChar)kPatternDigit); // '#' |
- UnicodeString separator ((UChar)kPatternSeparator); |
- UnicodeString exponent ((UChar)kPatternExponent); |
- UnicodeString plus ((UChar)kPatternPlus); |
- UnicodeString minus ((UChar)kPatternMinus); |
- UnicodeString padEscape ((UChar)kPatternPadEscape); |
- // Substitute with the localized symbols if necessary |
+ DecimalFormatPatternParser patternParser; |
if (localized) { |
- zeroDigit = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); |
- sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); |
- groupingSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)); |
- decimalSeparator. remove().append(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)); |
- percent. remove().append(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)); |
- perMill. remove().append(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)); |
- digit. remove().append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)); |
- separator. remove().append(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)); |
- exponent. remove().append(getConstSymbol(DecimalFormatSymbols::kExponentialSymbol)); |
- plus. remove().append(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)); |
- minus. remove().append(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)); |
- padEscape. remove().append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol)); |
- } |
- UChar nineDigit = (UChar)(zeroDigit + 9); |
- int32_t digitLen = digit.length(); |
- int32_t groupSepLen = groupingSeparator.length(); |
- int32_t decimalSepLen = decimalSeparator.length(); |
- |
- int32_t pos = 0; |
- int32_t patLen = pattern.length(); |
- // Part 0 is the positive pattern. Part 1, if present, is the negative |
- // pattern. |
- for (int32_t part=0; part<2 && pos<patLen; ++part) { |
- // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, |
- // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is |
- // between the prefix and suffix, and consists of pattern |
- // characters. In the prefix and suffix, percent, perMill, and |
- // currency symbols are recognized and translated. |
- int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0; |
- |
- // It's important that we don't change any fields of this object |
- // prematurely. We set the following variables for the multiplier, |
- // grouping, etc., and then only change the actual object fields if |
- // everything parses correctly. This also lets us register |
- // the data from part 0 and ignore the part 1, except for the |
- // prefix and suffix. |
- UnicodeString prefix; |
- UnicodeString suffix; |
- int32_t decimalPos = -1; |
- int32_t multiplier = 1; |
- int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0; |
- int8_t groupingCount = -1; |
- int8_t groupingCount2 = -1; |
- int32_t padPos = -1; |
- UChar32 padChar = 0; |
- int32_t roundingPos = -1; |
- DigitList roundingInc; |
- int8_t expDigits = -1; |
- UBool expSignAlways = FALSE; |
- |
- // The affix is either the prefix or the suffix. |
- UnicodeString* affix = &prefix; |
- |
- int32_t start = pos; |
- UBool isPartDone = FALSE; |
- UChar32 ch; |
- |
- for (; !isPartDone && pos < patLen; ) { |
- // Todo: account for surrogate pairs |
- ch = pattern.char32At(pos); |
- switch (subpart) { |
- case 0: // Pattern proper subpart (between prefix & suffix) |
- // Process the digits, decimal, and grouping characters. We |
- // record five pieces of information. We expect the digits |
- // to occur in the pattern ####00.00####, and we record the |
- // number of left digits, zero (central) digits, and right |
- // digits. The position of the last grouping character is |
- // recorded (should be somewhere within the first two blocks |
- // of characters), as is the position of the decimal point, |
- // if any (should be in the zero digits). If there is no |
- // decimal point, then there should be no right digits. |
- if (pattern.compare(pos, digitLen, digit) == 0) { |
- if (zeroDigitCount > 0 || sigDigitCount > 0) { |
- ++digitRightCount; |
- } else { |
- ++digitLeftCount; |
- } |
- if (groupingCount >= 0 && decimalPos < 0) { |
- ++groupingCount; |
- } |
- pos += digitLen; |
- } else if ((ch >= zeroDigit && ch <= nineDigit) || |
- ch == sigDigit) { |
- if (digitRightCount > 0) { |
- // Unexpected '0' |
- debug("Unexpected '0'") |
- status = U_UNEXPECTED_TOKEN; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- if (ch == sigDigit) { |
- ++sigDigitCount; |
- } else { |
- if (ch != zeroDigit && roundingPos < 0) { |
- roundingPos = digitLeftCount + zeroDigitCount; |
- } |
- if (roundingPos >= 0) { |
- roundingInc.append((char)(ch - zeroDigit + '0')); |
- } |
- ++zeroDigitCount; |
- } |
- if (groupingCount >= 0 && decimalPos < 0) { |
- ++groupingCount; |
- } |
- pos += U16_LENGTH(ch); |
- } else if (pattern.compare(pos, groupSepLen, groupingSeparator) == 0) { |
- if (decimalPos >= 0) { |
- // Grouping separator after decimal |
- debug("Grouping separator after decimal") |
- status = U_UNEXPECTED_TOKEN; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- groupingCount2 = groupingCount; |
- groupingCount = 0; |
- pos += groupSepLen; |
- } else if (pattern.compare(pos, decimalSepLen, decimalSeparator) == 0) { |
- if (decimalPos >= 0) { |
- // Multiple decimal separators |
- debug("Multiple decimal separators") |
- status = U_MULTIPLE_DECIMAL_SEPARATORS; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- // Intentionally incorporate the digitRightCount, |
- // even though it is illegal for this to be > 0 |
- // at this point. We check pattern syntax below. |
- decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; |
- pos += decimalSepLen; |
- } else { |
- if (pattern.compare(pos, exponent.length(), exponent) == 0) { |
- if (expDigits >= 0) { |
- // Multiple exponential symbols |
- debug("Multiple exponential symbols") |
- status = U_MULTIPLE_EXPONENTIAL_SYMBOLS; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- if (groupingCount >= 0) { |
- // Grouping separator in exponential pattern |
- debug("Grouping separator in exponential pattern") |
- status = U_MALFORMED_EXPONENTIAL_PATTERN; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- pos += exponent.length(); |
- // Check for positive prefix |
- if (pos < patLen |
- && pattern.compare(pos, plus.length(), plus) == 0) { |
- expSignAlways = TRUE; |
- pos += plus.length(); |
- } |
- // Use lookahead to parse out the exponential part of the |
- // pattern, then jump into suffix subpart. |
- expDigits = 0; |
- while (pos < patLen && |
- pattern.char32At(pos) == zeroDigit) { |
- ++expDigits; |
- pos += U16_LENGTH(zeroDigit); |
- } |
- |
- // 1. Require at least one mantissa pattern digit |
- // 2. Disallow "#+ @" in mantissa |
- // 3. Require at least one exponent pattern digit |
- if (((digitLeftCount + zeroDigitCount) < 1 && |
- (sigDigitCount + digitRightCount) < 1) || |
- (sigDigitCount > 0 && digitLeftCount > 0) || |
- expDigits < 1) { |
- // Malformed exponential pattern |
- debug("Malformed exponential pattern") |
- status = U_MALFORMED_EXPONENTIAL_PATTERN; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- } |
- // Transition to suffix subpart |
- subpart = 2; // suffix subpart |
- affix = &suffix; |
- sub0Limit = pos; |
- continue; |
- } |
- break; |
- case 1: // Prefix subpart |
- case 2: // Suffix subpart |
- // Process the prefix / suffix characters |
- // Process unquoted characters seen in prefix or suffix |
- // subpart. |
- |
- // Several syntax characters implicitly begins the |
- // next subpart if we are in the prefix; otherwise |
- // they are illegal if unquoted. |
- if (!pattern.compare(pos, digitLen, digit) || |
- !pattern.compare(pos, groupSepLen, groupingSeparator) || |
- !pattern.compare(pos, decimalSepLen, decimalSeparator) || |
- (ch >= zeroDigit && ch <= nineDigit) || |
- ch == sigDigit) { |
- if (subpart == 1) { // prefix subpart |
- subpart = 0; // pattern proper subpart |
- sub0Start = pos; // Reprocess this character |
- continue; |
- } else { |
- status = U_UNQUOTED_SPECIAL; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- } else if (ch == kCurrencySign) { |
- affix->append(kQuote); // Encode currency |
- // Use lookahead to determine if the currency sign is |
- // doubled or not. |
- U_ASSERT(U16_LENGTH(kCurrencySign) == 1); |
- if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) { |
- affix->append(kCurrencySign); |
- ++pos; // Skip over the doubled character |
- if ((pos+1) < pattern.length() && |
- pattern[pos+1] == kCurrencySign) { |
- affix->append(kCurrencySign); |
- ++pos; // Skip over the doubled character |
- fCurrencySignCount = fgCurrencySignCountInPluralFormat; |
- } else { |
- fCurrencySignCount = fgCurrencySignCountInISOFormat; |
- } |
- } else { |
- fCurrencySignCount = fgCurrencySignCountInSymbolFormat; |
- } |
- // Fall through to append(ch) |
- } else if (ch == kQuote) { |
- // A quote outside quotes indicates either the opening |
- // quote or two quotes, which is a quote literal. That is, |
- // we have the first quote in 'do' or o''clock. |
- U_ASSERT(U16_LENGTH(kQuote) == 1); |
- ++pos; |
- if (pos < pattern.length() && pattern[pos] == kQuote) { |
- affix->append(kQuote); // Encode quote |
- // Fall through to append(ch) |
- } else { |
- subpart += 2; // open quote |
- continue; |
- } |
- } else if (pattern.compare(pos, separator.length(), separator) == 0) { |
- // Don't allow separators in the prefix, and don't allow |
- // separators in the second pattern (part == 1). |
- if (subpart == 1 || part == 1) { |
- // Unexpected separator |
- debug("Unexpected separator") |
- status = U_UNEXPECTED_TOKEN; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- sub2Limit = pos; |
- isPartDone = TRUE; // Go to next part |
- pos += separator.length(); |
- break; |
- } else if (pattern.compare(pos, percent.length(), percent) == 0) { |
- // Next handle characters which are appended directly. |
- if (multiplier != 1) { |
- // Too many percent/perMill characters |
- debug("Too many percent characters") |
- status = U_MULTIPLE_PERCENT_SYMBOLS; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- affix->append(kQuote); // Encode percent/perMill |
- affix->append(kPatternPercent); // Use unlocalized pattern char |
- multiplier = 100; |
- pos += percent.length(); |
- break; |
- } else if (pattern.compare(pos, perMill.length(), perMill) == 0) { |
- // Next handle characters which are appended directly. |
- if (multiplier != 1) { |
- // Too many percent/perMill characters |
- debug("Too many perMill characters") |
- status = U_MULTIPLE_PERMILL_SYMBOLS; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- affix->append(kQuote); // Encode percent/perMill |
- affix->append(kPatternPerMill); // Use unlocalized pattern char |
- multiplier = 1000; |
- pos += perMill.length(); |
- break; |
- } else if (pattern.compare(pos, padEscape.length(), padEscape) == 0) { |
- if (padPos >= 0 || // Multiple pad specifiers |
- (pos+1) == pattern.length()) { // Nothing after padEscape |
- debug("Multiple pad specifiers") |
- status = U_MULTIPLE_PAD_SPECIFIERS; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- padPos = pos; |
- pos += padEscape.length(); |
- padChar = pattern.char32At(pos); |
- pos += U16_LENGTH(padChar); |
- break; |
- } else if (pattern.compare(pos, minus.length(), minus) == 0) { |
- affix->append(kQuote); // Encode minus |
- affix->append(kPatternMinus); |
- pos += minus.length(); |
- break; |
- } else if (pattern.compare(pos, plus.length(), plus) == 0) { |
- affix->append(kQuote); // Encode plus |
- affix->append(kPatternPlus); |
- pos += plus.length(); |
- break; |
- } |
- // Unquoted, non-special characters fall through to here, as |
- // well as other code which needs to append something to the |
- // affix. |
- affix->append(ch); |
- pos += U16_LENGTH(ch); |
- break; |
- case 3: // Prefix subpart, in quote |
- case 4: // Suffix subpart, in quote |
- // A quote within quotes indicates either the closing |
- // quote or two quotes, which is a quote literal. That is, |
- // we have the second quote in 'do' or 'don''t'. |
- if (ch == kQuote) { |
- ++pos; |
- if (pos < pattern.length() && pattern[pos] == kQuote) { |
- affix->append(kQuote); // Encode quote |
- // Fall through to append(ch) |
- } else { |
- subpart -= 2; // close quote |
- continue; |
- } |
- } |
- affix->append(ch); |
- pos += U16_LENGTH(ch); |
- break; |
- } |
- } |
- |
- if (sub0Limit == 0) { |
- sub0Limit = pattern.length(); |
- } |
- |
- if (sub2Limit == 0) { |
- sub2Limit = pattern.length(); |
- } |
- |
- /* Handle patterns with no '0' pattern character. These patterns |
- * are legal, but must be recodified to make sense. "##.###" -> |
- * "#0.###". ".###" -> ".0##". |
- * |
- * We allow patterns of the form "####" to produce a zeroDigitCount |
- * of zero (got that?); although this seems like it might make it |
- * possible for format() to produce empty strings, format() checks |
- * for this condition and outputs a zero digit in this situation. |
- * Having a zeroDigitCount of zero yields a minimum integer digits |
- * of zero, which allows proper round-trip patterns. We don't want |
- * "#" to become "#0" when toPattern() is called (even though that's |
- * what it really is, semantically). |
- */ |
- if (zeroDigitCount == 0 && sigDigitCount == 0 && |
- digitLeftCount > 0 && decimalPos >= 0) { |
- // Handle "###.###" and "###." and ".###" |
- int n = decimalPos; |
- if (n == 0) |
- ++n; // Handle ".###" |
- digitRightCount = digitLeftCount - n; |
- digitLeftCount = n - 1; |
- zeroDigitCount = 1; |
- } |
- |
- // Do syntax checking on the digits, decimal points, and quotes. |
- if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || |
- (decimalPos >= 0 && |
- (sigDigitCount > 0 || |
- decimalPos < digitLeftCount || |
- decimalPos > (digitLeftCount + zeroDigitCount))) || |
- groupingCount == 0 || groupingCount2 == 0 || |
- (sigDigitCount > 0 && zeroDigitCount > 0) || |
- subpart > 2) |
- { // subpart > 2 == unmatched quote |
- debug("Syntax error") |
- status = U_PATTERN_SYNTAX_ERROR; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- |
- // Make sure pad is at legal position before or after affix. |
- if (padPos >= 0) { |
- if (padPos == start) { |
- padPos = kPadBeforePrefix; |
- } else if (padPos+2 == sub0Start) { |
- padPos = kPadAfterPrefix; |
- } else if (padPos == sub0Limit) { |
- padPos = kPadBeforeSuffix; |
- } else if (padPos+2 == sub2Limit) { |
- padPos = kPadAfterSuffix; |
- } else { |
- // Illegal pad position |
- debug("Illegal pad position") |
- status = U_ILLEGAL_PAD_POSITION; |
- syntaxError(pattern,pos,parseError); |
- return; |
- } |
- } |
- |
- if (part == 0) { |
- delete fPosPrefixPattern; |
- delete fPosSuffixPattern; |
- delete fNegPrefixPattern; |
- delete fNegSuffixPattern; |
- fPosPrefixPattern = new UnicodeString(prefix); |
- /* test for NULL */ |
- if (fPosPrefixPattern == 0) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- fPosSuffixPattern = new UnicodeString(suffix); |
- /* test for NULL */ |
- if (fPosSuffixPattern == 0) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- delete fPosPrefixPattern; |
- return; |
- } |
- fNegPrefixPattern = 0; |
- fNegSuffixPattern = 0; |
- |
- fUseExponentialNotation = (expDigits >= 0); |
- if (fUseExponentialNotation) { |
- fMinExponentDigits = expDigits; |
- } |
- fExponentSignAlwaysShown = expSignAlways; |
- int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; |
- // The effectiveDecimalPos is the position the decimal is at or |
- // would be at if there is no decimal. Note that if |
- // decimalPos<0, then digitTotalCount == digitLeftCount + |
- // zeroDigitCount. |
- int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount; |
- UBool isSigDig = (sigDigitCount > 0); |
- setSignificantDigitsUsed(isSigDig); |
- if (isSigDig) { |
- setMinimumSignificantDigits(sigDigitCount); |
- setMaximumSignificantDigits(sigDigitCount + digitRightCount); |
- } else { |
- int32_t minInt = effectiveDecimalPos - digitLeftCount; |
- setMinimumIntegerDigits(minInt); |
- setMaximumIntegerDigits(fUseExponentialNotation |
- ? digitLeftCount + getMinimumIntegerDigits() |
- : NumberFormat::gDefaultMaxIntegerDigits); |
- setMaximumFractionDigits(decimalPos >= 0 |
- ? (digitTotalCount - decimalPos) : 0); |
- setMinimumFractionDigits(decimalPos >= 0 |
- ? (digitLeftCount + zeroDigitCount - decimalPos) : 0); |
- } |
- setGroupingUsed(groupingCount > 0); |
- fGroupingSize = (groupingCount > 0) ? groupingCount : 0; |
- fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) |
- ? groupingCount2 : 0; |
- setMultiplier(multiplier); |
- setDecimalSeparatorAlwaysShown(decimalPos == 0 |
- || decimalPos == digitTotalCount); |
- if (padPos >= 0) { |
- fPadPosition = (EPadPosition) padPos; |
- // To compute the format width, first set up sub0Limit - |
- // sub0Start. Add in prefix/suffix length later. |
- |
- // fFormatWidth = prefix.length() + suffix.length() + |
- // sub0Limit - sub0Start; |
- fFormatWidth = sub0Limit - sub0Start; |
- fPad = padChar; |
- } else { |
- fFormatWidth = 0; |
- } |
- if (roundingPos >= 0) { |
- roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos); |
- if (fRoundingIncrement != NULL) { |
- *fRoundingIncrement = roundingInc; |
- } else { |
- fRoundingIncrement = new DigitList(roundingInc); |
- /* test for NULL */ |
- if (fRoundingIncrement == NULL) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- delete fPosPrefixPattern; |
- delete fPosSuffixPattern; |
- return; |
- } |
- } |
- fRoundingMode = kRoundHalfEven; |
- } else { |
- setRoundingIncrement(0.0); |
- } |
- } else { |
- fNegPrefixPattern = new UnicodeString(prefix); |
- /* test for NULL */ |
- if (fNegPrefixPattern == 0) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- fNegSuffixPattern = new UnicodeString(suffix); |
- /* test for NULL */ |
- if (fNegSuffixPattern == 0) { |
- delete fNegPrefixPattern; |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- } |
+ patternParser.useSymbols(*fSymbols); |
} |
- |
- if (pattern.length() == 0) { |
- delete fNegPrefixPattern; |
- delete fNegSuffixPattern; |
- fNegPrefixPattern = NULL; |
- fNegSuffixPattern = NULL; |
- if (fPosPrefixPattern != NULL) { |
- fPosPrefixPattern->remove(); |
- } else { |
- fPosPrefixPattern = new UnicodeString(); |
- /* test for NULL */ |
- if (fPosPrefixPattern == 0) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- } |
- if (fPosSuffixPattern != NULL) { |
- fPosSuffixPattern->remove(); |
+ 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 { |
- fPosSuffixPattern = new UnicodeString(); |
+ fRoundingIncrement = new DigitList(out.fRoundingIncrement); |
/* test for NULL */ |
- if (fPosSuffixPattern == 0) { |
- delete fPosPrefixPattern; |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
+ if (fRoundingIncrement == NULL) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ return; |
} |
} |
- |
- setMinimumIntegerDigits(0); |
- setMaximumIntegerDigits(kDoubleIntegerDigits); |
- setMinimumFractionDigits(0); |
- setMaximumFractionDigits(kDoubleFractionDigits); |
- |
- fUseExponentialNotation = FALSE; |
- fCurrencySignCount = fgCurrencySignCountZero; |
- setGroupingUsed(FALSE); |
- fGroupingSize = 0; |
- fGroupingSize2 = 0; |
- setMultiplier(1); |
- setDecimalSeparatorAlwaysShown(FALSE); |
- fFormatWidth = 0; |
+ } else { |
setRoundingIncrement(0.0); |
} |
- |
- // If there was no negative pattern, or if the negative pattern is |
- // identical to the positive pattern, then prepend the minus sign to the |
- // positive pattern to form the negative pattern. |
- if (fNegPrefixPattern == NULL || |
- (*fNegPrefixPattern == *fPosPrefixPattern |
- && *fNegSuffixPattern == *fPosSuffixPattern)) { |
- _copy_ptr(&fNegSuffixPattern, fPosSuffixPattern); |
- if (fNegPrefixPattern == NULL) { |
- fNegPrefixPattern = new UnicodeString(); |
- /* test for NULL */ |
- if (fNegPrefixPattern == 0) { |
- status = U_MEMORY_ALLOCATION_ERROR; |
- return; |
- } |
- } else { |
- fNegPrefixPattern->remove(); |
- } |
- fNegPrefixPattern->append(kQuote).append(kPatternMinus) |
- .append(*fPosPrefixPattern); |
+ 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; |
} |
-#ifdef FMT_DEBUG |
- UnicodeString s; |
- s.append((UnicodeString)"\"").append(pattern).append((UnicodeString)"\"->"); |
- debugout(s); |
-#endif |
- |
- // save the pattern |
- fFormatPattern = pattern; |
+ 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); |
} |
@@ -5572,8 +5203,8 @@ void DecimalFormat::setCurrencyInternally(const UChar* theCurrency, |
double rounding = 0.0; |
int32_t frac = 0; |
if (fCurrencySignCount != fgCurrencySignCountZero && isCurr) { |
- rounding = ucurr_getRoundingIncrement(theCurrency, &ec); |
- frac = ucurr_getDefaultFractionDigits(theCurrency, &ec); |
+ rounding = ucurr_getRoundingIncrementForUsage(theCurrency, fCurrencyUsage, &ec); |
+ frac = ucurr_getDefaultFractionDigitsForUsage(theCurrency, fCurrencyUsage, &ec); |
} |
NumberFormat::setCurrency(theCurrency, ec); |
@@ -5609,6 +5240,28 @@ void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { |
#endif |
} |
+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); |
+ } |
+ } |
+} |
+ |
+UCurrencyUsage DecimalFormat::getCurrencyUsage() const { |
+ return fCurrencyUsage; |
+} |
+ |
// Deprecated variant with no UErrorCode parameter |
void DecimalFormat::setCurrency(const UChar* theCurrency) { |
UErrorCode ec = U_ZERO_ERROR; |
@@ -5754,6 +5407,29 @@ DecimalFormat::copyHashForAffixPattern(const Hashtable* source, |
} |
} |
+// this is only overridden to call handleChanged() for fastpath purposes. |
+void |
+DecimalFormat::setGroupingUsed(UBool newValue) { |
+ NumberFormat::setGroupingUsed(newValue); |
+ handleChanged(); |
+} |
+ |
+// 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) { |
@@ -5848,6 +5524,7 @@ DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, |
/* These are stored in fBoolFlags */ |
case UNUM_PARSE_NO_EXPONENT: |
case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: |
+ case UNUM_PARSE_DECIMAL_MARK_REQUIRED: |
if(!fBoolFlags.isValidValue(newValue)) { |
status = U_ILLEGAL_ARGUMENT_ERROR; |
} else { |
@@ -5859,6 +5536,9 @@ DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, |
fScale = newValue; |
break; |
+ case UNUM_CURRENCY_USAGE: |
+ setCurrencyUsage((UCurrencyUsage)newValue, &status); |
+ |
default: |
status = U_UNSUPPORTED_ERROR; |
break; |
@@ -5932,11 +5612,15 @@ int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr, |
/* These are stored in fBoolFlags */ |
case UNUM_PARSE_NO_EXPONENT: |
case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: |
+ case UNUM_PARSE_DECIMAL_MARK_REQUIRED: |
return fBoolFlags.get(attr); |
case UNUM_SCALE: |
return fScale; |
+ case UNUM_CURRENCY_USAGE: |
+ return fCurrencyUsage; |
+ |
default: |
status = U_UNSUPPORTED_ERROR; |
break; |