Skip to content

Commit

Permalink
Fix all cases in which we already have an invalid syntax before we ca…
Browse files Browse the repository at this point in the history
…n start parsing Infinity/NaN.
  • Loading branch information
wrandelshofer committed Oct 19, 2024
1 parent 3af4b7b commit 5c97216
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public final long parseFloatingPointLiteral(char[] str, int offset, int length)
digitCount = significandEndIndex - significandStartIndex - 1 - groupingCount;
exponent = integerDigitCount - digitCount;
}
illegal |= digitCount == 0 && significandEndIndex > significandStartIndex;

// Parse exponent number
// ---------------------
Expand Down Expand Up @@ -171,11 +172,16 @@ public final long parseFloatingPointLiteral(char[] str, int offset, int length)

// Parse NaN or Infinity (this occurs rarely)
// ---------------------
if (illegal || index < endIndex
|| digitCount == 0) {
if (!illegal && digitCount == 0) {
return parseNaNOrInfinity(str, index, endIndex, isNegative);
}

// Check if FloatingPointLiteral is complete
// ------------------------
if (illegal || index < endIndex) {
throw new NumberFormatException(SYNTAX_ERROR);
}

// Re-parse significand in case of a potential overflow
// -----------------------------------------------
final boolean isSignificandTruncated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public final long parseFloatingPointLiteral(CharSequence str, int offset, int le
digitCount = significandEndIndex - significandStartIndex - 1 - groupingCount;
exponent = integerDigitCount - digitCount;
}
illegal |= digitCount == 0 && significandEndIndex > significandStartIndex;

// Parse exponent number
// ---------------------
Expand Down Expand Up @@ -173,11 +174,16 @@ public final long parseFloatingPointLiteral(CharSequence str, int offset, int le

// Parse NaN or Infinity (this occurs rarely)
// ---------------------
if (illegal || index < endIndex
|| digitCount == 0) {
if (!illegal && digitCount == 0) {
return parseNaNOrInfinity(str, index, endIndex, isNegative);
}

// Check if FloatingPointLiteral is complete
// ------------------------
if (illegal || index < endIndex) {
throw new NumberFormatException(SYNTAX_ERROR);
}

// Re-parse significand in case of a potential overflow
// -----------------------------------------------
final boolean isSignificandTruncated;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,15 @@ private static int skipWhitespace(byte[] str, int index, int endIndex) {
* See {@link JavaDoubleParser} for the grammar of
* {@code DecimalFloatingPointLiteral} and {@code DecSignificand}.
*
* @param str a string
* @param index start index inclusive of the {@code DecimalFloatingPointLiteralWithWhiteSpace}
* @param endIndex end index (exclusive)
* @param isNegative true if the float value is negative
* @param hasLeadingZero true if we have consumed the optional leading zero
* @param str a string
* @param index start index inclusive of the {@code DecimalFloatingPointLiteralWithWhiteSpace}
* @param endIndex end index (exclusive)
* @param isNegative true if the float value is negative
* @return the bit pattern of the parsed value, if the input is legal;
* otherwise, {@code -1L}.
*/

private long parseDecFloatLiteral(byte[] str, int index, int startIndex, int endIndex, boolean isNegative, boolean hasLeadingZero) {
private long parseDecFloatLiteral(byte[] str, int index, int startIndex, int endIndex, boolean isNegative) {
// Parse significand
// -----------------
// Note: a multiplication by a constant is cheaper than an
Expand Down Expand Up @@ -108,6 +107,7 @@ private long parseDecFloatLiteral(byte[] str, int index, int startIndex, int end
digitCount = index - significandStartIndex - 1;
exponent = integerDigitCount - digitCount;
}
illegal |= digitCount == 0 && significandEndIndex > significandStartIndex;

// Parse exponent number
// ---------------------
Expand All @@ -134,6 +134,13 @@ private long parseDecFloatLiteral(byte[] str, int index, int startIndex, int end
exponent += expNumber;
}


// Parse NaN or Infinity (this occurs rarely)
// ---------------------
if (!illegal && digitCount == 0) {
return parseNaNOrInfinity(str, index, endIndex, isNegative);
}

// Skip optional FloatTypeSuffix
// long-circuit-or is faster than short-circuit-or
// ------------------------
Expand All @@ -144,11 +151,8 @@ private long parseDecFloatLiteral(byte[] str, int index, int startIndex, int end
// Skip trailing whitespace and check if FloatingPointLiteral is complete
// ------------------------
index = skipWhitespace(str, index, endIndex);
if (illegal || index < endIndex
|| !hasLeadingZero && digitCount == 0) {
// Parse NaN or Infinity (this occurs rarely)
// ---------------------
return parseNaNOrInfinity(str, index, endIndex, isNegative);
if (illegal || index < endIndex) {
throw new NumberFormatException(SYNTAX_ERROR);
}

// Re-parse significand in case of a potential overflow
Expand Down Expand Up @@ -228,9 +232,10 @@ public long parseFloatingPointLiteral(byte[] str, int offset, int length) {
if ((ch | 0x20) == 'x') {// equals ignore case
return parseHexFloatingPointLiteral(str, index + 1, offset, endIndex, isNegative);
}
index--;//push the leading zero back
}

return parseDecFloatLiteral(str, index, offset, endIndex, isNegative, hasLeadingZero);
return parseDecFloatLiteral(str, index, offset, endIndex, isNegative);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,15 @@ private static int skipWhitespace(char[] str, int index, int endIndex) {
* See {@link JavaDoubleParser} for the grammar of
* {@code DecimalFloatingPointLiteral} and {@code DecSignificand}.
*
* @param str a string
* @param index the current index
* @param startIndex start index inclusive of the {@code DecimalFloatingPointLiteralWithWhiteSpace}
* @param endIndex end index (exclusive)
* @param isNegative true if the float value is negative
* @param hasLeadingZero true if we have consumed the optional leading zero
* @param str a string
* @param index the current index
* @param startIndex start index inclusive of the {@code DecimalFloatingPointLiteralWithWhiteSpace}
* @param endIndex end index (exclusive)
* @param isNegative true if the float value is negative
* @return the bit pattern of the parsed value, if the input is legal;
* otherwise, {@code -1L}.
*/
private long parseDecFloatLiteral(char[] str, int index, int startIndex, int endIndex, boolean isNegative, boolean hasLeadingZero) {
private long parseDecFloatLiteral(char[] str, int index, int startIndex, int endIndex, boolean isNegative) {
// Parse significand
// -----------------
// Note: a multiplication by a constant is cheaper than an
Expand Down Expand Up @@ -111,6 +110,7 @@ private long parseDecFloatLiteral(char[] str, int index, int startIndex, int end
digitCount = index - significandStartIndex - 1;
exponent = integerDigitCount - digitCount;
}
illegal |= digitCount == 0 && significandEndIndex > significandStartIndex;

// Parse exponent number
// ---------------------
Expand All @@ -137,6 +137,12 @@ private long parseDecFloatLiteral(char[] str, int index, int startIndex, int end
exponent += expNumber;
}

// Parse NaN or Infinity (this occurs rarely)
// ---------------------
if (!illegal && digitCount == 0) {
return parseNaNOrInfinity(str, index, endIndex, isNegative);
}

// Skip optional FloatTypeSuffix
// long-circuit-or is faster than short-circuit-or
// ------------------------
Expand All @@ -147,11 +153,8 @@ private long parseDecFloatLiteral(char[] str, int index, int startIndex, int end
// Skip trailing whitespace and check if FloatingPointLiteral is complete
// ------------------------
index = skipWhitespace(str, index, endIndex);
if (illegal || index < endIndex
|| !hasLeadingZero && digitCount == 0) {
// Parse NaN or Infinity (this occurs rarely)
// ---------------------
return parseNaNOrInfinity(str, index, endIndex, isNegative);
if (illegal || index < endIndex) {
throw new NumberFormatException(SYNTAX_ERROR);
}

// Re-parse significand in case of a potential overflow
Expand Down Expand Up @@ -230,9 +233,10 @@ public long parseFloatingPointLiteral(char[] str, int offset, int length) {
if ((ch | 0x20) == 'x') {// equals ignore case
return parseHexFloatLiteral(str, index + 1, offset, endIndex, isNegative);
}
index--;//push the leading zero back
}

return parseDecFloatLiteral(str, index, offset, endIndex, isNegative, hasLeadingZero);
return parseDecFloatLiteral(str, index, offset, endIndex, isNegative);
}

/**
Expand Down Expand Up @@ -376,35 +380,35 @@ private long parseHexFloatLiteral(

private long parseNaNOrInfinity(char[] str, int index, int endIndex, boolean isNegative) {
if (index < endIndex) {
if (str[index] == 'N') {
if (index + 2 < endIndex
// && str[index] == 'N'
&& str[index + 1] == 'a'
&& str[index + 2] == 'N') {

index = skipWhitespace(str, index + 3, endIndex);
if (index == endIndex) {
return nan();
if (str[index] == 'N') {
if (index + 2 < endIndex
// && str[index] == 'N'
&& str[index + 1] == 'a'
&& str[index + 2] == 'N') {

index = skipWhitespace(str, index + 3, endIndex);
if (index == endIndex) {
return nan();
}
}
}
} else {
if (index + 7 < endIndex
&& str[index] == 'I'
&& str[index + 1] == 'n'
&& str[index + 2] == 'f'
&& str[index + 3] == 'i'
&& str[index + 4] == 'n'
&& str[index + 5] == 'i'
&& str[index + 6] == 't'
&& str[index + 7] == 'y'
) {
index = skipWhitespace(str, index + 8, endIndex);
if (index == endIndex) {
return isNegative ? negativeInfinity() : positiveInfinity();
} else {
if (index + 7 < endIndex
&& str[index] == 'I'
&& str[index + 1] == 'n'
&& str[index + 2] == 'f'
&& str[index + 3] == 'i'
&& str[index + 4] == 'n'
&& str[index + 5] == 'i'
&& str[index + 6] == 't'
&& str[index + 7] == 'y'
) {
index = skipWhitespace(str, index + 8, endIndex);
if (index == endIndex) {
return isNegative ? negativeInfinity() : positiveInfinity();
}
}
}
}
}
throw new NumberFormatException(SYNTAX_ERROR);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,15 @@ private static int skipWhitespace(CharSequence str, int index, int endIndex) {
* See {@link JavaDoubleParser} for the grammar of
* {@code DecimalFloatingPointLiteral} and {@code DecSignificand}.
*
* @param str a string
* @param index the current index
* @param startIndex start index inclusive of the {@code DecimalFloatingPointLiteralWithWhiteSpace}
* @param endIndex end index (exclusive)
* @param isNegative true if the float value is negative
* @param hasLeadingZero true if we have consumed the optional leading zero
* @param str a string
* @param index the current index
* @param startIndex start index inclusive of the {@code DecimalFloatingPointLiteralWithWhiteSpace}
* @param endIndex end index (exclusive)
* @param isNegative true if the float value is negative
* @return the bit pattern of the parsed value, if the input is legal;
* otherwise, {@code -1L}.
*/
private long parseDecFloatLiteral(CharSequence str, int index, int startIndex, int endIndex, boolean isNegative, boolean hasLeadingZero) {
private long parseDecFloatLiteral(CharSequence str, int index, int startIndex, int endIndex, boolean isNegative) {
// Parse significand
// -----------------
// Note: a multiplication by a constant is cheaper than an
Expand Down Expand Up @@ -108,6 +107,7 @@ private long parseDecFloatLiteral(CharSequence str, int index, int startIndex, i
digitCount = index - significandStartIndex - 1;
exponent = integerDigitCount - digitCount;
}
illegal |= digitCount == 0 && significandEndIndex > significandStartIndex;

// Parse exponent number
// ---------------------
Expand All @@ -134,6 +134,12 @@ private long parseDecFloatLiteral(CharSequence str, int index, int startIndex, i
exponent += expNumber;
}

// Parse NaN or Infinity (this occurs rarely)
// ---------------------
if (!illegal && digitCount == 0) {
return parseNaNOrInfinity(str, index, endIndex, isNegative);
}

// Skip optional FloatTypeSuffix
// long-circuit-or is faster than short-circuit-or
// ------------------------
Expand All @@ -144,11 +150,8 @@ private long parseDecFloatLiteral(CharSequence str, int index, int startIndex, i
// Skip trailing whitespace and check if FloatingPointLiteral is complete
// ------------------------
index = skipWhitespace(str, index, endIndex);
if (illegal || index < endIndex
|| !hasLeadingZero && digitCount == 0) {
// Parse NaN or Infinity (this occurs rarely)
// ---------------------
return parseNaNOrInfinity(str, index, endIndex, isNegative);
if (illegal || index < endIndex) {
throw new NumberFormatException(SYNTAX_ERROR);
}

// Re-parse significand in case of a potential overflow
Expand Down Expand Up @@ -227,9 +230,10 @@ public final long parseFloatingPointLiteral(CharSequence str, int offset, int le
if ((ch | 0x20) == 'x') {// equals ignore case
return parseHexFloatLiteral(str, index + 1, offset, endIndex, isNegative);
}
index--;//push the leading zero back
}

return parseDecFloatLiteral(str, index, offset, endIndex, isNegative, hasLeadingZero);
return parseDecFloatLiteral(str, index, offset, endIndex, isNegative);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import static ch.randelshofer.fastdoubleparser.JavaDoubleTestDataFactory.createDataForLegalDecStrings;
import static ch.randelshofer.fastdoubleparser.JavaDoubleTestDataFactory.createFloatTestDataForInputClassesInMethodParseFloatValue;
import static ch.randelshofer.fastdoubleparser.JavaDoubleTestDataFactory.createLongRunningDoubleTestData;
import static ch.randelshofer.fastdoubleparser.JavaDoubleTestDataFactory.createTestDataForInfinity;
import static ch.randelshofer.fastdoubleparser.JavaDoubleTestDataFactory.createTestDataForNaN;
import static ch.randelshofer.fastdoubleparser.JavaFloatTestDataFactory.createTestDataForInfinity;
import static ch.randelshofer.fastdoubleparser.JavaFloatTestDataFactory.createTestDataForNaN;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,13 @@
import static ch.randelshofer.fastdoubleparser.FloatValueTestDataFactory.createDataForDoubleHexadecimalLimits;
import static ch.randelshofer.fastdoubleparser.FloatValueTestDataFactory.createDataForSignificandDigitsInputClasses;
import static ch.randelshofer.fastdoubleparser.FloatValueTestDataFactory.createDataWithVeryLongInputStrings;
import static ch.randelshofer.fastdoubleparser.JavaFloatTestDataFactory.createTestDataForInfinity;
import static ch.randelshofer.fastdoubleparser.JavaFloatTestDataFactory.createTestDataForNaN;

public abstract class JavaDoubleTestDataFactory {


public static List<NumberTestData> createTestDataForNaN() {
return Arrays.asList(
new NumberTestData("NaN", Double.NaN),
new NumberTestData("+NaN", Double.NaN),
new NumberTestData("-NaN", Double.NaN),
new NumberTestData("NaNf"),
new NumberTestData("+NaNd"),
new NumberTestData("-NaNF"),
new NumberTestData("+-NaND"),
new NumberTestData("NaNInfinity"),
new NumberTestData("nan")
);
}

public static List<NumberTestData> createTestDataForInfinity() {
return Arrays.asList(
new NumberTestData("Infinity", Double.POSITIVE_INFINITY),
new NumberTestData("+Infinity", Double.POSITIVE_INFINITY),
new NumberTestData("-Infinity", Double.NEGATIVE_INFINITY),
new NumberTestData("Infinit"),
new NumberTestData("+Infinityf"),
new NumberTestData("-InfinityF"),
new NumberTestData("+Infinityd"),
new NumberTestData("+-InfinityD"),
new NumberTestData("+InfinityNaN"),
new NumberTestData("infinity")
);
}

/**
* ALl these strings must throw a {@link java.lang.NumberFormatException}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ public static List<NumberTestData> createTestDataForInfinity() {
new NumberTestData("+Infinity", Double.POSITIVE_INFINITY),
new NumberTestData("-Infinity", Double.NEGATIVE_INFINITY),
new NumberTestData("Infinit"),
new NumberTestData("+ Infinity"),
new NumberTestData("+.Infinity"),
new NumberTestData("eInfinity"),
new NumberTestData("5Infinity"),
new NumberTestData("0Infinity"),
new NumberTestData(".Infinity"),
new NumberTestData("+Infinityf"),
new NumberTestData("-InfinityF"),
new NumberTestData("+Infinityd"),
Expand Down

0 comments on commit 5c97216

Please sign in to comment.