提交 7d2c99ae 编写于 作者: N nishjain

8165466: DecimalFormat percentage format can contain unexpected %

Reviewed-by: okutsu, peytoia
上级 24fae5dc
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -968,7 +968,7 @@ public class DecimalFormat extends NumberFormat {
* Decimal : min = 0. max = 3.
*
*/
private void checkAndSetFastPathStatus() {
private boolean checkAndSetFastPathStatus() {
boolean fastPathWasOn = isFastPath;
......@@ -998,12 +998,27 @@ public class DecimalFormat extends NumberFormat {
} else
isFastPath = false;
resetFastPathData(fastPathWasOn);
fastPathCheckNeeded = false;
/*
* Returns true after successfully checking the fast path condition and
* setting the fast path data. The return value is used by the
* fastFormat() method to decide whether to call the resetFastPathData
* method to reinitialize fast path data or is it already initialized
* in this method.
*/
return true;
}
private void resetFastPathData(boolean fastPathWasOn) {
// Since some instance properties may have changed while still falling
// in the fast-path case, we need to reinitialize fastPathData anyway.
if (isFastPath) {
// We need to instantiate fastPathData if not already done.
if (fastPathData == null)
if (fastPathData == null) {
fastPathData = new FastPathData();
}
// Sets up the locale specific constants used when formatting.
// '0' is our default representation of zero.
......@@ -1011,22 +1026,27 @@ public class DecimalFormat extends NumberFormat {
fastPathData.groupingChar = symbols.getGroupingSeparator();
// Sets up fractional constants related to currency/decimal pattern.
fastPathData.fractionalMaxIntBound = (isCurrencyFormat) ? 99 : 999;
fastPathData.fractionalScaleFactor = (isCurrencyFormat) ? 100.0d : 1000.0d;
fastPathData.fractionalMaxIntBound = (isCurrencyFormat)
? 99 : 999;
fastPathData.fractionalScaleFactor = (isCurrencyFormat)
? 100.0d : 1000.0d;
// Records the need for adding prefix or suffix
fastPathData.positiveAffixesRequired =
(positivePrefix.length() != 0) || (positiveSuffix.length() != 0);
fastPathData.negativeAffixesRequired =
(negativePrefix.length() != 0) || (negativeSuffix.length() != 0);
fastPathData.positiveAffixesRequired
= (positivePrefix.length() != 0)
|| (positiveSuffix.length() != 0);
fastPathData.negativeAffixesRequired
= (negativePrefix.length() != 0)
|| (negativeSuffix.length() != 0);
// Creates a cached char container for result, with max possible size.
int maxNbIntegralDigits = 10;
int maxNbGroups = 3;
int containerSize =
Math.max(positivePrefix.length(), negativePrefix.length()) +
maxNbIntegralDigits + maxNbGroups + 1 + maximumFractionDigits +
Math.max(positiveSuffix.length(), negativeSuffix.length());
int containerSize
= Math.max(positivePrefix.length(), negativePrefix.length())
+ maxNbIntegralDigits + maxNbGroups + 1
+ maximumFractionDigits
+ Math.max(positiveSuffix.length(), negativeSuffix.length());
fastPathData.fastPathContainer = new char[containerSize];
......@@ -1038,17 +1058,18 @@ public class DecimalFormat extends NumberFormat {
// Sets up fixed index positions for integral and fractional digits.
// Sets up decimal point in cached result container.
int longestPrefixLength =
Math.max(positivePrefix.length(), negativePrefix.length());
int decimalPointIndex =
maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
int longestPrefixLength
= Math.max(positivePrefix.length(),
negativePrefix.length());
int decimalPointIndex
= maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
fastPathData.integralLastIndex = decimalPointIndex - 1;
fastPathData.integralLastIndex = decimalPointIndex - 1;
fastPathData.fractionalFirstIndex = decimalPointIndex + 1;
fastPathData.fastPathContainer[decimalPointIndex] =
isCurrencyFormat ?
symbols.getMonetaryDecimalSeparator() :
symbols.getDecimalSeparator();
fastPathData.fastPathContainer[decimalPointIndex]
= isCurrencyFormat
? symbols.getMonetaryDecimalSeparator()
: symbols.getDecimalSeparator();
} else if (fastPathWasOn) {
// Previous state was fast-path and is no more.
......@@ -1059,8 +1080,6 @@ public class DecimalFormat extends NumberFormat {
fastPathData.charsPositivePrefix = null;
fastPathData.charsNegativePrefix = null;
}
fastPathCheckNeeded = false;
}
/**
......@@ -1554,9 +1573,11 @@ public class DecimalFormat extends NumberFormat {
* @return the formatted result for {@code d} as a string.
*/
String fastFormat(double d) {
boolean isDataSet = false;
// (Re-)Evaluates fast-path status if needed.
if (fastPathCheckNeeded)
checkAndSetFastPathStatus();
if (fastPathCheckNeeded) {
isDataSet = checkAndSetFastPathStatus();
}
if (!isFastPath )
// DecimalFormat instance is not in a fast-path state.
......@@ -1580,9 +1601,21 @@ public class DecimalFormat extends NumberFormat {
if (d > MAX_INT_AS_DOUBLE)
// Filters out values that are outside expected fast-path range
return null;
else
else {
if (!isDataSet) {
/*
* If the fast path data is not set through
* checkAndSetFastPathStatus() and fulfil the
* fast path conditions then reset the data
* directly through resetFastPathData()
*/
resetFastPathData(isFastPath);
}
fastDoubleFormat(d, negative);
}
// Returns a new string from updated fastPathContainer.
return new String(fastPathData.fastPathContainer,
fastPathData.firstUsedIndex,
......
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8165466
* @summary Checks the subsequent function calls of the DecimalFormat.format()
* method in which the minimumFractionDigit is set to 0 and one of
* the format() call include formatting of the number with zero
* fraction value e.g. 0.00, 9.00
*/
import java.text.DecimalFormat;
import java.util.Locale;
public class Bug8165466 {
public static void main(String[] args) {
DecimalFormat nf = (DecimalFormat) DecimalFormat
.getPercentInstance(Locale.US);
nf.setMaximumFractionDigits(3);
nf.setMinimumFractionDigits(0);
nf.setMultiplier(1);
double d = 0.005678;
String result = nf.format(d);
if (!result.equals("0.006%")) {
throw new RuntimeException("[Failed while formatting the double"
+ " value: " + d + " Expected: 0.006%, Found: " + result
+ "]");
}
d = 0.00;
result = nf.format(d);
if (!result.equals("0%")) {
throw new RuntimeException("[Failed while formatting the double"
+ " value: " + d + " Expected: 0%, Found: " + result
+ "]");
}
d = 0.005678;
result = nf.format(d);
if (!result.equals("0.006%")) {
throw new RuntimeException("[Failed while formatting the double"
+ " value: " + d + " Expected: 0.006%, Found: " + result
+ "]");
}
//checking with the non zero value
d = 0.005678;
result = nf.format(d);
if (!result.equals("0.006%")) {
throw new RuntimeException("[Failed while formatting the double"
+ " value: " + d + " Expected: 0.006%, Found: " + result
+ "]");
}
d = 9.00;
result = nf.format(d);
if (!result.equals("9%")) {
throw new RuntimeException("[Failed while formatting the double"
+ " value: " + d + " Expected: 9%, Found: " + result
+ "]");
}
d = 0.005678;
result = nf.format(d);
if (!result.equals("0.006%")) {
throw new RuntimeException("[Failed while formatting the double"
+ " value: " + d + " Expected: 0.006%, Found: " + result
+ "]");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册