Skip to content

Commit 9d7f14b

Browse files
authored
Lazy big decimal parsing (#830)
1 parent 7d3e902 commit 9d7f14b

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

src/main/java/com/fasterxml/jackson/core/base/ParserBase.java

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ public abstract class ParserBase extends ParserMinimalBase
207207
* Textual number representation captured from input in cases lazy-parsing
208208
* is desired.
209209
*<p>
210-
* As of 2.14 this only applies to {@link BigInteger}.
210+
* As of 2.14, this only applies to {@link BigInteger} and {@link BigDecimal}.
211211
*
212212
* @since 2.14
213213
*/
@@ -625,7 +625,7 @@ public Number getNumberValue() throws IOException
625625
// And then floating point types. But here optimal type
626626
// needs to be big decimal, to avoid losing any data?
627627
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
628-
return _numberBigDecimal;
628+
return _getBigDecimal();
629629
}
630630
if ((_numTypesValid & NR_FLOAT) != 0) {
631631
return _numberFloat;
@@ -660,7 +660,7 @@ public Number getNumberValueExact() throws IOException
660660
_parseNumericValue(NR_BIGDECIMAL);
661661
}
662662
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
663-
return _numberBigDecimal;
663+
return _getBigDecimal();
664664
}
665665
if ((_numTypesValid & NR_FLOAT) != 0) {
666666
return _numberFloat;
@@ -791,7 +791,7 @@ public BigDecimal getDecimalValue() throws IOException
791791
convertNumberToBigDecimal();
792792
}
793793
}
794-
return _numberBigDecimal;
794+
return _getBigDecimal();
795795
}
796796

797797
/*
@@ -900,7 +900,8 @@ private void _parseSlowFloat(int expType) throws IOException
900900
*/
901901
try {
902902
if (expType == NR_BIGDECIMAL) {
903-
_numberBigDecimal = _textBuffer.contentsAsDecimal();
903+
_numberBigDecimal = null;
904+
_numberString = _textBuffer.contentsAsString();
904905
_numTypesValid = NR_BIGDECIMAL;
905906
} else if (expType == NR_FLOAT) {
906907
_numberFloat = _textBuffer.contentsAsFloat(isEnabled(Feature.USE_FAST_DOUBLE_PARSER));
@@ -992,11 +993,12 @@ protected void convertNumberToInt() throws IOException
992993
}
993994
_numberInt = (int) _numberDouble;
994995
} else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
995-
if (BD_MIN_INT.compareTo(_numberBigDecimal) > 0
996-
|| BD_MAX_INT.compareTo(_numberBigDecimal) < 0) {
996+
final BigDecimal bigDecimal = _getBigDecimal();
997+
if (BD_MIN_INT.compareTo(bigDecimal) > 0
998+
|| BD_MAX_INT.compareTo(bigDecimal) < 0) {
997999
reportOverflowInt();
9981000
}
999-
_numberInt = _numberBigDecimal.intValue();
1001+
_numberInt = bigDecimal.intValue();
10001002
} else {
10011003
_throwInternal();
10021004
}
@@ -1021,11 +1023,12 @@ protected void convertNumberToLong() throws IOException
10211023
}
10221024
_numberLong = (long) _numberDouble;
10231025
} else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1024-
if (BD_MIN_LONG.compareTo(_numberBigDecimal) > 0
1025-
|| BD_MAX_LONG.compareTo(_numberBigDecimal) < 0) {
1026+
final BigDecimal bigDecimal = _getBigDecimal();
1027+
if (BD_MIN_LONG.compareTo(bigDecimal) > 0
1028+
|| BD_MAX_LONG.compareTo(bigDecimal) < 0) {
10261029
reportOverflowLong();
10271030
}
1028-
_numberLong = _numberBigDecimal.longValue();
1031+
_numberLong = bigDecimal.longValue();
10291032
} else {
10301033
_throwInternal();
10311034
}
@@ -1036,7 +1039,7 @@ protected void convertNumberToBigInteger() throws IOException
10361039
{
10371040
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
10381041
// here it'll just get truncated, no exceptions thrown
1039-
_numberBigInt = _numberBigDecimal.toBigInteger();
1042+
_numberBigInt = _getBigDecimal().toBigInteger();
10401043
} else if ((_numTypesValid & NR_LONG) != 0) {
10411044
_numberBigInt = BigInteger.valueOf(_numberLong);
10421045
} else if ((_numTypesValid & NR_INT) != 0) {
@@ -1058,7 +1061,7 @@ protected void convertNumberToDouble() throws IOException
10581061
*/
10591062

10601063
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1061-
_numberDouble = _numberBigDecimal.doubleValue();
1064+
_numberDouble = _getBigDecimal().doubleValue();
10621065
} else if ((_numTypesValid & NR_BIGINT) != 0) {
10631066
_numberDouble = _getBigInteger().doubleValue();
10641067
} else if ((_numTypesValid & NR_LONG) != 0) {
@@ -1082,7 +1085,7 @@ protected void convertNumberToFloat() throws IOException
10821085
*/
10831086

10841087
if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1085-
_numberFloat = _numberBigDecimal.floatValue();
1088+
_numberFloat = _getBigDecimal().floatValue();
10861089
} else if ((_numTypesValid & NR_BIGINT) != 0) {
10871090
_numberFloat = _getBigInteger().floatValue();
10881091
} else if ((_numTypesValid & NR_LONG) != 0) {
@@ -1137,6 +1140,23 @@ protected BigInteger _getBigInteger() {
11371140
_numberString = null;
11381141
return _numberBigInt;
11391142
}
1143+
1144+
/**
1145+
* Internal accessor that needs to be used for accessing number value of type
1146+
* {@link BigDecimal} which -- as of 2.14 -- is typically lazily parsed.
1147+
*
1148+
* @since 2.14
1149+
*/
1150+
protected BigDecimal _getBigDecimal() {
1151+
if (_numberBigDecimal != null) {
1152+
return _numberBigDecimal;
1153+
} else if (_numberString == null) {
1154+
throw new IllegalStateException("cannot get BigDecimal from current parser state");
1155+
}
1156+
_numberBigDecimal = NumberInput.parseBigDecimal(_numberString);
1157+
_numberString = null;
1158+
return _numberBigDecimal;
1159+
}
11401160

11411161
/*
11421162
/**********************************************************
@@ -1374,4 +1394,5 @@ protected void loadMoreGuaranteed() throws IOException {
13741394

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

0 commit comments

Comments
 (0)