Add support of special values to DecimalFormat.parse

This commit is contained in:
Alexey Andreev 2015-06-14 21:29:31 +03:00
parent ea49c9de9b
commit 69ac393068
2 changed files with 51 additions and 5 deletions

View File

@ -219,6 +219,7 @@ public class TDecimalFormat extends TNumberFormat {
boolean fractionalPart = false; boolean fractionalPart = false;
boolean positive = true; boolean positive = true;
// Find prefix
String negPrefix = getNegativePrefix(); String negPrefix = getNegativePrefix();
String posPrefix = getPositivePrefix(); String posPrefix = getPositivePrefix();
if (string.regionMatches(index, negPrefix, 0, negPrefix.length())) { if (string.regionMatches(index, negPrefix, 0, negPrefix.length())) {
@ -231,6 +232,23 @@ public class TDecimalFormat extends TNumberFormat {
return null; return null;
} }
// Find suffix
String suffix = positive ? getPositiveSuffix() : getNegativeSuffix();
if (suffix == null) {
suffix = getPositiveSuffix();
}
// Check for infinity
if (string.regionMatches(index, symbols.getInfinity(), 0, symbols.getInfinity().length())) {
index += symbols.getInfinity().length();
if (suffix != null && !string.regionMatches(index, suffix, 0, suffix.length())) {
position.setErrorIndex(index);
return null;
}
return positive ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
}
// Parse mantissa and exponent
while (index < string.length()) { while (index < string.length()) {
char c = string.charAt(index); char c = string.charAt(index);
int digit = c - symbols.getZeroDigit(); int digit = c - symbols.getZeroDigit();
@ -309,22 +327,32 @@ public class TDecimalFormat extends TNumberFormat {
} }
} }
// If decimal separator without fractional part is not allowed, report error
if (fracSize == 0 && fractionalPart && !isDecimalSeparatorAlwaysShown()) { if (fracSize == 0 && fractionalPart && !isDecimalSeparatorAlwaysShown()) {
position.setErrorIndex(index); position.setErrorIndex(index);
return null; return null;
} }
String suffix = positive ? getPositiveSuffix() : getNegativeSuffix(); // Check suffix
if (suffix == null) {
suffix = getPositiveSuffix();
}
if (suffix != null && !string.regionMatches(index, suffix, 0, suffix.length())) { if (suffix != null && !string.regionMatches(index, suffix, 0, suffix.length())) {
position.setErrorIndex(index); position.setErrorIndex(index);
return null; return null;
} }
// Advance parse position
position.setIndex(index); position.setIndex(index);
// Apply multiplier
if (multiplier != 1) {
int multiplierDigits = fastLn10(multiplier);
if (POW10_INT_ARRAY[multiplierDigits] != multiplier) {
mantissa /= multiplier;
} else {
exponent -= multiplierDigits;
}
}
// Apply exponent
exponent += shift - fracSize; exponent += shift - fracSize;
if (exponent > 0 && exponent < POW10_ARRAY.length) { if (exponent > 0 && exponent < POW10_ARRAY.length) {
if (mantissa < Long.MAX_VALUE / POW10_ARRAY[exponent]) { if (mantissa < Long.MAX_VALUE / POW10_ARRAY[exponent]) {
@ -338,10 +366,13 @@ public class TDecimalFormat extends TNumberFormat {
} }
} }
// Expose result
if (mantissa == 0 && !positive) {
return -0.0;
}
if (exponent == 0) { if (exponent == 0) {
return positive ? mantissa : -mantissa; return positive ? mantissa : -mantissa;
} }
double result = TDouble.decimalExponent(exponent) * mantissa; double result = TDouble.decimalExponent(exponent) * mantissa;
return positive ? result : -result; return positive ? result : -result;
} }

View File

@ -76,6 +76,21 @@ public class DecimalFormatParseTest {
} }
} }
@Test
public void parsesPercent() throws ParseException {
DecimalFormat format = createFormat("0.#E0%");
assertEquals(0.23, format.parse("23%").doubleValue(), 0.001);
assertEquals(23L, format.parse("2300%"));
}
@Test
public void parsesSpecial() throws ParseException {
DecimalFormat format = createFormat("0.#E0");
assertEquals(Double.POSITIVE_INFINITY, format.parse(""));
assertEquals(Double.NEGATIVE_INFINITY, format.parse("-∞"));
assertEquals(-0.0, format.parse("-0"));
}
private DecimalFormat createFormat(String format) { private DecimalFormat createFormat(String format) {
return new DecimalFormat(format, symbols); return new DecimalFormat(format, symbols);
} }