Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy big decimal parsing #830

Merged
merged 5 commits into from
Oct 24, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions src/main/java/com/fasterxml/jackson/core/base/ParserBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public abstract class ParserBase extends ParserMinimalBase
* Textual number representation captured from input in cases lazy-parsing
* is desired.
*<p>
* As of 2.14 this only applies to {@link BigInteger}.
* As of 2.14, this only applies to {@link BigInteger} and {@link BigDecimal}.
*
* @since 2.14
*/
Expand Down Expand Up @@ -625,7 +625,7 @@ public Number getNumberValue() throws IOException
// And then floating point types. But here optimal type
// needs to be big decimal, to avoid losing any data?
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
return _numberBigDecimal;
return _getBigDecimal();
}
if ((_numTypesValid & NR_FLOAT) != 0) {
return _numberFloat;
Expand Down Expand Up @@ -660,7 +660,7 @@ public Number getNumberValueExact() throws IOException
_parseNumericValue(NR_BIGDECIMAL);
}
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
return _numberBigDecimal;
return _getBigDecimal();
}
if ((_numTypesValid & NR_FLOAT) != 0) {
return _numberFloat;
Expand Down Expand Up @@ -791,7 +791,7 @@ public BigDecimal getDecimalValue() throws IOException
convertNumberToBigDecimal();
}
}
return _numberBigDecimal;
return _getBigDecimal();
}

/*
Expand Down Expand Up @@ -900,7 +900,8 @@ private void _parseSlowFloat(int expType) throws IOException
*/
try {
if (expType == NR_BIGDECIMAL) {
_numberBigDecimal = _textBuffer.contentsAsDecimal();
_numberBigDecimal = null;
_numberString = _textBuffer.contentsAsString();
_numTypesValid = NR_BIGDECIMAL;
} else if (expType == NR_FLOAT) {
_numberFloat = _textBuffer.contentsAsFloat(isEnabled(Feature.USE_FAST_DOUBLE_PARSER));
Expand Down Expand Up @@ -992,11 +993,12 @@ protected void convertNumberToInt() throws IOException
}
_numberInt = (int) _numberDouble;
} else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
if (BD_MIN_INT.compareTo(_numberBigDecimal) > 0
|| BD_MAX_INT.compareTo(_numberBigDecimal) < 0) {
final BigDecimal bigDecimal = _getBigDecimal();
if (BD_MIN_INT.compareTo(bigDecimal) > 0
|| BD_MAX_INT.compareTo(bigDecimal) < 0) {
reportOverflowInt();
}
_numberInt = _numberBigDecimal.intValue();
_numberInt = bigDecimal.intValue();
} else {
_throwInternal();
}
Expand All @@ -1021,11 +1023,12 @@ protected void convertNumberToLong() throws IOException
}
_numberLong = (long) _numberDouble;
} else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
if (BD_MIN_LONG.compareTo(_numberBigDecimal) > 0
|| BD_MAX_LONG.compareTo(_numberBigDecimal) < 0) {
final BigDecimal bigDecimal = _getBigDecimal();
if (BD_MIN_LONG.compareTo(bigDecimal) > 0
|| BD_MAX_LONG.compareTo(bigDecimal) < 0) {
reportOverflowLong();
}
_numberLong = _numberBigDecimal.longValue();
_numberLong = bigDecimal.longValue();
} else {
_throwInternal();
}
Expand All @@ -1036,7 +1039,7 @@ protected void convertNumberToBigInteger() throws IOException
{
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
// here it'll just get truncated, no exceptions thrown
_numberBigInt = _numberBigDecimal.toBigInteger();
_numberBigInt = _getBigDecimal().toBigInteger();
} else if ((_numTypesValid & NR_LONG) != 0) {
_numberBigInt = BigInteger.valueOf(_numberLong);
} else if ((_numTypesValid & NR_INT) != 0) {
Expand All @@ -1058,7 +1061,7 @@ protected void convertNumberToDouble() throws IOException
*/

if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
_numberDouble = _numberBigDecimal.doubleValue();
_numberDouble = _getBigDecimal().doubleValue();
} else if ((_numTypesValid & NR_BIGINT) != 0) {
_numberDouble = _getBigInteger().doubleValue();
} else if ((_numTypesValid & NR_LONG) != 0) {
Expand All @@ -1082,7 +1085,7 @@ protected void convertNumberToFloat() throws IOException
*/

if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
_numberFloat = _numberBigDecimal.floatValue();
_numberFloat = _getBigDecimal().floatValue();
} else if ((_numTypesValid & NR_BIGINT) != 0) {
_numberFloat = _getBigInteger().floatValue();
} else if ((_numTypesValid & NR_LONG) != 0) {
Expand Down Expand Up @@ -1137,6 +1140,23 @@ protected BigInteger _getBigInteger() {
_numberString = null;
return _numberBigInt;
}

/**
* Internal accessor that needs to be used for accessing number value of type
* {@link BigDecimal} which -- as of 2.14 -- is typically lazily parsed.
*
* @since 2.14
*/
protected BigDecimal _getBigDecimal() {
if (_numberBigDecimal != null) {
return _numberBigDecimal;
} else if (_numberString == null) {
throw new IllegalStateException("cannot get BigDecimal from current parser state");
}
_numberBigDecimal = NumberInput.parseBigDecimal(_numberString);
_numberString = null;
return _numberBigDecimal;
}

/*
/**********************************************************
Expand Down Expand Up @@ -1374,4 +1394,5 @@ protected void loadMoreGuaranteed() throws IOException {

// Can't declare as deprecated, for now, but shouldn't be needed
protected void _finishString() throws IOException { }

}